Skip to content

Commit 083efc6

Browse files
Added categorical data example (#932)
* Added categorical data example * Added description and changed code slightly
1 parent d3e8ed0 commit 083efc6

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44
### Added
5+
- Added categorical data example
56
- Added printProblem to print problem to stdout
67
- Added stage checks to presolve, freereoptsolve, freetransform
78
- Added primal_dual_evolution recipe and a plot recipe
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
This example shows how one can optimize a model with categorical data by converting it into integers.
3+
4+
There are three employees (Alice, Bob, Charlie) and three shifts. Each shift is assigned an integer:
5+
6+
Morning - 0
7+
Afternoon - 1
8+
Night - 2
9+
10+
The employees have availabilities (e.g. Alice can only work in the Morning and Afternoon), and different
11+
salary demands. These constraints, and an additional one stipulating that every shift must be covered,
12+
allows us to model a MIP with the objective of minimizing the money spent on salary.
13+
"""
14+
15+
from pyscipopt import Model
16+
17+
# Define categorical data
18+
shift_to_int = {"Morning": 0, "Afternoon": 1, "Night": 2}
19+
employees = ["Alice", "Bob", "Charlie"]
20+
21+
# Employee availability
22+
availability = {
23+
"Alice": ["Morning", "Afternoon"],
24+
"Bob": ["Afternoon", "Night"],
25+
"Charlie": ["Morning", "Night"]
26+
}
27+
28+
# Transform availability into integer values
29+
availability_int = {}
30+
for emp, available_shifts in availability.items():
31+
availability_int[emp] = [shift_to_int[shift] for shift in available_shifts]
32+
33+
34+
# Employees have different salary demands
35+
cost = {
36+
"Alice": [2,4,1],
37+
"Bob": [3,2,7],
38+
"Charlie": [3,3,3]
39+
}
40+
41+
# Create the model
42+
model = Model("Shift Assignment")
43+
44+
# x[e, s] = 1 if employee e is assigned to shift s
45+
x = {}
46+
for e in employees:
47+
for s in shift_to_int.values():
48+
x[e, s] = model.addVar(vtype="B", name=f"x({e},{s})")
49+
50+
# Each shift must be assigned to exactly one employee
51+
for s in shift_to_int.values():
52+
model.addCons(sum(x[e, s] for e in employees) == 1)
53+
54+
# Employees can only work shifts they are available for
55+
for e in employees:
56+
for s in shift_to_int.values():
57+
if s not in availability_int[e]:
58+
model.addCons(x[e, s] == 0)
59+
60+
# Minimize shift assignment cost
61+
model.setObjective(
62+
sum(cost[e][s]*x[e, s] for e in employees for s in shift_to_int.values()), "minimize"
63+
)
64+
65+
# Solve the problem
66+
model.optimize()
67+
68+
# Display the results
69+
print("\nOptimal Shift Assignment:")
70+
for e in employees:
71+
for s, s_id in shift_to_int.items():
72+
if model.getVal(x[e, s_id]) > 0.5:
73+
print("%s is assigned to %s" % (e, s))

0 commit comments

Comments
 (0)