diff --git a/examples/python/BUILD.bazel b/examples/python/BUILD.bazel index a3c8f5c7d5a..4a82eb95558 100644 --- a/examples/python/BUILD.bazel +++ b/examples/python/BUILD.bazel @@ -58,6 +58,8 @@ code_sample_py("maze_escape_sat") code_sample_py("no_wait_baking_scheduling_sat") +code_sample_py("pell_equation_sat") + code_sample_py("pentominoes_sat") code_sample_py("prize_collecting_tsp_sat") @@ -96,6 +98,8 @@ code_sample_py("task_allocation_sat") code_sample_py("tasks_and_workers_assignment_sat") +code_sample_py("test_scheduling_sat") + code_sample_py("tsp_sat") code_sample_py("vendor_scheduling_sat") diff --git a/examples/python/golomb8.py b/examples/python/golomb8.py index 44a464f32f5..c648bf93dd2 100755 --- a/examples/python/golomb8.py +++ b/examples/python/golomb8.py @@ -23,11 +23,8 @@ """ from absl import app -from absl import flags from ortools.constraint_solver import pywrapcp -FLAGS = flags.FLAGS - # We disable the following warning because it is a false positive on constraints # like: solver.Add(x == 0) # pylint: disable=g-explicit-bool-comparison diff --git a/examples/python/line_balancing_sat.py b/examples/python/line_balancing_sat.py index a43cb0318e7..af97d80a2c8 100644 --- a/examples/python/line_balancing_sat.py +++ b/examples/python/line_balancing_sat.py @@ -47,7 +47,7 @@ ) -class SectionInfo(object): +class SectionInfo: """Store model information for each section of the input file.""" def __init__(self): diff --git a/examples/python/no_wait_baking_scheduling_sat.py b/examples/python/no_wait_baking_scheduling_sat.py index b6f6177b3ec..3031aa19f4d 100644 --- a/examples/python/no_wait_baking_scheduling_sat.py +++ b/examples/python/no_wait_baking_scheduling_sat.py @@ -50,7 +50,7 @@ DISPLAY = "display" -class Task(object): +class Task: """A unit baking task. - Simple baking tasks have a fixed duration. They are performed by workers. @@ -64,7 +64,7 @@ def __init__(self, name, min_duration, max_duration): self.max_duration = max_duration -class Skill(object): +class Skill: """The skill of a worker or the capability of a machine.""" def __init__(self, name, efficiency): @@ -73,7 +73,7 @@ def __init__(self, name, efficiency): self.efficiency = efficiency -class Recipe(object): +class Recipe: """A recipe is a sequence of cooking tasks.""" def __init__(self, name): @@ -85,7 +85,7 @@ def add_task(self, resource_name, min_duration, max_duration): return self -class Resource(object): +class Resource: """A resource is a worker, a machine, or just some space for cakes to rest. - Workers have a capacity of 1 and can have variable efficiency. @@ -106,7 +106,7 @@ def add_skill(self, skill_name, efficiency): return self -class Order(object): +class Order: """An order is a recipe that should be delivered at a given due date.""" def __init__(self, unique_id, recipe_name, due_date, quantity): diff --git a/examples/python/pentominoes_sat.py b/examples/python/pentominoes_sat.py index cb3b9443d0e..d4573e1f672 100644 --- a/examples/python/pentominoes_sat.py +++ b/examples/python/pentominoes_sat.py @@ -20,6 +20,9 @@ This problem comes from the game Katamino: http://boardgamegeek.com/boardgame/6931/katamino + +This example also includes suggestions from +https://web.ma.utexas.edu/users/smmg/archive/1997/radin.html """ from collections.abc import Sequence @@ -42,6 +45,8 @@ "pieces", "FILNPTUVWXYZ", "The subset of pieces to consider." ) +_HEIGHT = flags.DEFINE_integer("height", 5, "The height of the box.") + def is_one(mask: List[List[int]], x: int, y: int, orientation: int) -> bool: """Returns true if the oriented piece is 1 at position [i][j]. @@ -104,8 +109,9 @@ def orientation_is_redundant(mask: List[List[int]], orientation: int) -> bool: def generate_and_solve_problem(pieces: Dict[str, List[List[int]]]) -> None: """Solves the pentominoes problem.""" - box_width = len(pieces) - box_height = 5 + box_height = _HEIGHT.value + box_width = 5 * len(pieces) // box_height + print(f"Box has dimension {box_height} * {box_width}") model = cp_model.CpModel() position_to_variables: List[List[List[cp_model.IntVar]]] = [ @@ -142,8 +148,8 @@ def generate_and_solve_problem(pieces: Dict[str, List[List[int]]]) -> None: status = solver.solve(model) print( - f"Problem {_PIECES.value} solved in {solver.wall_time}s with status" - f" {solver.status_name(status)}" + f"Problem {_PIECES.value} box {box_height}*{box_width} solved in" + f" {solver.wall_time}s with status {solver.status_name(status)}" ) # Print the solution. @@ -183,6 +189,16 @@ def main(argv: Sequence[str]) -> None: print(f"Piece {p} not found in the list of pieces") return selected_pieces[p] = pieces[p] + if (len(selected_pieces) * 5) % _HEIGHT.value != 0: + print( + f"The height {_HEIGHT.value} does not divide the total area" + f" {5 * len(selected_pieces)}" + ) + return + if _HEIGHT.value < 3 or 5 * len(selected_pieces) // _HEIGHT.value < 3: + print(f"The height {_HEIGHT.value} is not compatible with the pieces.") + return + generate_and_solve_problem(selected_pieces) diff --git a/examples/python/single_machine_scheduling_with_setup_release_due_dates_sat.py b/examples/python/single_machine_scheduling_with_setup_release_due_dates_sat.py index 8e048c09694..7bc29ba5534 100644 --- a/examples/python/single_machine_scheduling_with_setup_release_due_dates_sat.py +++ b/examples/python/single_machine_scheduling_with_setup_release_due_dates_sat.py @@ -27,7 +27,7 @@ ) _PARAMS = flags.DEFINE_string( "params", - "num_search_workers:16,log_search_progress:false,max_time_in_seconds:45", + "num_search_workers:16,log_search_progress:true,max_time_in_seconds:45", "Sat solver parameters.", ) _PREPROCESS = flags.DEFINE_bool(