start reformating with black
This commit is contained in:
@@ -27,18 +27,18 @@ 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 pywraprcpsp
|
||||
from ortools.scheduling import rcpsp_pb2
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
from ortools.scheduling import pywraprcpsp
|
||||
|
||||
_INPUT = flags.DEFINE_string('input', '', 'Input file to parse and solve.')
|
||||
_OUTPUT_PROTO = flags.DEFINE_string(
|
||||
'output_proto', '', 'Output file to write the cp_model proto to.')
|
||||
_PARAMS = flags.DEFINE_string('params', '', 'Sat solver parameters.')
|
||||
_USE_INTERVAL_MAKESPAN = flags.DEFINE_bool(
|
||||
'use_interval_makespan', True,
|
||||
'Whether we encode the makespan using an interval or not.')
|
||||
'use_interval_makespan',
|
||||
False,
|
||||
'Whether we encode the makespan using an interval or not.',
|
||||
)
|
||||
_HORIZON = flags.DEFINE_integer('horizon', -1, 'Force horizon.')
|
||||
_ADD_REDUNDANT_ENERGETIC_CONSTRAINTS = flags.DEFINE_bool(
|
||||
'add_redundant_energetic_constraints', False,
|
||||
@@ -213,7 +213,7 @@ def SolveRcpsp(problem,
|
||||
lower_bound: A valid lower bound of the makespan objective.
|
||||
|
||||
Returns:
|
||||
(lower_bound of the objective, best solution found, asssignment)
|
||||
(lower_bound of the objective, best solution found, assignment)
|
||||
"""
|
||||
# Create the model.
|
||||
model = cp_model.CpModel()
|
||||
@@ -350,8 +350,7 @@ def SolveRcpsp(problem,
|
||||
task = problem.tasks[task_id]
|
||||
num_modes = len(task.recipes)
|
||||
|
||||
for successor_index in range(len(task.successors)):
|
||||
next_id = task.successors[successor_index]
|
||||
for successor_index, next_id in enumerate(task.successors):
|
||||
delay_matrix = task.successor_delays[successor_index]
|
||||
num_next_modes = len(problem.tasks[next_id].recipes)
|
||||
for m1 in range(num_modes):
|
||||
@@ -510,6 +509,9 @@ def SolveRcpsp(problem,
|
||||
|
||||
# Solve model.
|
||||
solver = cp_model.CpSolver()
|
||||
if not _USE_INTERVAL_MAKESPAN.value:
|
||||
solver.parameters.exploit_all_precedences = True
|
||||
solver.parameters.use_hard_precedences_in_cumulative = True
|
||||
if params:
|
||||
text_format.Parse(params, solver.parameters)
|
||||
if in_main_solve:
|
||||
@@ -517,7 +519,7 @@ def SolveRcpsp(problem,
|
||||
status = solver.Solve(model)
|
||||
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
|
||||
assignment = rcpsp_pb2.RcpspAssignment()
|
||||
for t in range(len(problem.tasks)):
|
||||
for t, _ in enumerate(problem.tasks):
|
||||
if t in task_starts:
|
||||
assignment.start_of_task.append(solver.Value(task_starts[t]))
|
||||
for r in range(len(task_to_presence_literals[t])):
|
||||
@@ -666,7 +668,7 @@ def ComputePreemptiveLowerBound(problem, after, lower_bound):
|
||||
min_duration = max_duration
|
||||
for t in c:
|
||||
min_duration = min(min_duration, duration_map[t])
|
||||
count = model.NewIntVar(0, min_duration, f'count_{t}')
|
||||
count = model.NewIntVar(0, min_duration, f'count_{c}')
|
||||
all_vars.append(count)
|
||||
for t in c:
|
||||
vars_per_task[t].append(count)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# 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.
|
||||
|
||||
"""A simple knapsack problem."""
|
||||
# [START program]
|
||||
# [START import]
|
||||
@@ -22,22 +23,118 @@ def main():
|
||||
# Create the solver.
|
||||
# [START solver]
|
||||
solver = pywrapknapsack_solver.KnapsackSolver(
|
||||
pywrapknapsack_solver.KnapsackSolver.
|
||||
KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, 'KnapsackExample')
|
||||
pywrapknapsack_solver.KnapsackSolver.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
|
||||
"KnapsackExample",
|
||||
)
|
||||
# [END solver]
|
||||
|
||||
# [START data]
|
||||
values = [
|
||||
360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147,
|
||||
78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28,
|
||||
87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276,
|
||||
312
|
||||
360,
|
||||
83,
|
||||
59,
|
||||
130,
|
||||
431,
|
||||
67,
|
||||
230,
|
||||
52,
|
||||
93,
|
||||
125,
|
||||
670,
|
||||
892,
|
||||
600,
|
||||
38,
|
||||
48,
|
||||
147,
|
||||
78,
|
||||
256,
|
||||
63,
|
||||
17,
|
||||
120,
|
||||
164,
|
||||
432,
|
||||
35,
|
||||
92,
|
||||
110,
|
||||
22,
|
||||
42,
|
||||
50,
|
||||
323,
|
||||
514,
|
||||
28,
|
||||
87,
|
||||
73,
|
||||
78,
|
||||
15,
|
||||
26,
|
||||
78,
|
||||
210,
|
||||
36,
|
||||
85,
|
||||
189,
|
||||
274,
|
||||
43,
|
||||
33,
|
||||
10,
|
||||
19,
|
||||
389,
|
||||
276,
|
||||
312,
|
||||
]
|
||||
weights = [
|
||||
[
|
||||
7,
|
||||
0,
|
||||
30,
|
||||
22,
|
||||
80,
|
||||
94,
|
||||
11,
|
||||
81,
|
||||
70,
|
||||
64,
|
||||
59,
|
||||
18,
|
||||
0,
|
||||
36,
|
||||
3,
|
||||
8,
|
||||
15,
|
||||
42,
|
||||
9,
|
||||
0,
|
||||
42,
|
||||
47,
|
||||
52,
|
||||
32,
|
||||
26,
|
||||
48,
|
||||
55,
|
||||
6,
|
||||
29,
|
||||
84,
|
||||
2,
|
||||
4,
|
||||
18,
|
||||
56,
|
||||
7,
|
||||
29,
|
||||
93,
|
||||
44,
|
||||
71,
|
||||
3,
|
||||
86,
|
||||
66,
|
||||
31,
|
||||
65,
|
||||
0,
|
||||
79,
|
||||
20,
|
||||
65,
|
||||
52,
|
||||
13,
|
||||
]
|
||||
]
|
||||
weights = [[
|
||||
7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0,
|
||||
42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71,
|
||||
3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13
|
||||
]]
|
||||
capacities = [850]
|
||||
# [END data]
|
||||
|
||||
@@ -50,18 +147,18 @@ def main():
|
||||
packed_items = []
|
||||
packed_weights = []
|
||||
total_weight = 0
|
||||
print('Total value =', computed_value)
|
||||
print("Total value =", computed_value)
|
||||
for i in range(len(values)):
|
||||
if solver.BestSolutionContains(i):
|
||||
packed_items.append(i)
|
||||
packed_weights.append(weights[0][i])
|
||||
total_weight += weights[0][i]
|
||||
print('Total weight:', total_weight)
|
||||
print('Packed items:', packed_items)
|
||||
print('Packed_weights:', packed_weights)
|
||||
print("Total weight:", total_weight)
|
||||
print("Packed items:", packed_items)
|
||||
print("Packed_weights:", packed_weights)
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END program]
|
||||
|
||||
@@ -23,15 +23,33 @@ def main():
|
||||
# Create the solver.
|
||||
# [START solver]
|
||||
solver = pywrapknapsack_solver.KnapsackSolver(
|
||||
pywrapknapsack_solver.KnapsackSolver.
|
||||
KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER, "test")
|
||||
pywrapknapsack_solver.KnapsackSolver.KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER, "test"
|
||||
)
|
||||
# [END solver]
|
||||
|
||||
# [START data]
|
||||
weights = [[
|
||||
565, 406, 194, 130, 435, 367, 230, 315, 393, 125, 670, 892, 600, 293,
|
||||
712, 147, 421, 255
|
||||
]]
|
||||
weights = [
|
||||
[
|
||||
565,
|
||||
406,
|
||||
194,
|
||||
130,
|
||||
435,
|
||||
367,
|
||||
230,
|
||||
315,
|
||||
393,
|
||||
125,
|
||||
670,
|
||||
892,
|
||||
600,
|
||||
293,
|
||||
712,
|
||||
147,
|
||||
421,
|
||||
255,
|
||||
]
|
||||
]
|
||||
capacities = [850]
|
||||
values = weights[0]
|
||||
# [END data]
|
||||
|
||||
@@ -28,17 +28,20 @@ def main():
|
||||
# [END solver]
|
||||
|
||||
# [START data]
|
||||
costs = np.array([
|
||||
[90, 76, 75, 70],
|
||||
[35, 85, 55, 65],
|
||||
[125, 95, 90, 105],
|
||||
[45, 110, 95, 115],
|
||||
])
|
||||
costs = np.array(
|
||||
[
|
||||
[90, 76, 75, 70],
|
||||
[35, 85, 55, 65],
|
||||
[125, 95, 90, 105],
|
||||
[45, 110, 95, 115],
|
||||
]
|
||||
)
|
||||
|
||||
# Let's transform this into 3 parallel vectors (start_nodes, end_nodes,
|
||||
# arc_costs)
|
||||
end_nodes_unraveled, start_nodes_unraveled = np.meshgrid(
|
||||
np.arange(costs.shape[1]), np.arange(costs.shape[0]))
|
||||
np.arange(costs.shape[1]), np.arange(costs.shape[0])
|
||||
)
|
||||
start_nodes = start_nodes_unraveled.ravel()
|
||||
end_nodes = end_nodes_unraveled.ravel()
|
||||
arc_costs = costs.ravel()
|
||||
@@ -54,18 +57,19 @@ def main():
|
||||
|
||||
# [START print_solution]
|
||||
if status == assignment.OPTIMAL:
|
||||
print(f'Total cost = {assignment.optimal_cost()}\n')
|
||||
print(f"Total cost = {assignment.optimal_cost()}\n")
|
||||
for i in range(0, assignment.num_nodes()):
|
||||
print(f'Worker {i} assigned to task {assignment.right_mate(i)}.' +
|
||||
f' Cost = {assignment.assignment_cost(i)}')
|
||||
print(
|
||||
f"Worker {i} assigned to task {assignment.right_mate(i)}."
|
||||
+ f" Cost = {assignment.assignment_cost(i)}"
|
||||
)
|
||||
elif status == assignment.INFEASIBLE:
|
||||
print('No assignment is possible.')
|
||||
print("No assignment is possible.")
|
||||
elif status == assignment.POSSIBLE_OVERFLOW:
|
||||
print(
|
||||
'Some input costs are too large and may cause an integer overflow.')
|
||||
print("Some input costs are too large and may cause an integer overflow.")
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END Program]
|
||||
|
||||
@@ -28,18 +28,20 @@ def main():
|
||||
|
||||
# [START data]
|
||||
# Define the directed graph for the flow.
|
||||
start_nodes = [0, 0, 0, 0] + [
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4
|
||||
] + [5, 6, 7, 8]
|
||||
end_nodes = [1, 2, 3, 4] + [5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8
|
||||
] + [9, 9, 9, 9]
|
||||
capacities = [1, 1, 1, 1] + [
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||
] + [1, 1, 1, 1]
|
||||
start_nodes = (
|
||||
[0, 0, 0, 0] + [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4] + [5, 6, 7, 8]
|
||||
)
|
||||
end_nodes = (
|
||||
[1, 2, 3, 4] + [5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8] + [9, 9, 9, 9]
|
||||
)
|
||||
capacities = (
|
||||
[1, 1, 1, 1] + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + [1, 1, 1, 1]
|
||||
)
|
||||
costs = (
|
||||
[0, 0, 0, 0] +
|
||||
[90, 76, 75, 70, 35, 85, 55, 65, 125, 95, 90, 105, 45, 110, 95, 115] +
|
||||
[0, 0, 0, 0])
|
||||
[0, 0, 0, 0]
|
||||
+ [90, 76, 75, 70, 35, 85, 55, 65, 125, 95, 90, 105, 45, 110, 95, 115]
|
||||
+ [0, 0, 0, 0]
|
||||
)
|
||||
|
||||
source = 0
|
||||
sink = 9
|
||||
@@ -50,8 +52,9 @@ def main():
|
||||
# [START constraints]
|
||||
# Add each arc.
|
||||
for i in range(len(start_nodes)):
|
||||
smcf.add_arc_with_capacity_and_unit_cost(start_nodes[i], end_nodes[i],
|
||||
capacities[i], costs[i])
|
||||
smcf.add_arc_with_capacity_and_unit_cost(
|
||||
start_nodes[i], end_nodes[i], capacities[i], costs[i]
|
||||
)
|
||||
# Add node supplies.
|
||||
for i in range(len(supplies)):
|
||||
smcf.set_node_supply(i, supplies[i])
|
||||
@@ -64,23 +67,24 @@ def main():
|
||||
|
||||
# [START print_solution]
|
||||
if status == smcf.OPTIMAL:
|
||||
print('Total cost = ', smcf.optimal_cost())
|
||||
print("Total cost = ", smcf.optimal_cost())
|
||||
print()
|
||||
for arc in range(smcf.num_arcs()):
|
||||
# Can ignore arcs leading out of source or into sink.
|
||||
if smcf.tail(arc) != source and smcf.head(arc) != sink:
|
||||
|
||||
# Arcs in the solution have a flow value of 1. Their start and end nodes
|
||||
# give an assignment of worker to task.
|
||||
if smcf.flow(arc) > 0:
|
||||
print('Worker %d assigned to task %d. Cost = %d' %
|
||||
(smcf.tail(arc), smcf.head(arc), smcf.unit_cost(arc)))
|
||||
print(
|
||||
"Worker %d assigned to task %d. Cost = %d"
|
||||
% (smcf.tail(arc), smcf.head(arc), smcf.unit_cost(arc))
|
||||
)
|
||||
else:
|
||||
print('There was an issue with the min cost flow input.')
|
||||
print(f'Status: {status}')
|
||||
print("There was an issue with the min cost flow input.")
|
||||
print(f"Status: {status}")
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END program]
|
||||
|
||||
@@ -30,20 +30,59 @@ def main():
|
||||
team_a = [1, 3, 5]
|
||||
team_b = [2, 4, 6]
|
||||
|
||||
start_nodes = ([0, 0] + [11, 11, 11] + [12, 12, 12] + [
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6
|
||||
] + [7, 8, 9, 10])
|
||||
end_nodes = ([11, 12] + team_a + team_b + [
|
||||
7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8,
|
||||
9, 10
|
||||
] + [13, 13, 13, 13])
|
||||
capacities = ([2, 2] + [1, 1, 1] + [1, 1, 1] + [
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||
] + [1, 1, 1, 1])
|
||||
costs = ([0, 0] + [0, 0, 0] + [0, 0, 0] + [
|
||||
90, 76, 75, 70, 35, 85, 55, 65, 125, 95, 90, 105, 45, 110, 95, 115, 60,
|
||||
105, 80, 75, 45, 65, 110, 95
|
||||
] + [0, 0, 0, 0])
|
||||
start_nodes = (
|
||||
[0, 0]
|
||||
+ [11, 11, 11]
|
||||
+ [12, 12, 12]
|
||||
+ [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6]
|
||||
+ [7, 8, 9, 10]
|
||||
)
|
||||
end_nodes = (
|
||||
[11, 12]
|
||||
+ team_a
|
||||
+ team_b
|
||||
+ [7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10, 7, 8, 9, 10]
|
||||
+ [13, 13, 13, 13]
|
||||
)
|
||||
capacities = (
|
||||
[2, 2]
|
||||
+ [1, 1, 1]
|
||||
+ [1, 1, 1]
|
||||
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
+ [1, 1, 1, 1]
|
||||
)
|
||||
costs = (
|
||||
[0, 0]
|
||||
+ [0, 0, 0]
|
||||
+ [0, 0, 0]
|
||||
+ [
|
||||
90,
|
||||
76,
|
||||
75,
|
||||
70,
|
||||
35,
|
||||
85,
|
||||
55,
|
||||
65,
|
||||
125,
|
||||
95,
|
||||
90,
|
||||
105,
|
||||
45,
|
||||
110,
|
||||
95,
|
||||
115,
|
||||
60,
|
||||
105,
|
||||
80,
|
||||
75,
|
||||
45,
|
||||
65,
|
||||
110,
|
||||
95,
|
||||
]
|
||||
+ [0, 0, 0, 0]
|
||||
)
|
||||
|
||||
source = 0
|
||||
sink = 13
|
||||
@@ -55,8 +94,9 @@ def main():
|
||||
# [START constraints]
|
||||
# Add each arc.
|
||||
for i in range(0, len(start_nodes)):
|
||||
smcf.add_arc_with_capacity_and_unit_cost(start_nodes[i], end_nodes[i],
|
||||
capacities[i], costs[i])
|
||||
smcf.add_arc_with_capacity_and_unit_cost(
|
||||
start_nodes[i], end_nodes[i], capacities[i], costs[i]
|
||||
)
|
||||
|
||||
# Add node supplies.
|
||||
for i in range(0, len(supplies)):
|
||||
@@ -70,24 +110,29 @@ def main():
|
||||
|
||||
# [START print_solution]
|
||||
if status == smcf.OPTIMAL:
|
||||
print('Total cost = ', smcf.optimal_cost())
|
||||
print("Total cost = ", smcf.optimal_cost())
|
||||
print()
|
||||
for arc in range(smcf.num_arcs()):
|
||||
# Can ignore arcs leading out of source or intermediate, or into sink.
|
||||
if (smcf.tail(arc) != source and smcf.tail(arc) != 11 and
|
||||
smcf.tail(arc) != 12 and smcf.head(arc) != sink):
|
||||
|
||||
if (
|
||||
smcf.tail(arc) != source
|
||||
and smcf.tail(arc) != 11
|
||||
and smcf.tail(arc) != 12
|
||||
and smcf.head(arc) != sink
|
||||
):
|
||||
# Arcs in the solution will have a flow value of 1.
|
||||
# There start and end nodes give an assignment of worker to task.
|
||||
if smcf.flow(arc) > 0:
|
||||
print('Worker %d assigned to task %d. Cost = %d' %
|
||||
(smcf.tail(arc), smcf.head(arc), smcf.unit_cost(arc)))
|
||||
print(
|
||||
"Worker %d assigned to task %d. Cost = %d"
|
||||
% (smcf.tail(arc), smcf.head(arc), smcf.unit_cost(arc))
|
||||
)
|
||||
else:
|
||||
print('There was an issue with the min cost flow input.')
|
||||
print(f'Status: {status}')
|
||||
print("There was an issue with the min cost flow input.")
|
||||
print(f"Status: {status}")
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END program]
|
||||
|
||||
@@ -50,20 +50,20 @@ def main():
|
||||
|
||||
# [START print_solution]
|
||||
if status != smf.OPTIMAL:
|
||||
print('There was an issue with the max flow input.')
|
||||
print(f'Status: {status}')
|
||||
print("There was an issue with the max flow input.")
|
||||
print(f"Status: {status}")
|
||||
exit(1)
|
||||
print('Max flow:', smf.optimal_flow())
|
||||
print('')
|
||||
print(' Arc Flow / Capacity')
|
||||
print("Max flow:", smf.optimal_flow())
|
||||
print("")
|
||||
print(" Arc Flow / Capacity")
|
||||
solution_flows = smf.flows(all_arcs)
|
||||
for arc, flow, capacity in zip(all_arcs, solution_flows, capacities):
|
||||
print(f'{smf.tail(arc)} / {smf.head(arc)} {flow:3} / {capacity:3}')
|
||||
print('Source side min-cut:', smf.get_source_side_min_cut())
|
||||
print('Sink side min-cut:', smf.get_sink_side_min_cut())
|
||||
print(f"{smf.tail(arc)} / {smf.head(arc)} {flow:3} / {capacity:3}")
|
||||
print("Source side min-cut:", smf.get_source_side_min_cut())
|
||||
print("Sink side min-cut:", smf.get_sink_side_min_cut())
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END program]
|
||||
|
||||
@@ -44,7 +44,8 @@ def main():
|
||||
# [START constraints]
|
||||
# Add arcs, capacities and costs in bulk using numpy.
|
||||
all_arcs = smcf.add_arcs_with_capacity_and_unit_cost(
|
||||
start_nodes, end_nodes, capacities, unit_costs)
|
||||
start_nodes, end_nodes, capacities, unit_costs
|
||||
)
|
||||
|
||||
# Add supply for each nodes.
|
||||
smcf.set_nodes_supplies(np.arange(0, len(supplies)), supplies)
|
||||
@@ -57,21 +58,21 @@ def main():
|
||||
|
||||
# [START print_solution]
|
||||
if status != smcf.OPTIMAL:
|
||||
print('There was an issue with the min cost flow input.')
|
||||
print(f'Status: {status}')
|
||||
print("There was an issue with the min cost flow input.")
|
||||
print(f"Status: {status}")
|
||||
exit(1)
|
||||
print(f'Minimum cost: {smcf.optimal_cost()}')
|
||||
print('')
|
||||
print(' Arc Flow / Capacity Cost')
|
||||
print(f"Minimum cost: {smcf.optimal_cost()}")
|
||||
print("")
|
||||
print(" Arc Flow / Capacity Cost")
|
||||
solution_flows = smcf.flows(all_arcs)
|
||||
costs = solution_flows * unit_costs
|
||||
for arc, flow, cost in zip(all_arcs, solution_flows, costs):
|
||||
print(
|
||||
f'{smcf.tail(arc):1} -> {smcf.head(arc)} {flow:3} / {smcf.capacity(arc):3} {cost}'
|
||||
f"{smcf.tail(arc):1} -> {smcf.head(arc)} {flow:3} / {smcf.capacity(arc):3} {cost}"
|
||||
)
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# [END program]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# 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.
|
||||
|
||||
"""Simple unit tests for python/init.i. Not exhaustive."""
|
||||
|
||||
import unittest
|
||||
@@ -18,26 +19,25 @@ from ortools.init import pywrapinit
|
||||
|
||||
|
||||
class PyWrapInit(unittest.TestCase):
|
||||
|
||||
def test_logging(self):
|
||||
print('test_logging')
|
||||
pywrapinit.CppBridge.InitLogging('pywrapinit_test.py')
|
||||
print("test_logging")
|
||||
pywrapinit.CppBridge.InitLogging("pywrapinit_test.py")
|
||||
pywrapinit.CppBridge.ShutdownLogging()
|
||||
|
||||
def test_flags(self):
|
||||
print('test_cpp_flags')
|
||||
print("test_cpp_flags")
|
||||
cpp_flags = pywrapinit.CppFlags()
|
||||
# print(f'{dir(cpp_flags)}')
|
||||
assert hasattr(cpp_flags, 'stderrthreshold')
|
||||
assert hasattr(cpp_flags, 'log_prefix')
|
||||
assert hasattr(cpp_flags, 'cp_model_dump_prefix')
|
||||
assert hasattr(cpp_flags, 'cp_model_dump_models')
|
||||
assert hasattr(cpp_flags, 'cp_model_dump_lns')
|
||||
assert hasattr(cpp_flags, 'cp_model_dump_response')
|
||||
assert hasattr(cpp_flags, "stderrthreshold")
|
||||
assert hasattr(cpp_flags, "log_prefix")
|
||||
assert hasattr(cpp_flags, "cp_model_dump_prefix")
|
||||
assert hasattr(cpp_flags, "cp_model_dump_models")
|
||||
assert hasattr(cpp_flags, "cp_model_dump_lns")
|
||||
assert hasattr(cpp_flags, "cp_model_dump_response")
|
||||
pywrapinit.CppBridge.SetFlags(cpp_flags)
|
||||
|
||||
def test_version(self):
|
||||
print('test_version')
|
||||
print("test_version")
|
||||
major = pywrapinit.OrToolsVersion.MajorNumber()
|
||||
self.assertIsInstance(major, int)
|
||||
minor = pywrapinit.OrToolsVersion.MinorNumber()
|
||||
@@ -46,9 +46,9 @@ class PyWrapInit(unittest.TestCase):
|
||||
self.assertIsInstance(patch, int)
|
||||
version = pywrapinit.OrToolsVersion.VersionString()
|
||||
self.assertIsInstance(version, str)
|
||||
string = f'{major}.{minor}.{patch}'
|
||||
string = f"{major}.{minor}.{patch}"
|
||||
self.assertEqual(version, string)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@
|
||||
# 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.
|
||||
|
||||
"""helpers methods for the cp_model module."""
|
||||
|
||||
import numbers
|
||||
@@ -28,56 +29,56 @@ def is_integral(x):
|
||||
|
||||
def is_a_number(x):
|
||||
"""Checks if x has either a number.Number or a np.double type."""
|
||||
return isinstance(x, numbers.Number) or isinstance(
|
||||
x, np.double) or isinstance(x, np.integer)
|
||||
return (
|
||||
isinstance(x, numbers.Number)
|
||||
or isinstance(x, np.double)
|
||||
or isinstance(x, np.integer)
|
||||
)
|
||||
|
||||
|
||||
def is_zero(x):
|
||||
"""Checks if the x is 0 or 0.0."""
|
||||
return (is_integral(x) and int(x) == 0) or (is_a_number(x) and
|
||||
float(x) == 0.0)
|
||||
return (is_integral(x) and int(x) == 0) or (is_a_number(x) and float(x) == 0.0)
|
||||
|
||||
|
||||
def is_one(x):
|
||||
"""Checks if x is 1 or 1.0."""
|
||||
return (is_integral(x) and int(x) == 1) or (is_a_number(x) and
|
||||
float(x) == 1.0)
|
||||
return (is_integral(x) and int(x) == 1) or (is_a_number(x) and float(x) == 1.0)
|
||||
|
||||
|
||||
def is_minus_one(x):
|
||||
"""Checks if x is -1 or -1.0."""
|
||||
return (is_integral(x) and int(x) == -1) or (is_a_number(x) and
|
||||
float(x) == -1.0)
|
||||
return (is_integral(x) and int(x) == -1) or (is_a_number(x) and float(x) == -1.0)
|
||||
|
||||
|
||||
def assert_is_int64(x):
|
||||
"""Asserts that x is integer and x is in [min_int_64, max_int_64]."""
|
||||
if not is_integral(x):
|
||||
raise TypeError('Not an integer: %s' % x)
|
||||
raise TypeError("Not an integer: %s" % x)
|
||||
if x < INT_MIN or x > INT_MAX:
|
||||
raise OverflowError('Does not fit in an int64_t: %s' % x)
|
||||
raise OverflowError("Does not fit in an int64_t: %s" % x)
|
||||
return int(x)
|
||||
|
||||
|
||||
def assert_is_int32(x):
|
||||
"""Asserts that x is integer and x is in [min_int_32, max_int_32]."""
|
||||
if not is_integral(x):
|
||||
raise TypeError('Not an integer: %s' % x)
|
||||
raise TypeError("Not an integer: %s" % x)
|
||||
if x < INT32_MIN or x > INT32_MAX:
|
||||
raise OverflowError('Does not fit in an int32_t: %s' % x)
|
||||
raise OverflowError("Does not fit in an int32_t: %s" % x)
|
||||
return int(x)
|
||||
|
||||
|
||||
def assert_is_boolean(x):
|
||||
"""Asserts that x is 0 or 1."""
|
||||
if not is_integral(x) or x < 0 or x > 1:
|
||||
raise TypeError('Not a boolean: %s' % x)
|
||||
raise TypeError("Not a boolean: %s" % x)
|
||||
|
||||
|
||||
def assert_is_a_number(x):
|
||||
"""Asserts that x is a number and returns it."""
|
||||
if not is_a_number(x):
|
||||
raise TypeError('Not a number: %s' % x)
|
||||
raise TypeError("Not a number: %s" % x)
|
||||
elif is_integral(x):
|
||||
return int(x)
|
||||
else:
|
||||
@@ -101,8 +102,7 @@ def capped_subtraction(x, y):
|
||||
return x
|
||||
if x == y:
|
||||
if x == INT_MAX or x == INT_MIN:
|
||||
raise OverflowError(
|
||||
'Integer NaN: subtracting INT_MAX or INT_MIN to itself')
|
||||
raise OverflowError("Integer NaN: subtracting INT_MAX or INT_MIN to itself")
|
||||
return 0
|
||||
if x == INT_MAX or x == INT_MIN:
|
||||
return x
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# 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.
|
||||
|
||||
"""Tests for ortools.sat.python.cp_model_helper."""
|
||||
|
||||
from absl.testing import absltest
|
||||
@@ -18,64 +19,80 @@ from ortools.sat.python import cp_model_helper
|
||||
|
||||
|
||||
class CpModelHelperTest(absltest.TestCase):
|
||||
|
||||
def testassert_is_int64(self):
|
||||
print('testassert_is_int64')
|
||||
self.assertRaises(TypeError, cp_model_helper.assert_is_int64, 'Hello')
|
||||
print("testassert_is_int64")
|
||||
self.assertRaises(TypeError, cp_model_helper.assert_is_int64, "Hello")
|
||||
self.assertRaises(TypeError, cp_model_helper.assert_is_int64, 1.2)
|
||||
self.assertRaises(OverflowError, cp_model_helper.assert_is_int64, 2**63)
|
||||
self.assertRaises(OverflowError, cp_model_helper.assert_is_int64,
|
||||
-2**63 - 1)
|
||||
self.assertRaises(
|
||||
OverflowError, cp_model_helper.assert_is_int64, -(2**63) - 1
|
||||
)
|
||||
cp_model_helper.assert_is_int64(123)
|
||||
cp_model_helper.assert_is_int64(2**63 - 1)
|
||||
cp_model_helper.assert_is_int64(-2**63)
|
||||
cp_model_helper.assert_is_int64(-(2**63))
|
||||
|
||||
def testto_capped_int64(self):
|
||||
print('testto_capped_int64')
|
||||
print("testto_capped_int64")
|
||||
self.assertEqual(
|
||||
cp_model_helper.to_capped_int64(cp_model_helper.INT_MAX),
|
||||
cp_model_helper.INT_MAX)
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.to_capped_int64(cp_model_helper.INT_MAX + 1),
|
||||
cp_model_helper.INT_MAX)
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.to_capped_int64(cp_model_helper.INT_MIN),
|
||||
cp_model_helper.INT_MIN)
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.to_capped_int64(cp_model_helper.INT_MIN - 1),
|
||||
cp_model_helper.INT_MIN)
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertEqual(cp_model_helper.to_capped_int64(15), 15)
|
||||
|
||||
def testcapped_subtraction(self):
|
||||
print('testcapped_subtraction')
|
||||
print("testcapped_subtraction")
|
||||
self.assertEqual(cp_model_helper.capped_subtraction(10, 5), 5)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(cp_model_helper.INT_MIN, 5),
|
||||
cp_model_helper.INT_MIN)
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(cp_model_helper.INT_MIN, -5),
|
||||
cp_model_helper.INT_MIN)
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(cp_model_helper.INT_MAX, 5),
|
||||
cp_model_helper.INT_MAX)
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(cp_model_helper.INT_MAX, -5),
|
||||
cp_model_helper.INT_MAX)
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(2, cp_model_helper.INT_MIN),
|
||||
cp_model_helper.INT_MAX)
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertEqual(
|
||||
cp_model_helper.capped_subtraction(2, cp_model_helper.INT_MAX),
|
||||
cp_model_helper.INT_MIN)
|
||||
self.assertRaises(OverflowError, cp_model_helper.capped_subtraction,
|
||||
cp_model_helper.INT_MAX, cp_model_helper.INT_MAX)
|
||||
self.assertRaises(OverflowError, cp_model_helper.capped_subtraction,
|
||||
cp_model_helper.INT_MIN, cp_model_helper.INT_MIN)
|
||||
self.assertRaises(TypeError, cp_model_helper.capped_subtraction, 5,
|
||||
'dummy')
|
||||
self.assertRaises(TypeError, cp_model_helper.capped_subtraction,
|
||||
'dummy', 5)
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertRaises(
|
||||
OverflowError,
|
||||
cp_model_helper.capped_subtraction,
|
||||
cp_model_helper.INT_MAX,
|
||||
cp_model_helper.INT_MAX,
|
||||
)
|
||||
self.assertRaises(
|
||||
OverflowError,
|
||||
cp_model_helper.capped_subtraction,
|
||||
cp_model_helper.INT_MIN,
|
||||
cp_model_helper.INT_MIN,
|
||||
)
|
||||
self.assertRaises(TypeError, cp_model_helper.capped_subtraction, 5, "dummy")
|
||||
self.assertRaises(TypeError, cp_model_helper.capped_subtraction, "dummy", 5)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
absltest.main()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
# 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.
|
||||
|
||||
"""Tests for ortools.sat.python.swig_helper."""
|
||||
|
||||
from absl.testing import absltest
|
||||
@@ -21,13 +22,12 @@ from ortools.sat.python import swig_helper
|
||||
|
||||
|
||||
class Callback(swig_helper.SolutionCallback):
|
||||
|
||||
def __init__(self):
|
||||
swig_helper.SolutionCallback.__init__(self)
|
||||
self.__solution_count = 0
|
||||
|
||||
def OnSolutionCallback(self):
|
||||
print('New Solution')
|
||||
print("New Solution")
|
||||
self.__solution_count += 1
|
||||
|
||||
def SolutionCount(self):
|
||||
@@ -35,7 +35,6 @@ class Callback(swig_helper.SolutionCallback):
|
||||
|
||||
|
||||
class SwigHelperTest(absltest.TestCase):
|
||||
|
||||
def testVariableDomain(self):
|
||||
model_string = """
|
||||
variables { domain: [ -10, 10 ] }
|
||||
@@ -45,9 +44,11 @@ class SwigHelperTest(absltest.TestCase):
|
||||
self.assertTrue(text_format.Parse(model_string, model))
|
||||
|
||||
d0 = swig_helper.CpSatHelper.SerializedVariableDomain(
|
||||
model.variables[0].SerializeToString())
|
||||
model.variables[0].SerializeToString()
|
||||
)
|
||||
d1 = swig_helper.CpSatHelper.SerializedVariableDomain(
|
||||
model.variables[1].SerializeToString())
|
||||
model.variables[1].SerializeToString()
|
||||
)
|
||||
|
||||
self.assertEqual(d0.FlattenedIntervals(), [-10, 10])
|
||||
self.assertEqual(d1.FlattenedIntervals(), [-5, -5, 3, 6])
|
||||
@@ -89,8 +90,10 @@ class SwigHelperTest(absltest.TestCase):
|
||||
|
||||
solve_wrapper = swig_helper.SolveWrapper()
|
||||
solution = cp_model_pb2.CpSolverResponse.FromString(
|
||||
swig_helper.SolveWrapper.SerializedSolve(model.SerializeToString(),
|
||||
solve_wrapper))
|
||||
swig_helper.SolveWrapper.SerializedSolve(
|
||||
model.SerializeToString(), solve_wrapper
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(cp_model_pb2.OPTIMAL, solution.status)
|
||||
self.assertEqual(30.0, solution.objective_value)
|
||||
@@ -135,10 +138,13 @@ class SwigHelperTest(absltest.TestCase):
|
||||
|
||||
solve_wrapper = swig_helper.SolveWrapper()
|
||||
swig_helper.SolveWrapper.SetSerializedParameters(
|
||||
parameters.SerializeToString(), solve_wrapper)
|
||||
parameters.SerializeToString(), solve_wrapper
|
||||
)
|
||||
solution = cp_model_pb2.CpSolverResponse.FromString(
|
||||
swig_helper.SolveWrapper.SerializedSolve(model.SerializeToString(),
|
||||
solve_wrapper))
|
||||
swig_helper.SolveWrapper.SerializedSolve(
|
||||
model.SerializeToString(), solve_wrapper
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(cp_model_pb2.OPTIMAL, solution.status)
|
||||
self.assertEqual(30.0, solution.objective_value)
|
||||
@@ -161,8 +167,10 @@ class SwigHelperTest(absltest.TestCase):
|
||||
|
||||
solve_wrapper = swig_helper.SolveWrapper()
|
||||
solution = cp_model_pb2.CpSolverResponse.FromString(
|
||||
swig_helper.SolveWrapper.SerializedSolve(model.SerializeToString(),
|
||||
solve_wrapper))
|
||||
swig_helper.SolveWrapper.SerializedSolve(
|
||||
model.SerializeToString(), solve_wrapper
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(cp_model_pb2.OPTIMAL, solution.status)
|
||||
self.assertEqual(30.0, solution.objective_value)
|
||||
@@ -184,10 +192,13 @@ class SwigHelperTest(absltest.TestCase):
|
||||
params = sat_parameters_pb2.SatParameters()
|
||||
params.enumerate_all_solutions = True
|
||||
swig_helper.SolveWrapper.SetSerializedParameters(
|
||||
params.SerializeToString(), solve_wrapper)
|
||||
params.SerializeToString(), solve_wrapper
|
||||
)
|
||||
solution = cp_model_pb2.CpSolverResponse.FromString(
|
||||
swig_helper.SolveWrapper.SerializedSolve(model.SerializeToString(),
|
||||
solve_wrapper))
|
||||
swig_helper.SolveWrapper.SerializedSolve(
|
||||
model.SerializeToString(), solve_wrapper
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(5, callback.SolutionCount())
|
||||
self.assertEqual(cp_model_pb2.OPTIMAL, solution.status)
|
||||
@@ -228,10 +239,9 @@ class SwigHelperTest(absltest.TestCase):
|
||||
"""
|
||||
model = cp_model_pb2.CpModelProto()
|
||||
self.assertTrue(text_format.Parse(model_string, model))
|
||||
stats = swig_helper.CpSatHelper.SerializedModelStats(
|
||||
model.SerializeToString())
|
||||
stats = swig_helper.CpSatHelper.SerializedModelStats(model.SerializeToString())
|
||||
self.assertTrue(stats)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
absltest.main()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# 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.
|
||||
|
||||
"""Tests for ortools.util.python.sorted_interval_list."""
|
||||
|
||||
import unittest
|
||||
@@ -18,22 +19,20 @@ from ortools.util.python import sorted_interval_list
|
||||
|
||||
|
||||
class SortedIntervalListTest(unittest.TestCase):
|
||||
|
||||
def testCtorAndGetter(self):
|
||||
bool_domain = sorted_interval_list.Domain(0, 1)
|
||||
self.assertEqual(2, bool_domain.Size())
|
||||
self.assertEqual(0, bool_domain.Min())
|
||||
self.assertEqual(1, bool_domain.Max())
|
||||
self.assertFalse(bool_domain.IsEmpty())
|
||||
self.assertEqual(str(bool_domain), '[0,1]')
|
||||
self.assertEqual(str(bool_domain), "[0,1]")
|
||||
|
||||
def testFromValues(self):
|
||||
domain = sorted_interval_list.Domain.FromValues([1, 3, -5, 5])
|
||||
self.assertEqual(4, domain.Size())
|
||||
self.assertEqual(-5, domain.Min())
|
||||
self.assertEqual(5, domain.Max())
|
||||
self.assertEqual([-5, -5, 1, 1, 3, 3, 5, 5],
|
||||
domain.FlattenedIntervals())
|
||||
self.assertEqual([-5, -5, 1, 1, 3, 3, 5, 5], domain.FlattenedIntervals())
|
||||
self.assertTrue(domain.Contains(1))
|
||||
self.assertFalse(domain.Contains(0))
|
||||
|
||||
@@ -86,5 +85,5 @@ class SortedIntervalListTest(unittest.TestCase):
|
||||
self.assertEqual([6, 9223372036854775807], d2.FlattenedIntervals())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user