Skip to content

Commit

Permalink
add new python example; add simple typing annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Jul 23, 2024
1 parent 7fbe3d7 commit 5ab943e
Show file tree
Hide file tree
Showing 24 changed files with 111 additions and 27 deletions.
2 changes: 2 additions & 0 deletions examples/python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion examples/python/clustering_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
]


def clustering_sat():
def clustering_sat() -> None:
"""Entry point of the program."""
num_nodes = len(distance_matrix)
print("Num nodes =", num_nodes)
Expand Down
4 changes: 2 additions & 2 deletions examples/python/cryptarithm_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
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()

Expand Down Expand Up @@ -74,7 +74,7 @@ def send_more_money():
print("y:", solver.value(y))


def main(_):
def main(_) -> None:
send_more_money()


Expand Down
2 changes: 1 addition & 1 deletion examples/python/flexible_job_shop_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def on_solution_callback(self):
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)
Expand Down
2 changes: 1 addition & 1 deletion examples/python/gate_scheduling_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from ortools.sat.python import cp_model


def main(_):
def main(_) -> None:
"""Solves the gate scheduling problem."""
model = cp_model.CpModel()

Expand Down
2 changes: 1 addition & 1 deletion examples/python/golomb8.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
# pylint: disable=g-explicit-bool-comparison


def main(_):
def main(_) -> None:
# Create the solver.
solver = pywrapcp.Solver("golomb ruler")

Expand Down
2 changes: 1 addition & 1 deletion examples/python/golomb_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
)


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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/hidato_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/jobshop_ft06_distance_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/jobshop_with_maintenance_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def on_solution_callback(self):
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()
Expand Down
4 changes: 3 additions & 1 deletion examples/python/knapsack_2d_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions examples/python/line_balancing_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down Expand Up @@ -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")
Expand Down
75 changes: 75 additions & 0 deletions examples/python/maximize_combinations_sat.py
Original file line number Diff line number Diff line change
@@ -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)
6 changes: 4 additions & 2 deletions examples/python/maze_escape_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
)


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
Expand All @@ -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)]
Expand Down
9 changes: 6 additions & 3 deletions examples/python/no_wait_baking_scheduling_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"""

import collections
from typing import Sequence
from typing import List, Sequence, Tuple

from absl import app
from absl import flags

Expand Down Expand Up @@ -124,7 +125,7 @@ def __init__(self, unique_id, recipe_name, due_date, quantity):
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.
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/pell_equation_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
_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()

Expand Down
2 changes: 1 addition & 1 deletion examples/python/spread_robots_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
)


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()

Expand Down
2 changes: 1 addition & 1 deletion examples/python/steel_mill_slab_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def on_solution_callback(self):
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)
Expand Down
2 changes: 1 addition & 1 deletion examples/python/sudoku_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/task_allocation_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from ortools.sat.python import cp_model


def task_allocation_sat():
def task_allocation_sat() -> None:
"""Solves the task allocation problem."""
# Availability matrix.
available = [
Expand Down
2 changes: 1 addition & 1 deletion examples/python/tasks_and_workers_assignment_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def on_solution_callback(self):
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()

Expand Down
2 changes: 1 addition & 1 deletion examples/python/vendor_scheduling_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def solution_count(self):
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()
Expand Down
2 changes: 1 addition & 1 deletion examples/python/wedding_optimal_chart_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
2 changes: 1 addition & 1 deletion examples/python/weighted_latency_problem_sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down

0 comments on commit 5ab943e

Please sign in to comment.