Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/cp/constraints/target_working_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,14 @@ def create(
if employee.hidden:
target_working_time = round(40 * 60 * 4.35)
else:
available_days = set(range(1, len(self._days) + 1)) - (
set(employee.vacation_days) | set(employee._forbidden_days) # pyright: ignore[reportPrivateUsage]
)
unvavailable_days = set(employee.vacation_days) | set(employee._forbidden_days) # pyright: ignore[reportPrivateUsage]
factor = 1 - len(unvavailable_days) / len(self._days)

# maybe it effects the tool that working_time_domain is probably MUCH larger than
# target_working_time - TOLERANCE_LESS <= working_time_variable <= target_working_time + TOLERANCE_MORE
target_working_time = round(
max(
employee.target_working_time * len(available_days) / len(self._days)
- employee.actual_working_time,
employee.target_working_time * factor - employee.actual_working_time,
0,
)
)
Expand Down
1 change: 1 addition & 0 deletions src/web/process_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def employee_to_dict(emp: Employee):
"vacation_days": emp.vacation_days,
"vacation_shifts": emp.vacation_shifts,
"hidden_actual_working_time": emp._hidden_actual_working_time, # type: ignore
"actual_working_time": emp.actual_working_time,
}


Expand Down
32 changes: 30 additions & 2 deletions tests/cp/constraints/test_all_constraints.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import os
import shutil
from datetime import date
from pprint import pformat
from typing import cast

from ortools.sat.python.cp_model import CpSolver, CpSolverSolutionCallback
from ortools.sat.python.cp_model import CpSolver, CpSolverSolutionCallback, IntVar
from test_free_day_after_night_shift_phase import find_free_day_after_night_shift_phase_violations
from test_hierarchy_of_intermediate_shifts import find_hierarchy_of_intermediate_shifts_violations
from test_max_one_shift_per_day import find_max_one_shift_per_day_violations
Expand Down Expand Up @@ -37,6 +39,9 @@
RotateShiftsForwardObjective,
)
from src.cp.variables import Variable
from src.loader import FSLoader
from src.solution import Solution
from src.web.process_solution import process_solution


def detailed_error_display(
Expand Down Expand Up @@ -130,7 +135,7 @@ def test_all_constraints_mass_case(
model.cpModel.minimize(sum(model.penalties))
solver: CpSolver = CpSolver()
solver.parameters.num_workers = 0
solver.parameters.max_time_in_seconds = 15
solver.parameters.max_time_in_seconds = 30
solver.parameters.linearization_level = 0
cb = MultiSolutionCollector(model)
solver.solve(model.cpModel, cb)
Expand Down Expand Up @@ -202,6 +207,15 @@ def test_all_constraints_single_case(
shifts = model.shifts

model.add_objective(MinimizeHiddenEmployeesObjective(100.0, employees, days, shifts))
model.add_objective(FreeDaysNearWeekendObjective(2.0, employees, days))
model.add_objective(MinimizeConsecutiveNightShiftsObjective(2.0, employees, days, shifts))
model.add_objective(MinimizeHiddenEmployeesObjective(100.0, employees, days, shifts))
model.add_objective(MinimizeOvertimeObjective(4.0, employees, days, shifts))
model.add_objective(NotTooManyConsecutiveDaysObjective(5, 1.0, employees, days))
model.add_objective(RotateShiftsForwardObjective(1.0, employees, days, shifts))
model.add_objective(MaximizeEmployeeWishesObjective(3.0, employees, days, shifts))
model.add_objective(FreeDaysAfterNightShiftPhaseObjective(3.0, employees, days, shifts))
model.add_objective(EverySecondWeekendFreeObjective(1.0, employees, days))

model.add_constraint(FreeDayAfterNightShiftPhaseConstraint(employees, days, shifts))
model.add_constraint(HierarchyOfIntermediateShiftsConstraint(employees, days, shifts))
Expand All @@ -219,6 +233,20 @@ def test_all_constraints_single_case(
solver.parameters.linearization_level = 0
solver.solve(model.cpModel)

solution = Solution(
{cast(IntVar, variable).name: solver.value(variable) for variable in model.variables},
solver.objective_value,
)
solution_name = "soluting_of_test_all_costraints_single_case"
loader = FSLoader(77, start_date=date(2024, 11, 1), end_date=date(2024, 11, 30))
loader.write_solution(solution, solution_name)
process_solution(
loader=loader,
employees=employees,
output_filename=solution_name + "_processed.json",
solution_file_name=solution_name,
)

if CpSolver.StatusName(solver) == "INFEASIBLE":
raise Exception("There is no feasible solution and thus this test is pointless")

Expand Down
Loading