examples: backport from main

This commit is contained in:
Corentin Le Molgat
2025-07-23 17:38:49 +02:00
committed by Mizux Seiha
parent a7f49a2585
commit f0d0fe71ba
32 changed files with 335 additions and 64 deletions

View File

@@ -27,7 +27,6 @@ import numpy as np
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_PARAMS = flags.DEFINE_string(
@@ -149,7 +148,7 @@ def permutation_flow_shop(
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solver.parameters.log_search_progress = log
solver.parameters.max_time_in_seconds = time_limit

View File

@@ -9,7 +9,6 @@ import argparse
import collections
from ortools.sat.python import cp_model
from google.protobuf import text_format
#----------------------------------------------------------------------------
# Command line arguments.
@@ -295,7 +294,7 @@ def main(args):
solver = cp_model.CpSolver()
solver.parameters.max_time_in_seconds = 60 * 60 * 2
if parameters:
text_format.Merge(parameters, solver.parameters)
solver.parameters.merge_text_format(parameters)
solution_printer = SolutionPrinter(makespan)
status = solver.Solve(model, solution_printer)

View File

@@ -23,6 +23,8 @@ code_sample_py("balance_group_sat")
code_sample_py("bus_driver_scheduling_sat")
code_sample_py("car_sequencing_optimization_sat")
code_sample_py("chemical_balance_sat")
code_sample_py("clustering_sat")

View File

@@ -180,7 +180,7 @@ def aggregate_item_collections_optimally(
def get_optimal_schedule(
demand: list[tuple[float, str, int]]
demand: list[tuple[float, str, int]],
) -> list[tuple[int, list[tuple[int, str]]]]:
"""Computes the optimal schedule for the installation input.

View File

@@ -21,7 +21,6 @@ from absl import app
from absl import flags
import numpy as np
from google.protobuf import text_format
from ortools.linear_solver.python import model_builder as mb
from ortools.sat.python import cp_model
@@ -319,7 +318,7 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st
# Solve model.
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solver.parameters.log_search_progress = True
solver.Solve(model)

View File

@@ -19,6 +19,7 @@ be as close to the average as possible.
Furthermore, if one color is an a group, at least k items with this color must
be in that group.
"""
from typing import Dict, Sequence
from absl import app

View File

@@ -29,7 +29,7 @@ import math
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_OUTPUT_PROTO = flags.DEFINE_string(
@@ -81,7 +81,7 @@ SAMPLE_SHIFTS_TINY = [
[25, "15:40", "15:56", 940, 956, 16],
[26, "15:58", "16:45", 958, 1005, 47],
[27, "16:04", "17:30", 964, 1050, 86],
] # yapf:disable
]
SAMPLE_SHIFTS_SMALL = [
#
@@ -143,7 +143,7 @@ SAMPLE_SHIFTS_SMALL = [
[47, "18:34", "19:58", 1114, 1198, 84],
[48, "19:56", "20:34", 1196, 1234, 38],
[49, "20:05", "20:48", 1205, 1248, 43],
] # yapf:disable
]
SAMPLE_SHIFTS_MEDIUM = [
[0, "04:30", "04:53", 270, 293, 23],
@@ -346,7 +346,7 @@ SAMPLE_SHIFTS_MEDIUM = [
[197, "00:02", "00:12", 1442, 1452, 10],
[198, "00:07", "00:39", 1447, 1479, 32],
[199, "00:25", "01:12", 1465, 1512, 47],
] # yapf:disable
]
SAMPLE_SHIFTS_LARGE = [
[0, "04:18", "05:00", 258, 300, 42],
@@ -1705,7 +1705,7 @@ SAMPLE_SHIFTS_LARGE = [
[1353, "00:47", "01:26", 1487, 1526, 39],
[1354, "00:54", "01:04", 1494, 1504, 10],
[1355, "00:57", "01:07", 1497, 1507, 10],
] # yapf:disable
]
def bus_driver_scheduling(minimize_drivers: bool, max_num_drivers: int) -> int:
@@ -1981,7 +1981,7 @@ def bus_driver_scheduling(minimize_drivers: bool, max_num_drivers: int) -> int:
# Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)

View File

@@ -0,0 +1,271 @@
#!/usr/bin/env python3
# Copyright 2010-2025 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.
"""Solve the car sequencing problem as an optimization problem.
Problem Description: The Car Sequencing Problem with Optimization
-----------------------------------------------------------------
See https://en.wikipedia.org/wiki/Car_sequencing_problem for more details.
We are tasked with determining the optimal production sequence for a set of cars
on an assembly line. This is a classic and challenging combinatorial
optimization problem with the following characteristics:
Fixed Production Demand: There is a specific, non-negotiable number of cars of
different types (or 'classes') that must be produced. In our case, we have 6
distinct classes of cars, and we must produce exactly 5 of each, for a total of
30 'real' cars.
Diverse Car Configurations: Each car class is defined by a unique combination of
optional features. For example, 'Class 1' might require a sunroof (Option 1) and
a special engine (Option 4), while 'Class 3' only requires air conditioning
(Option 2).
Specialized Assembly Stations: The assembly line is composed of a series of
specialized stations. Each station is responsible for installing one specific
option. For example, there is one station for sunroofs, one for special engines,
and so on.
Capacity-Limited Stations: The core challenge of the problem lies here. The
stations cannot handle an unlimited, dense flow of cars requiring their specific
option. Their capacity is defined by a 'sliding window' constraint. For example,
the sunroof station might have a constraint of 'at most 1 car with a sunroof in
any sequence of 3 consecutive cars'. This means sequences like [Sunroof, No, No,
Sunroof] are valid, but [Sunroof, No, Sunroof, No] are not.
The Need for Spacing (Optimization): The combination of high demand for certain
options and tight capacity constraints may make it impossible to produce the 30
real cars consecutively. To create a valid sequence, we may need to insert
'dummy' or 'filler' cars into the production line. These dummy cars have no
options and therefore do not consume capacity at any station. They serve purely
as spacers to break up dense sequences of option-heavy cars.
The Goal: The objective is to find a production sequence that fulfills the
demand for all 30 real cars while using the minimum number of dummy cars. This
is equivalent to finding the shortest possible total production schedule (real
cars + dummy cars).
Modeling and Solution Approach with CP-SAT
------------------------------------------
To solve this problem, we use the CP-SAT solver from Google's OR-Tools library.
This is a constraint programming approach, which works by defining variables,
constraints, and an objective function.
1. Decision Variables
The fundamental decision the solver must make is: 'Which class of car should be
placed in each production slot?'
We define a large number of boolean variables: produces[c][s]. This variable is
True if a car of class c is scheduled in slot s, and False otherwise. We create
these for all car classes (including the dummy class) and for an extended number
of slots (30 real + a buffer of 20 for dummies).
We introduce a key integer variable: makespan. This variable represents the
total length of the 'meaningful' part of our schedule. It's the slot number
where the first dummy car appears, after which all subsequent cars are also
dummies.
2. Constraints (The Rules of the Game)
We translate the problem's rules into mathematical constraints that the solver
must obey:
One Car Per Slot: For every production slot s, exactly one car class can be
assigned. We enforce this using an AddExactlyOne constraint over all
produces[c][s] variables for that slot.
Fulfill Real Car Demand: The total number of times each real car class c appears
across all slots must equal its required demand (5 in our case). This is a
simple Add(sum(...) == 5) constraint.
Station Capacity (Sliding Window): This is the most critical constraint. For
each option (e.g., 'sunroof') and its capacity rule (e.g., '1 in 3'), we create
constraints for every possible sliding window. For every subsequence of 3 slots,
we sum up the produces variables corresponding to car classes that require that
option and constrain this sum to be less than or equal to 1.
Makespan Definition: This is the clever part of the model. We link our makespan
objective variable to the placement of dummy cars using logical equivalences for
each slot s:
(makespan <= s) is equivalent to (slot s contains a dummy car)
This ensures that if the solver chooses a makespan of 32, for example, it is
forced to place dummy cars in slots 32, 33, 34, and so on. Conversely, if the
solver is forced to place a dummy car in slot 32 to satisfy a capacity
constraint, the makespan must be at most 32.
3. The Objective Function
The objective is simple and directly tied to our goal:
Minimize makespan: By instructing the solver to find a solution with the
smallest possible value for the makespan variable, we are asking it to find the
shortest possible production schedule that satisfies all the rules. This
inherently minimizes the number of dummy cars used.
By defining the problem in this way, we let the CP-SAT solver explore the vast
search space of possible sequences efficiently, using its powerful constraint
propagation and search techniques to find an optimal arrangement that meets all
our complex requirements.
"""
from collections.abc import Sequence
from absl import app
from ortools.sat.python import cp_model
def solve_car_sequencing_optimization() -> None:
"""Solves the car sequencing problem with an optimization approach."""
# --------------------
# 1. Data
# --------------------
num_real_cars: int = 30
max_dummy_cars: int = 20
num_slots = num_real_cars + max_dummy_cars
all_slots = range(num_slots)
class_options = [
# Options: 1 2 3 4 5
[0, 0, 0, 0, 0], # Class 0 (Dummy)
[1, 0, 0, 1, 0], # Class 1
[0, 1, 0, 0, 1], # Class 2
[0, 1, 0, 0, 0], # Class 3
[0, 0, 1, 1, 0], # Class 4
[0, 0, 1, 0, 0], # Class 5
[0, 0, 0, 0, 1], # Class 6
]
num_classes = len(class_options)
all_classes = range(num_classes)
real_classes = range(1, num_classes)
dummy_class = 0
demands = [5, 5, 5, 5, 5, 5]
capacity_constraints = [(1, 3), (1, 2), (1, 3), (2, 5), (1, 5)]
num_options = len(capacity_constraints)
all_options = range(num_options)
classes_with_option = [
[c for c in real_classes if class_options[c][o] == 1] for o in all_options
]
# --------------------
# 2. Model Creation
# --------------------
model = cp_model.CpModel()
# --------------------
# 3. Decision Variables
# --------------------
produces = {}
for c in all_classes:
for s in all_slots:
produces[(c, s)] = model.new_bool_var(f"produces_c{c}_s{s}")
makespan = model.new_int_var(num_real_cars, num_slots, "makespan")
# --------------------
# 4. Constraints
# --------------------
# Constraint 1: Only one car produced per slot.
for s in all_slots:
model.add_exactly_one([produces[(c, s)] for c in all_classes])
# Constraint 2: Meet the demand of real cars.
for i, c in enumerate(real_classes):
model.add(sum(produces[(c, s)] for s in all_slots) == demands[i])
# Constraint 3: Enforce the capacity constraints on options.
for o in all_options:
max_cars, subsequence_len = capacity_constraints[o]
for start in range(num_slots - subsequence_len + 1):
window = range(start, start + subsequence_len)
cars_with_option_in_window = []
for c in classes_with_option[o]:
for s in window:
cars_with_option_in_window.append(produces[(c, s)])
model.add(sum(cars_with_option_in_window) <= max_cars)
# Constraint 4 (Link objective and dummy cars at the end of the schedule)
for s in all_slots:
makespan_le_s = model.new_bool_var(f"makespan_le_{s}")
# Enforce makespan_le_s <=> (makespan <= s)
model.add(makespan <= s).only_enforce_if(makespan_le_s)
# Use ~ for negation
model.add(makespan > s).only_enforce_if(~makespan_le_s)
# Enforce makespan_le_s => produces[dummy_class, s]
model.add_implication(makespan_le_s, produces[dummy_class, s])
# --------------------
# 5. Objective
# --------------------
model.minimize(makespan)
# --------------------
# 6. Solve and Print Solution
# --------------------
solver = cp_model.CpSolver()
solver.parameters.max_time_in_seconds = 30.0
solver.parameters.num_search_workers = 1 # The problem is easy to solve.
# solver.parameters.log_search_progress = True # uncomment to see the log.
status = solver.Solve(model)
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
final_makespan = int(solver.ObjectiveValue())
num_dummies_needed = final_makespan - num_real_cars
print(
f'\n{"Optimal" if status == cp_model.OPTIMAL else "Feasible"}'
f" solution found with a makespan of {final_makespan}."
)
print(
f"This requires the conceptual equivalent of {num_dummies_needed} dummy"
" car(s) to be used as spacers."
)
sequence = [-1] * num_slots
for s in all_slots:
for c in all_classes:
if solver.Value(produces[(c, s)]) == 1:
sequence[s] = c
break
print("\nFull Production Sequence (Class 0 is dummy):")
print("Slot: | " + " | ".join(f"{i:2}" for i in range(num_slots)) + " |")
print("-------|-" + "--|-" * num_slots)
print("Class: | " + " | ".join(f"{c:2}" for c in sequence) + " |")
elif status == cp_model.INFEASIBLE:
print("\nNo solution found.")
else:
print(f"\nSomething went wrong. Solver status: {status}")
print("\nSolver statistics:")
print(solver.response_stats())
def main(argv: Sequence[str]) -> None:
if len(argv) > 1:
raise app.UsageError("Too many command-line arguments.")
solve_car_sequencing_optimization()
if __name__ == "__main__":
app.run(main)

View File

@@ -12,8 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Use CP-SAT to solve a simple cryptarithmetic problem: SEND+MORE=MONEY.
"""
"""Use CP-SAT to solve a simple cryptarithmetic problem: SEND+MORE=MONEY."""
from absl import app
from ortools.sat.python import cp_model

View File

@@ -69,7 +69,7 @@ def main(_) -> None:
branches = collector.Branches(i)
failures = collector.Failures(i)
print(
("Solution #%i: value = %i, failures = %i, branches = %i," "time = %i ms")
"Solution #%i: value = %i, failures = %i, branches = %i,time = %i ms"
% (i, obj_value, failures, branches, time)
)
time = solver.WallTime()

View File

@@ -24,10 +24,10 @@ see: https://en.wikipedia.org/wiki/Golomb_ruler
"""
from typing import Sequence
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_ORDER = flags.DEFINE_integer("order", 8, "Order of the ruler.")
@@ -70,7 +70,7 @@ def solve_golomb_ruler(order: int, params: str) -> None:
# Solve the model.
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solution_printer = cp_model.ObjectiveSolutionPrinter()
print(f"Golomb ruler(order={order})")
status = solver.solve(model, solution_printer)

View File

@@ -25,8 +25,6 @@ from absl import flags
import numpy as np
import pandas as pd
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -159,7 +157,7 @@ def solve_with_duplicate_items(
# Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)
@@ -261,7 +259,7 @@ def solve_with_duplicate_optional_items(
# solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)
@@ -382,7 +380,7 @@ def solve_with_rotations(data: pd.Series, max_height: int, max_width: int):
# solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)

View File

@@ -33,7 +33,7 @@ from typing import Dict, Sequence
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -272,7 +272,7 @@ def solve_problem_with_boolean_model(
# solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solver.parameters.log_search_progress = True
solver.solve(model)
@@ -339,7 +339,7 @@ def solve_problem_with_scheduling_model(
# solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solver.parameters.log_search_progress = True
solver.solve(model)

View File

@@ -14,9 +14,9 @@
"""Test linear sum assignment on a 4x4 matrix.
Example taken from:
http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1]
modified so the optimum solution is unique.
Example taken from:
http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1]
modified so the optimum solution is unique.
"""
from typing import Sequence
@@ -28,7 +28,12 @@ def run_assignment_on_4x4_matrix():
"""Test linear sum assignment on a 4x4 matrix."""
num_sources = 4
num_targets = 4
cost = [[90, 76, 75, 80], [35, 85, 55, 65], [125, 95, 90, 105], [45, 110, 95, 115]]
cost = [
[90, 76, 75, 80],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
]
expected_cost = cost[0][3] + cost[1][2] + cost[2][1] + cost[3][0]
assignment = linear_sum_assignment.SimpleLinearSumAssignment()

View File

@@ -15,6 +15,7 @@
"""Maximize the number of valid combinations of Boolean variables."""
from typing import Sequence
from absl import app
from ortools.sat.python import cp_model

View File

@@ -20,12 +20,12 @@ visit all boxes in order, and walk on each block in a 4x4x4 map exactly once.
Admissible moves are one step in one of the 6 directions:
x+, x-, y+, y-, z+(up), z-(down)
"""
from typing import Dict, Sequence, Tuple
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_OUTPUT_PROTO = flags.DEFINE_string(
@@ -140,7 +140,7 @@ def escape_the_maze(params: str, output_proto: str) -> None:
# Solve model.
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solver.parameters.log_search_progress = True
result = solver.solve(model)

View File

@@ -20,7 +20,6 @@ from typing import List
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -72,7 +71,7 @@ def solve_hard_model(output_proto: str, params: str) -> bool:
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
status = solver.solve(model)
print(solver.response_stats())
@@ -158,7 +157,7 @@ def solve_soft_model_with_maximization(params: str) -> None:
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
status = solver.solve(model)
print(solver.response_stats())
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:

View File

@@ -26,7 +26,6 @@ from typing import List, Sequence, Tuple
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_PARAMS = flags.DEFINE_string(
@@ -287,7 +286,7 @@ def solve_with_cp_sat(
# Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solver.parameters.log_search_progress = True
status = solver.solve(model)

View File

@@ -18,6 +18,7 @@ import time
from absl import app
from absl import flags
from ortools.sat.python import cp_model
_SIZE = flags.DEFINE_integer("size", 8, "Number of queens.")

View File

@@ -18,6 +18,7 @@ from collections.abc import Sequence
from absl import app
from absl import flags
from ortools.sat.python import cp_model

View File

@@ -31,7 +31,6 @@ from typing import Dict, List
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -144,7 +143,7 @@ def generate_and_solve_problem(pieces: Dict[str, List[List[int]]]) -> None:
# Solve the model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)
print(

View File

@@ -82,6 +82,8 @@ def print_solution(manager, routing, assignment):
total_distance = 0
total_value_collected = 0
for v in range(manager.GetNumberOfVehicles()):
if not routing.IsVehicleUsed(assignment, v):
continue
index = routing.Start(v)
plan_output = f'Route for vehicle {v}:\n'
route_distance = 0

View File

@@ -52,7 +52,12 @@ def min_cost_flow_api():
print("MinCostFlow on 4x4 matrix.")
num_sources = 4
num_targets = 4
costs = [[90, 75, 75, 80], [35, 85, 55, 65], [125, 95, 90, 105], [45, 110, 95, 115]]
costs = [
[90, 75, 75, 80],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
]
expected_cost = 275
smcf = min_cost_flow.SimpleMinCostFlow()
for source in range(0, num_sources):

View File

@@ -26,7 +26,6 @@ import collections
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
from ortools.scheduling import rcpsp_pb2
from ortools.scheduling.python import rcpsp
@@ -361,7 +360,7 @@ def solve_rcpsp(
# Parse user specified parameters.
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
# Favor objective_shaving over objective_lb_search.
if solver.parameters.num_workers >= 16 and solver.parameters.num_workers < 24:

View File

@@ -17,7 +17,6 @@
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_OUTPUT_PROTO = flags.DEFINE_string(
@@ -410,7 +409,7 @@ def solve_shift_scheduling(params: str, output_proto: str):
# Solve the model.
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solution_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.solve(model, solution_printer)

View File

@@ -17,7 +17,6 @@
from typing import Sequence
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
# ----------------------------------------------------------------------------
@@ -498,7 +497,7 @@ def single_machine_scheduling():
# Solve.
solver = cp_model.CpSolver()
if parameters:
text_format.Parse(parameters, solver.parameters)
solver.parameters.parse_text_format(parameters)
solution_printer = SolutionPrinter()
solver.best_bound_callback = lambda a: print(f"New objective lower bound: {a}")
solver.solve(model, solution_printer)

View File

@@ -18,8 +18,6 @@ import math
from typing import Sequence
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_NUM_ROBOTS = flags.DEFINE_integer("num_robots", 8, "Number of robots to place.")
@@ -94,7 +92,7 @@ def spread_robots(num_robots: int, room_size: int, params: str) -> None:
# Creates a solver and solves the model.
solver = cp_model.CpSolver()
if params:
text_format.Parse(params, solver.parameters)
solver.parameters.parse_text_format(params)
solver.parameters.log_search_progress = True
status = solver.solve(model)

View File

@@ -21,7 +21,7 @@ import time
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -293,7 +293,7 @@ def steel_mill_slab(problem_id: int, break_symmetries: bool) -> None:
### Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
objective_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.solve(model, objective_printer)
@@ -477,7 +477,7 @@ def steel_mill_slab_with_valid_slabs(problem_id: int, break_symmetries: bool) ->
### Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solution_printer = SteelMillSlabSolutionPrinter(orders, assign, loads, losses)
status = solver.solve(model, solution_printer)
@@ -547,7 +547,7 @@ def steel_mill_slab_with_column_generation(problem_id: int) -> None:
### Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solution_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.solve(model, solution_printer)

View File

@@ -33,7 +33,6 @@ from absl import app
from absl import flags
import pandas as pd
from google.protobuf import text_format
from ortools.sat.python import cp_model
@@ -141,7 +140,7 @@ def solve(
# Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
status = solver.solve(model)
# Report solution.

View File

@@ -13,8 +13,4 @@
package(default_visibility = ["//visibility:public"])
exports_files(
[
"salbp_20_1.alb",
],
)
exports_files(["salbp_20_1.alb"])

View File

@@ -22,7 +22,6 @@
"""
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
###########################

View File

@@ -16,10 +16,10 @@
import random
from typing import Sequence
from absl import app
from absl import flags
from google.protobuf import text_format
from ortools.sat.python import cp_model
_NUM_NODES = flags.DEFINE_integer("num_nodes", 12, "Number of nodes to visit.")
@@ -27,7 +27,9 @@ _GRID_SIZE = flags.DEFINE_integer("grid_size", 20, "Size of the grid where nodes
_PROFIT_RANGE = flags.DEFINE_integer("profit_range", 50, "Range of profit.")
_SEED = flags.DEFINE_integer("seed", 0, "Random seed.")
_PARAMS = flags.DEFINE_string(
"params", "num_search_workers:16, max_time_in_seconds:5", "Sat solver parameters."
"params",
"num_search_workers:16, max_time_in_seconds:5",
"Sat solver parameters.",
)
_PROTO_FILE = flags.DEFINE_string(
"proto_file", "", "If not empty, output the proto to this file."
@@ -96,7 +98,7 @@ def solve_with_cp_sat(x, y, profits) -> None:
# Solve model.
solver = cp_model.CpSolver()
if _PARAMS.value:
text_format.Parse(_PARAMS.value, solver.parameters)
solver.parameters.parse_text_format(_PARAMS.value)
solver.parameters.log_search_progress = True
solver.solve(model)