add new python example; add simple typing annotations
This commit is contained in:
@@ -54,6 +54,8 @@ code_sample_test_arg_py(
|
||||
suffix = "salbp_20_1",
|
||||
)
|
||||
|
||||
code_sample_py("maximize_combinations_sat")
|
||||
|
||||
code_sample_py("maze_escape_sat")
|
||||
|
||||
code_sample_py("no_wait_baking_scheduling_sat")
|
||||
|
||||
@@ -65,7 +65,7 @@ distance_matrix = [
|
||||
]
|
||||
|
||||
|
||||
def clustering_sat():
|
||||
def clustering_sat() -> None:
|
||||
"""Entry point of the program."""
|
||||
num_nodes = len(distance_matrix)
|
||||
print("Num nodes =", num_nodes)
|
||||
|
||||
@@ -19,7 +19,7 @@ from absl import app
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def send_more_money():
|
||||
def send_more_money() -> None:
|
||||
"""solve the cryptarithmic puzzle SEND+MORE=MONEY."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -74,7 +74,7 @@ def send_more_money():
|
||||
print("y:", solver.value(y))
|
||||
|
||||
|
||||
def main(_):
|
||||
def main(_) -> None:
|
||||
send_more_money()
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class SolutionPrinter(cp_model.CpSolverSolutionCallback):
|
||||
self.__solution_count += 1
|
||||
|
||||
|
||||
def flexible_jobshop():
|
||||
def flexible_jobshop() -> None:
|
||||
"""solve a small flexible jobshop problem."""
|
||||
# Data part.
|
||||
jobs = [ # task = (processing_time, machine_id)
|
||||
|
||||
@@ -29,7 +29,7 @@ from ortools.sat.colab import visualization
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def main(_):
|
||||
def main(_) -> None:
|
||||
"""Solves the gate scheduling problem."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ from ortools.constraint_solver import pywrapcp
|
||||
# pylint: disable=g-explicit-bool-comparison
|
||||
|
||||
|
||||
def main(_):
|
||||
def main(_) -> None:
|
||||
# Create the solver.
|
||||
solver = pywrapcp.Solver("golomb ruler")
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ _PARAMS = flags.DEFINE_string(
|
||||
)
|
||||
|
||||
|
||||
def solve_golomb_ruler(order: int, params: str):
|
||||
def solve_golomb_ruler(order: int, params: str) -> None:
|
||||
"""Solve the Golomb ruler problem."""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -147,7 +147,7 @@ def build_puzzle(problem: int) -> Union[None, list[list[int]]]:
|
||||
return puzzle
|
||||
|
||||
|
||||
def solve_hidato(puzzle: list[list[int]], index: int):
|
||||
def solve_hidato(puzzle: list[list[int]], index: int) -> None:
|
||||
"""solve the given hidato table."""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -36,7 +36,7 @@ def distance_between_jobs(x: int, y: int) -> int:
|
||||
return abs(x - y)
|
||||
|
||||
|
||||
def jobshop_ft06_distance():
|
||||
def jobshop_ft06_distance() -> None:
|
||||
"""Solves the ft06 jobshop with distances between tasks."""
|
||||
# Creates the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -36,7 +36,7 @@ class SolutionPrinter(cp_model.CpSolverSolutionCallback):
|
||||
self.__solution_count += 1
|
||||
|
||||
|
||||
def jobshop_with_maintenance():
|
||||
def jobshop_with_maintenance() -> None:
|
||||
"""Solves a jobshop with maintenance on one machine."""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -71,7 +71,9 @@ def build_data() -> tuple[pd.Series, int, int]:
|
||||
return (data, max_height, max_width)
|
||||
|
||||
|
||||
def solve_with_duplicate_items(data: pd.Series, max_height: int, max_width: int):
|
||||
def solve_with_duplicate_items(
|
||||
data: pd.Series, max_height: int, max_width: int
|
||||
) -> None:
|
||||
"""solve the problem by building 2 items (rotated or not) for each item."""
|
||||
# Derived data (expanded to individual items).
|
||||
data_widths = data["width"].to_numpy()
|
||||
|
||||
@@ -115,7 +115,7 @@ def read_model(filename):
|
||||
return model
|
||||
|
||||
|
||||
def print_stats(model):
|
||||
def print_stats(model) -> None:
|
||||
print("Model Statistics")
|
||||
for key, value in model.items():
|
||||
print(f" - {key}: {value}")
|
||||
@@ -183,7 +183,7 @@ def solve_model_greedily(model):
|
||||
return assignment
|
||||
|
||||
|
||||
def solve_boolean_model(model, hint):
|
||||
def solve_boolean_model(model, hint) -> None:
|
||||
"""solve the given model."""
|
||||
|
||||
print("Solving using the Boolean model")
|
||||
|
||||
75
examples/python/maximize_combinations_sat.py
Normal file
75
examples/python/maximize_combinations_sat.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2010-2024 Google LLC
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Maximize the number of valid combinations of Boolean variables."""
|
||||
|
||||
from typing import Sequence
|
||||
from absl import app
|
||||
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def maximize_combinations_sat() -> None:
|
||||
"""Maximize the number of valid combinations of Boolean variables."""
|
||||
model = cp_model.CpModel()
|
||||
cards: list[cp_model.IntVar] = [
|
||||
model.new_bool_var("card1"),
|
||||
model.new_bool_var("card2"),
|
||||
model.new_bool_var("card3"),
|
||||
model.new_bool_var("card4"),
|
||||
]
|
||||
|
||||
combos: list[list[cp_model.IntVar]] = [
|
||||
[cards[0], cards[1]],
|
||||
[cards[0], cards[2]],
|
||||
[cards[1], cards[3]],
|
||||
[cards[0], cards[2], cards[3]],
|
||||
]
|
||||
|
||||
deck_size: int = 3
|
||||
model.add(sum(cards) == deck_size)
|
||||
|
||||
valid_combos: list[cp_model.IntVar] = []
|
||||
for combination in combos:
|
||||
is_valid = model.new_bool_var("")
|
||||
|
||||
# All true implies is_valid.
|
||||
model.add_bool_and(is_valid).only_enforce_if(combination)
|
||||
|
||||
# is_valid implies all true.
|
||||
for literal in combination:
|
||||
model.add_implication(is_valid, literal)
|
||||
valid_combos.append(is_valid)
|
||||
|
||||
model.maximize(sum(valid_combos))
|
||||
|
||||
solver = cp_model.CpSolver()
|
||||
solver.parameters.log_search_progress = True
|
||||
status = solver.solve(model)
|
||||
|
||||
if status == cp_model.OPTIMAL:
|
||||
print(
|
||||
"chosen cards:",
|
||||
[card.name for card in cards if solver.boolean_value(card)],
|
||||
)
|
||||
|
||||
|
||||
def main(argv: Sequence[str]) -> None:
|
||||
if len(argv) > 1:
|
||||
raise app.UsageError("Too many command-line arguments.")
|
||||
maximize_combinations_sat()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(main)
|
||||
@@ -35,7 +35,9 @@ _PARAMS = flags.DEFINE_string(
|
||||
)
|
||||
|
||||
|
||||
def add_neighbor(size, x, y, z, dx, dy, dz, model, index_map, position_to_rank, arcs):
|
||||
def add_neighbor(
|
||||
size, x, y, z, dx, dy, dz, model, index_map, position_to_rank, arcs
|
||||
) -> None:
|
||||
"""Checks if the neighbor is valid, and adds it to the model."""
|
||||
if (
|
||||
x + dx < 0
|
||||
@@ -55,7 +57,7 @@ def add_neighbor(size, x, y, z, dx, dy, dz, model, index_map, position_to_rank,
|
||||
arcs.append((before_index, after_index, move_literal))
|
||||
|
||||
|
||||
def escape_the_maze(params, output_proto):
|
||||
def escape_the_maze(params, output_proto) -> None:
|
||||
"""Escapes the maze."""
|
||||
size = 4
|
||||
boxes = [(0, 1, 0), (2, 0, 1), (1, 3, 1), (3, 1, 3)]
|
||||
|
||||
@@ -21,7 +21,8 @@ We are scheduling a full day of baking:
|
||||
"""
|
||||
|
||||
import collections
|
||||
from typing import Sequence
|
||||
from typing import List, Sequence, Tuple
|
||||
|
||||
from absl import app
|
||||
from absl import flags
|
||||
|
||||
@@ -124,7 +125,7 @@ class Order:
|
||||
self.quantity = quantity
|
||||
|
||||
|
||||
def set_up_data():
|
||||
def set_up_data() -> Tuple[List[Recipe], List[Resource], List[Order]]:
|
||||
"""Set up the bakery problem data."""
|
||||
|
||||
# Recipes.
|
||||
@@ -193,7 +194,9 @@ def set_up_data():
|
||||
return recipes, resources, orders
|
||||
|
||||
|
||||
def solve_with_cp_sat(recipes, resources, orders):
|
||||
def solve_with_cp_sat(
|
||||
recipes: List[Recipe], resources: List[Resource], orders: List[Order]
|
||||
) -> None:
|
||||
"""Build the optimization model, and solve the problem."""
|
||||
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -25,7 +25,7 @@ _COEFF = flags.DEFINE_integer("coeff", 1, "The Pell equation coefficient.")
|
||||
_MAX_VALUE = flags.DEFINE_integer("max_value", 5000_000, "The maximum value.")
|
||||
|
||||
|
||||
def solve_pell(coeff: int, max_value: int):
|
||||
def solve_pell(coeff: int, max_value: int) -> None:
|
||||
"""Solves Pell's equation x^2 - coeff * y^2 = 1."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ _PARAMS = flags.DEFINE_string(
|
||||
)
|
||||
|
||||
|
||||
def spread_robots(num_robots: int, room_size: int, params: str):
|
||||
def spread_robots(num_robots: int, room_size: int, params: str) -> None:
|
||||
"""Optimize robots placement."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ class SteelMillSlabSolutionPrinter(cp_model.CpSolverSolutionCallback):
|
||||
print(line)
|
||||
|
||||
|
||||
def steel_mill_slab(problem, break_symmetries):
|
||||
def steel_mill_slab(problem, break_symmetries) -> None:
|
||||
"""Solves the Steel Mill Slab Problem."""
|
||||
### Load problem.
|
||||
(num_slabs, capacities, num_colors, orders) = build_problem(problem)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def solve_sudoku():
|
||||
def solve_sudoku() -> None:
|
||||
"""Solves the sudoku problem with the CP-SAT solver."""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -23,7 +23,7 @@ from absl import app
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
|
||||
def task_allocation_sat():
|
||||
def task_allocation_sat() -> None:
|
||||
"""Solves the task allocation problem."""
|
||||
# Availability matrix.
|
||||
available = [
|
||||
|
||||
@@ -34,7 +34,7 @@ class ObjectivePrinter(cp_model.CpSolverSolutionCallback):
|
||||
self.__solution_count += 1
|
||||
|
||||
|
||||
def tasks_and_workers_assignment_sat():
|
||||
def tasks_and_workers_assignment_sat() -> None:
|
||||
"""solve the assignment problem."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class SolutionPrinter(cp_model.CpSolverSolutionCallback):
|
||||
return self.__solution_count
|
||||
|
||||
|
||||
def vendor_scheduling_sat():
|
||||
def vendor_scheduling_sat() -> None:
|
||||
"""Create the shift scheduling model and solve it."""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
|
||||
@@ -130,7 +130,7 @@ def build_data():
|
||||
return num_tables, table_capacity, min_known_neighbors, connections, names
|
||||
|
||||
|
||||
def solve_with_discrete_model():
|
||||
def solve_with_discrete_model() -> None:
|
||||
"""Discrete approach."""
|
||||
num_tables, table_capacity, min_known_neighbors, connections, names = build_data()
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ def build_model():
|
||||
return x, y, profits
|
||||
|
||||
|
||||
def solve_with_cp_sat(x, y, profits):
|
||||
def solve_with_cp_sat(x, y, profits) -> None:
|
||||
"""Solves the problem with the CP-SAT solver."""
|
||||
model = cp_model.CpModel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user