reformat linear_solver python code to BLACK; support pybind11_protobuf

This commit is contained in:
Laurent Perron
2023-06-28 15:57:32 +02:00
parent 36c570e670
commit 9635b925f6
35 changed files with 4451 additions and 949 deletions

View File

@@ -339,7 +339,11 @@ if(BUILD_PYTHON)
"NOT BUILD_DEPS" ON)
message(STATUS "Python: Build pybind11: ${BUILD_pybind11}")
CMAKE_DEPENDENT_OPTION(BUILD_PYTHON_DOC "Build the Python doc" OFF "NOT BUILD_DOC" ON)
CMAKE_DEPENDENT_OPTION(BUILD_pybind11_protobuf "Build the pybind11_protobuf dependency Library" OFF
"NOT BUILD_DEPS" ON)
message(STATUS "Python: Build pybind11_protobuf: ${BUILD_pybind11_protobuf}")
CMAKE_DEPENDENT_OPTION(BUILD_PYTHON_DOC "Build the Python doc" OFF "NOT BUILD_DOC" ON)
message(STATUS "Python: Build doc: ${BUILD_PYTHON_DOC}")
CMAKE_DEPENDENT_OPTION(BUILD_VENV "Create Python venv in BINARY_DIR/python/venv" OFF

View File

@@ -73,7 +73,7 @@ git_repository(
## Protobuf
git_repository(
name = "com_google_protobuf",
tag = "v23.2",
tag = "v23.3",
patches = ["//patches:protobuf-v23.2.patch"],
patch_args = ["-p1"],
remote = "https://github.com/protocolbuffers/protobuf.git",
@@ -214,9 +214,22 @@ new_git_repository(
remote = "https://github.com/pybind/pybind11.git",
)
new_git_repository(
name = "pybind11_protobuf",
#build_file = "@pybind11_bazel//:pybind11.BUILD",
#tag = "v2.10.3",
commit = "5baa2dc9d93e3b608cde86dfa4b8c63aeab4ac78",
remote = "https://github.com/pybind/pybind11_protobuf.git",
)
load("@pybind11_bazel//:python_configure.bzl", "python_configure")
python_configure(name = "local_config_python", python_version = "3")
bind(
name = "python_headers",
actual = "@local_config_python//:python_headers",
)
# Java support (with junit 5)
## Bazel Java rules.
git_repository(

View File

@@ -103,9 +103,9 @@ if(BUILD_Protobuf)
FetchContent_Declare(
protobuf
GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git"
GIT_TAG "v23.2"
GIT_TAG "v23.3"
GIT_SUBMODULES ""
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/protobuf-v23.2.patch")
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/protobuf-v23.3.patch")
FetchContent_MakeAvailable(protobuf)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
@@ -171,6 +171,23 @@ if(BUILD_PYTHON AND BUILD_pybind11)
message(CHECK_PASS "fetched")
endif()
if(BUILD_PYTHON AND BUILD_pybind11_protobuf)
message(CHECK_START "Fetching pybind11_protobuf")
list(APPEND CMAKE_MESSAGE_INDENT " ")
#set(PYBIND11_INSTALL ON)
#set(PYBIND11_TEST OFF)
FetchContent_Declare(
pybind11_protobuf
GIT_REPOSITORY "https://github.com/pybind/pybind11_protobuf.git"
GIT_TAG "main"
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/pybind11_protobuf.patch"
)
FetchContent_MakeAvailable(pybind11_protobuf)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif()
# ##############################################################################
# GLPK
# ##############################################################################

View File

@@ -153,4 +153,8 @@ if(BUILD_PYTHON)
if(NOT BUILD_pybind11)
find_package(pybind11 REQUIRED)
endif()
if(NOT BUILD_pybind11_protobuf)
find_package(pybind11_protobuf REQUIRED)
endif()
endif()

View File

@@ -268,6 +268,7 @@ file(COPY
file(COPY
ortools/linear_solver/python/model_builder.py
ortools/linear_solver/python/model_builder_helper.py
ortools/linear_solver/python/pandas_model.py
DESTINATION ${PYTHON_PROJECT_DIR}/linear_solver/python)
file(COPY
ortools/sat/python/cp_model.py

View File

@@ -59,6 +59,7 @@ cc_library(
":graph",
"//ortools/base:hash",
"//ortools/base:map_util",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/container:inlined_vector",
],
)

View File

@@ -25,6 +25,7 @@
#include <utility>
#include <vector>
#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/inlined_vector.h"
#include "ortools/base/hash.h"
@@ -353,7 +354,7 @@ void RemoveCyclesFromPath(const Graph& graph, std::vector<int>* arc_path) {
if (arc_path->empty()) return;
// This maps each node to the latest arc in the given path that leaves it.
std::map<int, int> last_arc_leaving_node;
absl::btree_map<int, int> last_arc_leaving_node;
for (const int arc : *arc_path) last_arc_leaving_node[graph.Tail(arc)] = arc;
// Special case for the destination.

View File

@@ -15,12 +15,8 @@
#define OR_TOOLS_LINEAR_SOLVER_MODEL_EXPORTER_H_
#include <string>
#include <vector>
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "ortools/base/hash.h"
#include "ortools/base/macros.h"
#include "ortools/linear_solver/linear_solver.pb.h"
namespace operations_research {

View File

@@ -26,6 +26,7 @@ pybind_extension(
"//ortools/linear_solver/wrappers:model_builder_helper",
"@com_google_absl//absl/strings",
"@eigen//:eigen3",
"@pybind11_protobuf//pybind11_protobuf:native_proto_caster",
],
)
@@ -83,3 +84,25 @@ py_test(
requirement("numpy"),
],
)
py_library(
name = "pandas_model",
srcs = ["pandas_model.py"],
deps = [
":pywrap_model_builder_helper",
requirement("numpy"),
requirement("pandas"),
"//ortools/linear_solver:linear_solver_py_pb2",
],
)
py_test(
name = "pandas_model_test",
srcs = ["pandas_model_test.py"],
deps = [
":pandas_model",
requirement("absl-py"),
requirement("pandas"),
"//ortools/linear_solver:linear_solver_py_pb2",
],
)

View File

@@ -48,6 +48,9 @@ endif()
pybind11_add_module(pywrap_model_builder_helper MODULE pywrap_model_builder_helper.cc)
target_include_directories(pywrap_model_builder_helper PRIVATE
${protobuf_SOURCE_DIR})
# note: macOS is APPLE and also UNIX !
if(APPLE)
set_target_properties(pywrap_model_builder_helper PROPERTIES
@@ -63,7 +66,11 @@ elseif(UNIX)
)
endif()
target_link_libraries(pywrap_model_builder_helper PRIVATE ${PROJECT_NAMESPACE}::ortools)
target_link_libraries(pywrap_model_builder_helper PRIVATE
${PROJECT_NAMESPACE}::ortools
pybind11_native_proto_caster
)
add_library(${PROJECT_NAMESPACE}::pywrap_model_builder_helper ALIAS pywrap_model_builder_helper)
if(BUILD_TESTING)

File diff suppressed because it is too large Load Diff

View File

@@ -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_builder module."""
import numbers
@@ -28,32 +29,32 @@ def is_integral(x: Any) -> bool:
def is_a_number(x: Any) -> bool:
"""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: Any) -> bool:
"""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: Any) -> bool:
"""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: Any) -> bool:
"""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_a_number(x: NumberT) -> np.double:
"""Asserts that x is a number and converts to a np.double."""
if not is_a_number(x):
raise TypeError('Not a number: %s' % x)
raise TypeError("Not a number: %s" % x)
return np.double(x)

View File

@@ -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 model_builder_helper."""
import gzip
@@ -25,36 +26,35 @@ from ortools.linear_solver.python import pywrap_model_builder_helper
class PywrapModelBuilderHelperTest(unittest.TestCase):
def test_export_model_proto_to_mps_string(self):
model = pywrap_model_builder_helper.ModelBuilderHelper()
model.set_name('testmodel')
model.set_name("testmodel")
result = model.export_to_mps_string()
self.assertIn('testmodel', result)
self.assertIn('ENDATA', result)
self.assertIn("testmodel", result)
self.assertIn("ENDATA", result)
def test_export_model_proto_to_lp_string(self):
model = pywrap_model_builder_helper.ModelBuilderHelper()
model.set_maximize(True)
lp_string = model.export_to_lp_string()
self.assertIn('Maximize', lp_string)
self.assertIn("Maximize", lp_string)
def test_import_from_mps_string(self):
model = pywrap_model_builder_helper.ModelBuilderHelper()
self.assertTrue(model.import_from_mps_string('NAME testmodel'))
self.assertEqual(model.name(), 'testmodel')
self.assertTrue(model.import_from_mps_string("NAME testmodel"))
self.assertEqual(model.name(), "testmodel")
# ImportFromMpsFile doesn't read from files yet
def test_import_from_mps_file(self):
path = os.path.dirname(__file__)
mps_path = f'{path}/../testdata/maximization.mps'
mps_path = f"{path}/../testdata/maximization.mps"
model = pywrap_model_builder_helper.ModelBuilderHelper()
self.assertTrue(model.import_from_mps_file(mps_path))
self.assertEqual(model.name(), 'SupportedMaximizationProblem')
self.assertEqual(model.name(), "SupportedMaximizationProblem")
def test_import_from_lp_string(self):
model = pywrap_model_builder_helper.ModelBuilderHelper()
model.import_from_lp_string('max:')
model.import_from_lp_string("max:")
self.assertTrue(model.maximize())
# TODO(user): Add test_import_from_lp_file after the implementation is fixed
@@ -62,21 +62,21 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
def test_solve_with_glop(self):
model = linear_solver_pb2.MPModelProto()
model.variable.append(
linear_solver_pb2.MPVariableProto(lower_bound=0.0,
upper_bound=1.0,
objective_coefficient=1.0))
linear_solver_pb2.MPVariableProto(
lower_bound=0.0, upper_bound=1.0, objective_coefficient=1.0
)
)
model.maximize = True
request = linear_solver_pb2.MPModelRequest(
model=model,
solver_type=linear_solver_pb2.MPModelRequest.GLOP_LINEAR_PROGRAMMING
solver_type=linear_solver_pb2.MPModelRequest.GLOP_LINEAR_PROGRAMMING,
)
solver_helper = pywrap_model_builder_helper.ModelSolverHelper('')
result = solver_helper.solve_serialized_request(
request.SerializeToString())
solver_helper = pywrap_model_builder_helper.ModelSolverHelper("")
result = solver_helper.solve_serialized_request(request.SerializeToString())
response = linear_solver_pb2.MPSolutionResponse().FromString(result)
self.assertEqual(
response.status,
linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL)
response.status, linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL
)
self.assertAlmostEqual(response.objective_value, 1.0)
def test_solve_with_glop_direct(self):
@@ -87,11 +87,11 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
model.set_var_objective_coefficient(0, 1.0)
model.set_maximize(True)
solver = pywrap_model_builder_helper.ModelSolverHelper('glop')
solver = pywrap_model_builder_helper.ModelSolverHelper("glop")
solver.solve(model)
self.assertEqual(
solver.status(),
linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL)
solver.status(), linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL
)
self.assertAlmostEqual(solver.objective_value(), 1.0)
self.assertAlmostEqual(solver.var_value(0), 1.0)
values = solver.variable_values()
@@ -101,17 +101,17 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
def test_solve_with_pdlp(self):
model = linear_solver_pb2.MPModelProto()
model.variable.append(
linear_solver_pb2.MPVariableProto(lower_bound=0.0,
upper_bound=1.0,
objective_coefficient=1.0))
linear_solver_pb2.MPVariableProto(
lower_bound=0.0, upper_bound=1.0, objective_coefficient=1.0
)
)
model.maximize = True
request = linear_solver_pb2.MPModelRequest(
model=model,
solver_type=linear_solver_pb2.MPModelRequest.PDLP_LINEAR_PROGRAMMING
solver_type=linear_solver_pb2.MPModelRequest.PDLP_LINEAR_PROGRAMMING,
)
solver_helper = pywrap_model_builder_helper.ModelSolverHelper('')
result = solver_helper.solve_serialized_request(
request.SerializeToString())
solver_helper = pywrap_model_builder_helper.ModelSolverHelper("")
result = solver_helper.solve_serialized_request(request.SerializeToString())
if result:
response = linear_solver_pb2.MPSolutionResponse().FromString(result)
self.assertEqual(
@@ -120,30 +120,32 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
)
self.assertAlmostEqual(response.objective_value, 1.0)
else:
print('Solver not supported.')
print("Solver not supported.")
# TODO(user): Test the log callback after the implementation is completed.
def test_interrupt_solve(self):
# This is an instance that we know Glop won't solve quickly.
path = os.path.dirname(__file__)
mps_path = f'{path}/../testdata/large_model.mps.gz'
with gzip.open(mps_path, 'r') as f:
mps_path = f"{path}/../testdata/large_model.mps.gz"
with gzip.open(mps_path, "r") as f:
mps_data = f.read()
model_helper = pywrap_model_builder_helper.ModelBuilderHelper()
self.assertTrue(model_helper.import_from_mps_string(mps_data))
solver_helper = pywrap_model_builder_helper.ModelSolverHelper('glop')
solver_helper = pywrap_model_builder_helper.ModelSolverHelper("glop")
result = []
solve_thread = threading.Thread(
target=lambda: result.append(solver_helper.solve(model_helper)))
target=lambda: result.append(solver_helper.solve(model_helper))
)
solve_thread.start()
self.assertTrue(solver_helper.interrupt_solve())
solve_thread.join(timeout=30.0)
self.assertTrue(solver_helper.has_response())
self.assertEqual(
solver_helper.status(),
pywrap_model_builder_helper.SolveStatus.CANCELLED_BY_USER)
pywrap_model_builder_helper.SolveStatus.CANCELLED_BY_USER,
)
def test_build_model(self):
var_lb = np.array([-1.0])
@@ -154,8 +156,9 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
constraint_matrix = sparse.csr_matrix(np.array([[1.0], [2.0]]))
model = pywrap_model_builder_helper.ModelBuilderHelper()
model.fill_model_from_sparse_data(var_lb, var_ub, obj, con_lb, con_ub,
constraint_matrix)
model.fill_model_from_sparse_data(
var_lb, var_ub, obj, con_lb, con_ub, constraint_matrix
)
self.assertEqual(1, model.num_variables())
self.assertEqual(-1.0, model.var_lower_bound(0))
self.assertEqual(np.inf, model.var_upper_bound(0))
@@ -172,12 +175,12 @@ class PywrapModelBuilderHelperTest(unittest.TestCase):
self.assertEqual([0], model.constraint_var_indices(1))
self.assertEqual([2.0], model.constraint_coefficients(1))
var_array = model.add_var_array([10], 1.0, 5.0, True, 'var_')
var_array = model.add_var_array([10], 1.0, 5.0, True, "var_")
self.assertEqual(1, var_array.ndim)
self.assertEqual(10, var_array.size)
self.assertEqual((10,), var_array.shape)
self.assertEqual(model.var_name(var_array[3]), 'var_3')
self.assertEqual(model.var_name(var_array[3]), "var_3")
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View File

@@ -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 ModelBuilder."""
import math
@@ -31,10 +32,10 @@ class ModelBuilderTest(unittest.TestCase):
def run_minimal_linear_example(self, solver_name):
"""Minimal Linear Example."""
model = mb.ModelBuilder()
model.name = 'minimal_linear_example'
x1 = model.new_num_var(0.0, math.inf, 'x1')
x2 = model.new_num_var(0.0, math.inf, 'x2')
x3 = model.new_num_var(0.0, math.inf, 'x3')
model.name = "minimal_linear_example"
x1 = model.new_num_var(0.0, math.inf, "x1")
x2 = model.new_num_var(0.0, math.inf, "x2")
x3 = model.new_num_var(0.0, math.inf, "x3")
self.assertEqual(3, model.num_variables)
self.assertFalse(x1.is_integral)
self.assertEqual(0.0, x1.lower_bound)
@@ -50,8 +51,8 @@ class ModelBuilderTest(unittest.TestCase):
c0 = model.add(x1 + x2 + x3 <= 100.0)
self.assertEqual(100, c0.upper_bound)
c1 = model.add(10 * x1 + 4.0 * x2 + 5.0 * x3 <= 600.0, 'c1')
self.assertEqual('c1', c1.name)
c1 = model.add(10 * x1 + 4.0 * x2 + 5.0 * x3 <= 600.0, "c1")
self.assertEqual("c1", c1.name)
c2 = model.add(2.0 * x1 + 2.0 * x2 + 6.0 * x3 <= 300.0)
self.assertEqual(-math.inf, c2.lower_bound)
@@ -59,61 +60,50 @@ class ModelBuilderTest(unittest.TestCase):
self.assertEqual(mb.SolveStatus.OPTIMAL, solver.solve(model))
# The problem has an optimal solution.
self.assertAlmostEqual(733.333333 + model.objective_offset,
solver.objective_value,
places=self.NUM_PLACES)
self.assertAlmostEqual(
733.333333 + model.objective_offset,
solver.objective_value,
places=self.NUM_PLACES,
)
self.assertAlmostEqual(
solver.value(10.0 * x1 + 6 * x2 + 4.0 * x3 - 5.5),
solver.objective_value,
places=self.NUM_PLACES,
)
self.assertAlmostEqual(33.333333,
solver.value(x1),
places=self.NUM_PLACES)
self.assertAlmostEqual(66.666667,
solver.value(x2),
places=self.NUM_PLACES)
self.assertAlmostEqual(33.333333, solver.value(x1), places=self.NUM_PLACES)
self.assertAlmostEqual(66.666667, solver.value(x2), places=self.NUM_PLACES)
self.assertAlmostEqual(0.0, solver.value(x3), places=self.NUM_PLACES)
dual_objective_value = (solver.dual_value(c0) * c0.upper_bound +
solver.dual_value(c1) * c1.upper_bound +
solver.dual_value(c2) * c2.upper_bound +
model.objective_offset)
self.assertAlmostEqual(solver.objective_value,
dual_objective_value,
places=self.NUM_PLACES)
dual_objective_value = (
solver.dual_value(c0) * c0.upper_bound
+ solver.dual_value(c1) * c1.upper_bound
+ solver.dual_value(c2) * c2.upper_bound
+ model.objective_offset
)
self.assertAlmostEqual(
solver.objective_value, dual_objective_value, places=self.NUM_PLACES
)
# x1 and x2 are basic
self.assertAlmostEqual(0.0,
solver.reduced_cost(x1),
places=self.NUM_PLACES)
self.assertAlmostEqual(0.0,
solver.reduced_cost(x2),
places=self.NUM_PLACES)
self.assertAlmostEqual(0.0, solver.reduced_cost(x1), places=self.NUM_PLACES)
self.assertAlmostEqual(0.0, solver.reduced_cost(x2), places=self.NUM_PLACES)
# x3 is non-basic
x3_expected_reduced_cost = (4.0 - 1.0 * solver.dual_value(c0) -
5.0 * solver.dual_value(c1))
self.assertAlmostEqual(x3_expected_reduced_cost,
solver.reduced_cost(x3),
places=self.NUM_PLACES)
x3_expected_reduced_cost = (
4.0 - 1.0 * solver.dual_value(c0) - 5.0 * solver.dual_value(c1)
)
self.assertAlmostEqual(
x3_expected_reduced_cost, solver.reduced_cost(x3), places=self.NUM_PLACES
)
self.assertAlmostEqual(100.0,
solver.activity(c0),
places=self.NUM_PLACES)
self.assertAlmostEqual(600.0,
solver.activity(c1),
places=self.NUM_PLACES)
self.assertAlmostEqual(200.0,
solver.activity(c2),
places=self.NUM_PLACES)
self.assertAlmostEqual(100.0, solver.activity(c0), places=self.NUM_PLACES)
self.assertAlmostEqual(600.0, solver.activity(c1), places=self.NUM_PLACES)
self.assertAlmostEqual(200.0, solver.activity(c2), places=self.NUM_PLACES)
self.assertIn('minimal_linear_example',
model.export_to_lp_string(False))
self.assertIn('minimal_linear_example',
model.export_to_mps_string(False))
self.assertIn("minimal_linear_example", model.export_to_lp_string(False))
self.assertIn("minimal_linear_example", model.export_to_mps_string(False))
def test_minimal_linear_example(self):
self.run_minimal_linear_example('glop')
self.run_minimal_linear_example("glop")
def test_import_from_mps_string(self):
mps_data = """
@@ -138,14 +128,14 @@ ENDATA
"""
model = mb.ModelBuilder()
self.assertTrue(model.import_from_mps_string(mps_data))
self.assertEqual(model.name, 'SupportedMaximizationProblem')
self.assertEqual(model.name, "SupportedMaximizationProblem")
def test_import_from_mps_file(self):
path = os.path.dirname(__file__)
mps_path = f'{path}/../testdata/maximization.mps'
mps_path = f"{path}/../testdata/maximization.mps"
model = mb.ModelBuilder()
self.assertTrue(model.import_from_mps_file(mps_path))
self.assertEqual(model.name, 'SupportedMaximizationProblem')
self.assertEqual(model.name, "SupportedMaximizationProblem")
def test_import_from_lp_string(self):
lp_data = """
@@ -162,80 +152,88 @@ ENDATA
self.assertEqual(3, model.num_constraints)
self.assertEqual(1, model.var_from_index(0).lower_bound)
self.assertEqual(42, model.var_from_index(0).upper_bound)
self.assertEqual('x', model.var_from_index(0).name)
self.assertEqual("x", model.var_from_index(0).name)
def test_import_from_lp_file(self):
path = os.path.dirname(__file__)
lp_path = f'{path}/../testdata/small_model.lp'
lp_path = f"{path}/../testdata/small_model.lp"
model = mb.ModelBuilder()
self.assertTrue(model.import_from_lp_file(lp_path))
self.assertEqual(6, model.num_variables)
self.assertEqual(3, model.num_constraints)
self.assertEqual(1, model.var_from_index(0).lower_bound)
self.assertEqual(42, model.var_from_index(0).upper_bound)
self.assertEqual('x', model.var_from_index(0).name)
self.assertEqual("x", model.var_from_index(0).name)
def test_class_api(self):
model = mb.ModelBuilder()
x = model.new_int_var(0, 10, 'x')
y = model.new_int_var(1, 10, 'y')
z = model.new_int_var(2, 10, 'z')
t = model.new_int_var(3, 10, 't')
x = model.new_int_var(0, 10, "x")
y = model.new_int_var(1, 10, "y")
z = model.new_int_var(2, 10, "z")
t = model.new_int_var(3, 10, "t")
e1 = mb.LinearExpr.sum([x, y, z])
expected_vars = np.array([0, 1, 2], dtype=np.int32)
np_testing.assert_array_equal(expected_vars, e1.variable_indices)
np_testing.assert_array_equal(np.array([1, 1, 1], dtype=np.double),
e1.coefficients)
np_testing.assert_array_equal(
np.array([1, 1, 1], dtype=np.double), e1.coefficients
)
self.assertEqual(e1.constant, 0.0)
self.assertEqual(e1.pretty_string(model.helper), 'x + y + z')
self.assertEqual(e1.pretty_string(model.helper), "x + y + z")
e2 = mb.LinearExpr.sum([e1, 4.0])
np_testing.assert_array_equal(expected_vars, e2.variable_indices)
np_testing.assert_array_equal(np.array([1, 1, 1], dtype=np.double),
e2.coefficients)
np_testing.assert_array_equal(
np.array([1, 1, 1], dtype=np.double), e2.coefficients
)
self.assertEqual(e2.constant, 4.0)
self.assertEqual(e2.pretty_string(model.helper), 'x + y + z + 4.0')
self.assertEqual(e2.pretty_string(model.helper), "x + y + z + 4.0")
e3 = mb.LinearExpr.term(e2, 2)
np_testing.assert_array_equal(expected_vars, e3.variable_indices)
np_testing.assert_array_equal(np.array([2, 2, 2], dtype=np.double),
e3.coefficients)
np_testing.assert_array_equal(
np.array([2, 2, 2], dtype=np.double), e3.coefficients
)
self.assertEqual(e3.constant, 8.0)
self.assertEqual(e3.pretty_string(model.helper),
'2.0 * x + 2.0 * y + 2.0 * z + 8.0')
self.assertEqual(
e3.pretty_string(model.helper), "2.0 * x + 2.0 * y + 2.0 * z + 8.0"
)
e4 = mb.LinearExpr.weighted_sum([x, t], [-1, 1], constant=2)
np_testing.assert_array_equal(np.array([0, 3], dtype=np.int32),
e4.variable_indices)
np_testing.assert_array_equal(np.array([-1, 1], dtype=np.double),
e4.coefficients)
np_testing.assert_array_equal(
np.array([0, 3], dtype=np.int32), e4.variable_indices
)
np_testing.assert_array_equal(
np.array([-1, 1], dtype=np.double), e4.coefficients
)
self.assertEqual(e4.constant, 2.0)
self.assertEqual(e4.pretty_string(model.helper), '-x + t + 2.0')
self.assertEqual(e4.pretty_string(model.helper), "-x + t + 2.0")
e4b = e4 * 3.0
np_testing.assert_array_equal(np.array([0, 3], dtype=np.int32),
e4b.variable_indices)
np_testing.assert_array_equal(np.array([-3, 3], dtype=np.double),
e4b.coefficients)
np_testing.assert_array_equal(
np.array([0, 3], dtype=np.int32), e4b.variable_indices
)
np_testing.assert_array_equal(
np.array([-3, 3], dtype=np.double), e4b.coefficients
)
self.assertEqual(e4b.constant, 6.0)
self.assertEqual(e4b.pretty_string(model.helper),
'-3.0 * x + 3.0 * t + 6.0')
self.assertEqual(e4b.pretty_string(model.helper), "-3.0 * x + 3.0 * t + 6.0")
e5 = mb.LinearExpr.sum([e1, -3, e4])
np_testing.assert_array_equal(np.array([0, 1, 2, 0, 3], dtype=np.int32),
e5.variable_indices)
np_testing.assert_array_equal(
np.array([1, 1, 1, -1, 1], dtype=np.double), e5.coefficients)
np.array([0, 1, 2, 0, 3], dtype=np.int32), e5.variable_indices
)
np_testing.assert_array_equal(
np.array([1, 1, 1, -1, 1], dtype=np.double), e5.coefficients
)
self.assertEqual(e5.constant, -1.0)
self.assertEqual(e5.pretty_string(model.helper),
'x + y + z - x + t - 1.0')
self.assertEqual(e5.pretty_string(model.helper), "x + y + z - x + t - 1.0")
e6 = mb.LinearExpr.term(x, 2.0, constant=1.0)
np_testing.assert_array_equal(np.array([0], dtype=np.int32),
e6.variable_indices)
np_testing.assert_array_equal(np.array([2], dtype=np.double),
e6.coefficients)
np_testing.assert_array_equal(
np.array([0], dtype=np.int32), e6.variable_indices
)
np_testing.assert_array_equal(np.array([2], dtype=np.double), e6.coefficients)
self.assertEqual(e6.constant, 1.0)
e7 = mb.LinearExpr.term(x, 1.0, constant=0.0)
@@ -246,11 +244,11 @@ ENDATA
def test_variables(self):
model = mb.ModelBuilder()
x = model.new_int_var(0.0, 4.0, 'x')
x = model.new_int_var(0.0, 4.0, "x")
self.assertEqual(0, x.index)
self.assertEqual(0.0, x.lower_bound)
self.assertEqual(4.0, x.upper_bound)
self.assertEqual('x', x.name)
self.assertEqual("x", x.name)
x.lower_bound = 1.0
x.upper_bound = 3.0
self.assertEqual(1.0, x.lower_bound)
@@ -258,35 +256,32 @@ ENDATA
self.assertTrue(x.is_integral)
# Tests the equality operator.
y = model.new_int_var(0.0, 4.0, 'y')
y = model.new_int_var(0.0, 4.0, "y")
x_copy = model.var_from_index(0)
self.assertEqual(x, x)
self.assertEqual(x, x_copy)
self.assertNotEqual(x, y)
# array
xs = model.new_int_var_array(shape=10,
lower_bounds=0.0,
upper_bounds=5.0,
name='xs_')
xs = model.new_int_var_array(
shape=10, lower_bounds=0.0, upper_bounds=5.0, name="xs_"
)
self.assertEqual(10, xs.size)
self.assertEqual('xs_4', str(xs[4]))
self.assertEqual("xs_4", str(xs[4]))
lbs = np.array([1.0, 2.0, 3.0])
ubs = [3.0, 4.0, 5.0]
ys = model.new_int_var_array(lower_bounds=lbs,
upper_bounds=ubs,
name='ys_')
self.assertEqual('VariableContainer([12 13 14])', str(ys))
zs = model.new_int_var_array(lower_bounds=[1.0, 2.0, 3],
upper_bounds=[4, 4, 4],
name='zs_')
ys = model.new_int_var_array(lower_bounds=lbs, upper_bounds=ubs, name="ys_")
self.assertEqual("VariableContainer([12 13 14])", str(ys))
zs = model.new_int_var_array(
lower_bounds=[1.0, 2.0, 3], upper_bounds=[4, 4, 4], name="zs_"
)
self.assertEqual(3, zs.size)
self.assertEqual((3,), zs.shape)
self.assertEqual('zs_1', str(zs[1]))
self.assertEqual('zs_2(index=17, lb=3.0, ub=4.0, integer)', repr(zs[2]))
self.assertEqual("zs_1", str(zs[1]))
self.assertEqual("zs_2(index=17, lb=3.0, ub=4.0, integer)", repr(zs[2]))
self.assertTrue(zs[2].is_integral)
bs = model.new_bool_var_array([4, 5], 'bs_')
bs = model.new_bool_var_array([4, 5], "bs_")
self.assertEqual((4, 5), bs.shape)
self.assertEqual((5, 4), bs.T.shape)
self.assertEqual(31, bs.index_at((2, 3)))
@@ -300,31 +295,33 @@ ENDATA
sum_bs = np.sum(bs)
self.assertEqual(20, sum_bs.variable_indices.size)
np_testing.assert_array_equal(sum_bs.variable_indices,
bs.variable_indices.flatten())
np_testing.assert_array_equal(
sum_bs.variable_indices, bs.variable_indices.flatten()
)
np_testing.assert_array_equal(sum_bs.coefficients, np.ones(20))
sum_bs_cte = np.sum(bs, 2.2)
self.assertEqual(20, sum_bs_cte.variable_indices.size)
np_testing.assert_array_equal(sum_bs_cte.variable_indices,
bs.variable_indices.flatten())
np_testing.assert_array_equal(
sum_bs_cte.variable_indices, bs.variable_indices.flatten()
)
np_testing.assert_array_equal(sum_bs.coefficients, np.ones(20))
self.assertEqual(sum_bs_cte.constant, 2.2)
times_bs = np.dot(bs[1], 4)
np_testing.assert_array_equal(times_bs.variable_indices,
bs[1].variable_indices.flatten())
np_testing.assert_array_equal(
times_bs.variable_indices, bs[1].variable_indices.flatten()
)
np_testing.assert_array_equal(times_bs.coefficients, np.full(5, 4.0))
times_bs_rev = np.dot(4, bs[2])
np_testing.assert_array_equal(times_bs_rev.variable_indices,
bs[2].variable_indices.flatten())
np_testing.assert_array_equal(times_bs_rev.coefficients,
np.full(5, 4.0))
np_testing.assert_array_equal(
times_bs_rev.variable_indices, bs[2].variable_indices.flatten()
)
np_testing.assert_array_equal(times_bs_rev.coefficients, np.full(5, 4.0))
dot_bs = np.dot(bs[2], np.array([1, 2, 3, 4, 5], dtype=np.double))
np_testing.assert_array_equal(dot_bs.variable_indices,
bs[2].variable_indices)
np_testing.assert_array_equal(dot_bs.variable_indices, bs[2].variable_indices)
np_testing.assert_array_equal(dot_bs.coefficients, [1, 2, 3, 4, 5])
# Tests the hash method.
@@ -349,7 +346,7 @@ ENDATA
lower_bounds=[[0.0, 1.0, 2.0], [0.0, 0.0, 2.0]],
upper_bounds=4.0,
is_integral=False,
name='y',
name="y",
)
np_testing.assert_array_equal(y.shape, [2, 3])
@@ -357,7 +354,7 @@ ENDATA
lower_bounds=0.0,
upper_bounds=[[2.0, 1.0, 2.0], [3.0, 4.0, 2.0]],
is_integral=False,
name='z',
name="z",
)
np_testing.assert_array_equal(z.shape, [2, 3])
@@ -419,14 +416,14 @@ ENDATA
y = model.new_num_var_array(
lower_bounds=[[0.0, 1.0, 2.0], [0.0, 0.0, 2.0]],
upper_bounds=4.0,
name='y',
name="y",
)
np_testing.assert_array_equal(y.shape, [2, 3])
z = model.new_num_var_array(
lower_bounds=0.0,
upper_bounds=[[2.0, 1.0, 2.0], [3.0, 4.0, 2.0]],
name='z',
name="z",
)
np_testing.assert_array_equal(z.shape, [2, 3])
@@ -469,14 +466,14 @@ ENDATA
y = model.new_int_var_array(
lower_bounds=[[0.0, 1.0, 2.0], [0.0, 0.0, 2.0]],
upper_bounds=4.0,
name='y',
name="y",
)
np_testing.assert_array_equal(y.shape, [2, 3])
z = model.new_int_var_array(
lower_bounds=0.0,
upper_bounds=[[2.0, 1.0, 2.0], [3.0, 4.0, 2.0]],
name='z',
name="z",
)
np_testing.assert_array_equal(z.shape, [2, 3])
@@ -508,12 +505,12 @@ ENDATA
def test_duplicate_variables(self):
model = mb.ModelBuilder()
x = model.new_int_var(0.0, 4.0, 'x')
y = model.new_int_var(0.0, 4.0, 'y')
z = model.new_int_var(0.0, 4.0, 'z')
x = model.new_int_var(0.0, 4.0, "x")
y = model.new_int_var(0.0, 4.0, "y")
z = model.new_int_var(0.0, 4.0, "z")
model.add(x + 2 * y == x - z)
model.minimize(x + y + z)
solver = mb.ModelSolver('sat')
solver = mb.ModelSolver("sat")
self.assertEqual(mb.SolveStatus.OPTIMAL, solver.solve(model))
def test_issue_3614(self):
@@ -532,27 +529,34 @@ ENDATA
y = {}
v = {}
for i in range(total_number_of_choices):
y[i] = model.new_bool_var(f'y_{i}')
y[i] = model.new_bool_var(f"y_{i}")
for j in range(total_unique_products):
for i in range(len(standalone_features)):
v[i, j] = model.new_bool_var(f'v_{(i,j)}')
model.add(v[i, j] == (y[i] +
(feature_bundle_incidence_matrix[(i, 0)] *
y[bundle_start_idx])))
v[i, j] = model.new_bool_var(f"v_{(i,j)}")
model.add(
v[i, j]
== (
y[i]
+ (
feature_bundle_incidence_matrix[(i, 0)]
* y[bundle_start_idx]
)
)
)
solver = mb.ModelSolver('sat')
solver = mb.ModelSolver("sat")
status = solver.solve(model)
self.assertEqual(mb.SolveStatus.OPTIMAL, status)
def test_varcompvar(self):
model = mb.ModelBuilder()
x = model.new_int_var(0.0, 4.0, 'x')
y = model.new_int_var(0.0, 4.0, 'y')
x = model.new_int_var(0.0, 4.0, "x")
y = model.new_int_var(0.0, 4.0, "y")
ct = x == y
self.assertEqual(ct.left.index, x.index)
self.assertEqual(ct.right.index, y.index)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,7 @@
#include "pybind11/pybind11.h"
#include "pybind11/pytypes.h"
#include "pybind11/stl.h"
#include "pybind11_protobuf/native_proto_caster.h"
using ::Eigen::SparseMatrix;
using ::Eigen::VectorXd;
@@ -52,6 +53,10 @@ using ::operations_research::SolveStatus;
namespace py = pybind11;
using ::py::arg;
const MPModelProto& ToMPModelProto(ModelBuilderHelper* helper) {
return helper->model();
}
// TODO(user): The interface uses serialized protos because of issues building
// pybind11_protobuf. See
// https://github.com/protocolbuffers/protobuf/issues/9464. After
@@ -146,6 +151,10 @@ std::vector<std::pair<int, double>> SortedGroupedTerms(
}
PYBIND11_MODULE(pywrap_model_builder_helper, m) {
pybind11_protobuf::ImportNativeProtoCasters();
m.def("to_mpmodel_proto", &ToMPModelProto, arg("helper"));
py::class_<MPModelExportOptions>(m, "MPModelExportOptions")
.def(py::init<>())
.def_readwrite("obfuscate", &MPModelExportOptions::obfuscate)

18
ortools/linear_solver/python/pywraplp_test.py Executable file → Normal file
View File

@@ -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/linear_solver.i. Not exhaustive."""
import unittest
@@ -41,11 +42,10 @@ constraint {
class PyWrapLp(unittest.TestCase):
def test_proto(self):
input_proto = linear_solver_pb2.MPModelProto()
text_format.Merge(TEXT_MODEL, input_proto)
solver = pywraplp.Solver.CreateSolver('CBC')
solver = pywraplp.Solver.CreateSolver("CBC")
if not solver:
return
# For now, create the model from the proto by parsing the proto
@@ -61,23 +61,23 @@ class PyWrapLp(unittest.TestCase):
self.assertEqual(solution.best_objective_bound, 3.0)
def test_external_api(self):
solver = pywraplp.Solver.CreateSolver('GLOP')
solver = pywraplp.Solver.CreateSolver("GLOP")
infinity = solver.Infinity()
infinity2 = solver.infinity()
self.assertEqual(infinity, infinity2)
# x1, x2 and x3 are continuous non-negative variables.
x1 = solver.NumVar(0.0, infinity, 'x1')
x2 = solver.NumVar(0.0, infinity, 'x2')
x3 = solver.NumVar(0.0, infinity, 'x3')
x1 = solver.NumVar(0.0, infinity, "x1")
x2 = solver.NumVar(0.0, infinity, "x2")
x3 = solver.NumVar(0.0, infinity, "x3")
self.assertEqual(x1.Lb(), 0)
self.assertEqual(x1.Ub(), infinity)
self.assertFalse(x1.Integer())
solver.Maximize(10 * x1 + 6 * x2 + 4 * x3 + 5)
self.assertEqual(solver.Objective().Offset(), 5)
c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, 'ConstraintName0')
c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, "ConstraintName0")
c1 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300)
sum_of_vars = sum([x1, x2, x3])
solver.Add(sum_of_vars <= 100.0, 'OtherConstraintName')
solver.Add(sum_of_vars <= 100.0, "OtherConstraintName")
self.assertEqual(c1.Lb(), -infinity)
self.assertEqual(c1.Ub(), 300)
c1.SetLb(-100000)
@@ -94,5 +94,5 @@ class PyWrapLp(unittest.TestCase):
self.assertAlmostEqual(c0.DualValue(), 0.6666666666666667)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

35
ortools/linear_solver/samples/assignment_groups_mip.py Executable file → Normal file
View File

@@ -70,7 +70,7 @@ def main():
# Solver.
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
# [END solver]
@@ -82,31 +82,30 @@ def main():
x = {}
for worker in range(num_workers):
for task in range(num_tasks):
x[worker, task] = solver.BoolVar(f'x[{worker},{task}]')
x[worker, task] = solver.BoolVar(f"x[{worker},{task}]")
# [END variables]
# Constraints
# [START constraints]
# The total size of the tasks each worker takes on is at most total_size_max.
for worker in range(num_workers):
solver.Add(
solver.Sum([x[worker, task] for task in range(num_tasks)]) <= 1)
solver.Add(solver.Sum([x[worker, task] for task in range(num_tasks)]) <= 1)
# Each task is assigned to exactly one worker.
for task in range(num_tasks):
solver.Add(
solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
solver.Add(solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
# [END constraints]
# [START assignments]
# Create variables for each worker, indicating whether they work on some task.
work = {}
for worker in range(num_workers):
work[worker] = solver.BoolVar(f'work[{worker}]')
work[worker] = solver.BoolVar(f"work[{worker}]")
for worker in range(num_workers):
solver.Add(work[worker] == solver.Sum(
[x[worker, task] for task in range(num_tasks)]))
solver.Add(
work[worker] == solver.Sum([x[worker, task] for task in range(num_tasks)])
)
# Group1
constraint_g1 = solver.Constraint(1, 1)
@@ -116,7 +115,7 @@ def main():
constraint = solver.Constraint(0, 1)
constraint.SetCoefficient(work[group1[i][0]], 1)
constraint.SetCoefficient(work[group1[i][1]], 1)
p = solver.BoolVar(f'g1_p{i}')
p = solver.BoolVar(f"g1_p{i}")
constraint.SetCoefficient(p, -2)
constraint_g1.SetCoefficient(p, 1)
@@ -129,7 +128,7 @@ def main():
constraint = solver.Constraint(0, 1)
constraint.SetCoefficient(work[group2[i][0]], 1)
constraint.SetCoefficient(work[group2[i][1]], 1)
p = solver.BoolVar(f'g2_p{i}')
p = solver.BoolVar(f"g2_p{i}")
constraint.SetCoefficient(p, -2)
constraint_g2.SetCoefficient(p, 1)
@@ -142,7 +141,7 @@ def main():
constraint = solver.Constraint(0, 1)
constraint.SetCoefficient(work[group3[i][0]], 1)
constraint.SetCoefficient(work[group3[i][1]], 1)
p = solver.BoolVar(f'g3_p{i}')
p = solver.BoolVar(f"g3_p{i}")
constraint.SetCoefficient(p, -2)
constraint_g3.SetCoefficient(p, 1)
@@ -165,17 +164,19 @@ def main():
# Print solution.
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
print(f"Total cost = {solver.Objective().Value()}\n")
for worker in range(num_workers):
for task in range(num_tasks):
if x[worker, task].solution_value() > 0.5:
print(f'Worker {worker} assigned to task {task}.' +
f' Cost: {costs[worker][task]}')
print(
f"Worker {worker} assigned to task {task}."
+ f" Cost: {costs[worker][task]}"
)
else:
print('No solution found.')
print("No solution found.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

View File

@@ -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.
"""MIP example that solves an assignment problem."""
# [START program]
# [START import]
@@ -23,13 +24,15 @@ from ortools.linear_solver.python import model_builder
def main():
# Data
# [START data_model]
costs = np.array([
[90, 80, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 95],
[45, 110, 95, 115],
[50, 100, 90, 100],
])
costs = np.array(
[
[90, 80, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 95],
[45, 110, 95, 115],
[50, 100, 90, 100],
]
)
num_workers, num_tasks = costs.shape
# [END data_model]
@@ -42,7 +45,9 @@ def main():
# [START variables]
# x[i, j] is an array of 0-1 variables, which will be 1
# if worker i is assigned to task j.
x = model.new_bool_var_array(shape=[num_workers, num_tasks], name='x') # pytype: disable=wrong-arg-types # numpy-scalars
x = model.new_bool_var_array(
shape=[num_workers, num_tasks], name="x"
) # pytype: disable=wrong-arg-types # numpy-scalars
# [END variables]
# Constraints
@@ -63,26 +68,27 @@ def main():
# [START solve]
# Create the solver with the CP-SAT backend, and solve the model.
solver = model_builder.ModelSolver('sat')
solver = model_builder.ModelSolver("sat")
status = solver.solve(model)
# [END solve]
# Print solution.
# [START print_solution]
if (status == model_builder.SolveStatus.OPTIMAL or
status == model_builder.SolveStatus.FEASIBLE):
print(f'Total cost = {solver.objective_value}\n')
if (
status == model_builder.SolveStatus.OPTIMAL
or status == model_builder.SolveStatus.FEASIBLE
):
print(f"Total cost = {solver.objective_value}\n")
for i in range(num_workers):
for j in range(num_tasks):
# Test if x[i,j] is 1 (with tolerance for floating point arithmetic).
if solver.value(x[i, j]) > 0.5:
print(f'Worker {i} assigned to task {j}.' +
f' Cost: {costs[i][j]}')
print(f"Worker {i} assigned to task {j}." + f" Cost: {costs[i][j]}")
else:
print('No solution found.')
print("No solution found.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

14
ortools/linear_solver/samples/assignment_mip.py Executable file → Normal file
View File

@@ -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.
"""MIP example that solves an assignment problem."""
# [START program]
# [START import]
@@ -35,7 +36,7 @@ def main():
# Solver
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
@@ -48,7 +49,7 @@ def main():
x = {}
for i in range(num_workers):
for j in range(num_tasks):
x[i, j] = solver.IntVar(0, 1, '')
x[i, j] = solver.IntVar(0, 1, "")
# [END variables]
# Constraints
@@ -79,18 +80,17 @@ def main():
# Print solution.
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
print(f"Total cost = {solver.Objective().Value()}\n")
for i in range(num_workers):
for j in range(num_tasks):
# Test if x[i,j] is 1 (with tolerance for floating point arithmetic).
if x[i, j].solution_value() > 0.5:
print(f'Worker {i} assigned to task {j}.' +
f' Cost: {costs[i][j]}')
print(f"Worker {i} assigned to task {j}." + f" Cost: {costs[i][j]}")
else:
print('No solution found.')
print("No solution found.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

View File

@@ -45,7 +45,7 @@ def main():
# Solver
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
@@ -58,7 +58,7 @@ def main():
x = {}
for worker in range(num_workers):
for task in range(num_tasks):
x[worker, task] = solver.BoolVar(f'x[{worker},{task}]')
x[worker, task] = solver.BoolVar(f"x[{worker},{task}]")
# [END variables]
# Constraints
@@ -66,14 +66,15 @@ def main():
# The total size of the tasks each worker takes on is at most total_size_max.
for worker in range(num_workers):
solver.Add(
solver.Sum([
task_sizes[task] * x[worker, task] for task in range(num_tasks)
]) <= total_size_max)
solver.Sum(
[task_sizes[task] * x[worker, task] for task in range(num_tasks)]
)
<= total_size_max
)
# Each task is assigned to exactly one worker.
for task in range(num_tasks):
solver.Add(
solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
solver.Add(solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
# [END constraints]
# Objective
@@ -93,17 +94,19 @@ def main():
# Print solution.
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
print(f"Total cost = {solver.Objective().Value()}\n")
for worker in range(num_workers):
for task in range(num_tasks):
if x[worker, task].solution_value() > 0.5:
print(f'Worker {worker} assigned to task {task}.' +
f' Cost: {costs[worker][task]}')
print(
f"Worker {worker} assigned to task {task}."
+ f" Cost: {costs[worker][task]}"
)
else:
print('No solution found.')
print("No solution found.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

24
ortools/linear_solver/samples/assignment_teams_mip.py Executable file → Normal file
View File

@@ -42,7 +42,7 @@ def main():
# Solver
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
# [END solver]
@@ -54,20 +54,18 @@ def main():
x = {}
for worker in range(num_workers):
for task in range(num_tasks):
x[worker, task] = solver.BoolVar(f'x[{worker},{task}]')
x[worker, task] = solver.BoolVar(f"x[{worker},{task}]")
# [END variables]
# Constraints
# [START constraints]
# Each worker is assigned at most 1 task.
for worker in range(num_workers):
solver.Add(
solver.Sum([x[worker, task] for task in range(num_tasks)]) <= 1)
solver.Add(solver.Sum([x[worker, task] for task in range(num_tasks)]) <= 1)
# Each task is assigned to exactly one worker.
for task in range(num_tasks):
solver.Add(
solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
solver.Add(solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)
# Each team takes at most two tasks.
team1_tasks = []
@@ -100,18 +98,20 @@ def main():
# Print solution.
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
print(f"Total cost = {solver.Objective().Value()}\n")
for worker in range(num_workers):
for task in range(num_tasks):
if x[worker, task].solution_value() > 0.5:
print(f'Worker {worker} assigned to task {task}.' +
f' Cost = {costs[worker][task]}')
print(
f"Worker {worker} assigned to task {task}."
+ f" Cost = {costs[worker][task]}"
)
else:
print('No solution found.')
print(f'Time = {solver.WallTime()} ms')
print("No solution found.")
print(f"Time = {solver.WallTime()} ms")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

30
ortools/linear_solver/samples/basic_example.py Executable file → Normal file
View File

@@ -11,37 +11,37 @@
# 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.
"""Minimal example to call the GLOP solver."""
# [START program]
# [START import]
from ortools.linear_solver import pywraplp
from ortools.init import pywrapinit
# [END import]
def main():
# [START solver]
# Create the linear solver with the GLOP backend.
solver = pywraplp.Solver.CreateSolver('GLOP')
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
return
# [END solver]
# [START variables]
# Create the variables x and y.
x = solver.NumVar(0, 1, 'x')
y = solver.NumVar(0, 2, 'y')
x = solver.NumVar(0, 1, "x")
y = solver.NumVar(0, 2, "y")
print('Number of variables =', solver.NumVariables())
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
# Create a linear constraint, 0 <= x + y <= 2.
ct = solver.Constraint(0, 2, 'ct')
ct = solver.Constraint(0, 2, "ct")
ct.SetCoefficient(x, 1)
ct.SetCoefficient(y, 1)
print('Number of constraints =', solver.NumConstraints())
print("Number of constraints =", solver.NumConstraints())
# [END constraints]
# [START objective]
@@ -57,19 +57,13 @@ def main():
# [END solve]
# [START print_solution]
print('Solution:')
print('Objective value =', objective.Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
print("Solution:")
print("Objective value =", objective.Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
# [END print_solution]
if __name__ == '__main__':
pywrapinit.CppBridge.InitLogging('basic_example.py')
cpp_flags = pywrapinit.CppFlags()
cpp_flags.logtostderr = True
cpp_flags.log_prefix = False
pywrapinit.CppBridge.SetFlags(cpp_flags)
if __name__ == "__main__":
main()
# [END program]

View File

@@ -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.
"""Solve a simple bin packing problem using a MIP solver."""
# [START program]
# [START import]
@@ -26,10 +27,10 @@ def create_data_model():
"""Create the data for the example."""
data = {}
weights = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30]
data['weights'] = weights
data['items'] = list(range(len(weights)))
data['bins'] = data['items']
data['bin_capacity'] = 100
data["weights"] = weights
data["items"] = list(range(len(weights)))
data["bins"] = data["items"]
data["bin_capacity"] = 100
return data
# [END data_model]
@@ -38,8 +39,8 @@ def create_data_model():
def main():
# [START data]
data = create_data_model()
num_items = len(data['items'])
num_bins = len(data['bins'])
num_items = len(data["items"])
num_bins = len(data["bins"])
# [END data]
# [END program_part1]
@@ -52,22 +53,25 @@ def main():
# [START variables]
# Variables
# x[i, j] = 1 if item i is packed in bin j.
x = model.new_bool_var_array(shape=[num_items, num_bins], name='x') # pytype: disable=wrong-arg-types # numpy-scalars
x = model.new_bool_var_array(
shape=[num_items, num_bins], name="x"
) # pytype: disable=wrong-arg-types # numpy-scalars
# y[j] = 1 if bin j is used.
y = model.new_bool_var_array(shape=[num_bins], name='y') # pytype: disable=wrong-arg-types # numpy-scalars
y = model.new_bool_var_array(
shape=[num_bins], name="y"
) # pytype: disable=wrong-arg-types # numpy-scalars
# [END variables]
# [START constraints]
# Constraints
# Each item must be in exactly one bin.
for i in data['items']:
for i in data["items"]:
model.add(np.sum(x[i, :]) == 1)
# The amount packed in each bin cannot exceed its capacity.
for j in data['bins']:
model.add(
np.dot(x[:, j], data['weights']) <= data['bin_capacity'] * y[j])
for j in data["bins"]:
model.add(np.dot(x[:, j], data["weights"]) <= data["bin_capacity"] * y[j])
# [END constraints]
# [START objective]
@@ -77,36 +81,36 @@ def main():
# [START solve]
# Create the solver with the CP-SAT backend, and solve the model.
solver = model_builder.ModelSolver('sat')
solver = model_builder.ModelSolver("sat")
status = solver.solve(model)
# [END solve]
# [START print_solution]
if status == model_builder.SolveStatus.OPTIMAL:
num_bins = 0.
for j in data['bins']:
num_bins = 0.0
for j in data["bins"]:
if solver.value(y[j]) == 1:
bin_items = []
bin_weight = 0
for i in data['items']:
for i in data["items"]:
if solver.value(x[i, j]) > 0:
bin_items.append(i)
bin_weight += data['weights'][i]
bin_weight += data["weights"][i]
if bin_weight > 0:
num_bins += 1
print('Bin number', j)
print(' Items packed:', bin_items)
print(' Total weight:', bin_weight)
print("Bin number", j)
print(" Items packed:", bin_items)
print(" Total weight:", bin_weight)
print()
print()
print('Number of bins used:', num_bins)
print('Time = ', solver.wall_time, ' seconds')
print("Number of bins used:", num_bins)
print("Time = ", solver.wall_time, " seconds")
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program_part2]
# [END program]

View File

@@ -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.
"""Solve a simple bin packing problem using a MIP solver."""
# [START program]
# [START import]
@@ -24,10 +25,10 @@ def create_data_model():
"""Create the data for the example."""
data = {}
weights = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30]
data['weights'] = weights
data['items'] = list(range(len(weights)))
data['bins'] = data['items']
data['bin_capacity'] = 100
data["weights"] = weights
data["items"] = list(range(len(weights)))
data["bins"] = data["items"]
data["bin_capacity"] = 100
return data
# [END data_model]
@@ -41,7 +42,7 @@ def main():
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
@@ -52,32 +53,33 @@ def main():
# Variables
# x[i, j] = 1 if item i is packed in bin j.
x = {}
for i in data['items']:
for j in data['bins']:
x[(i, j)] = solver.IntVar(0, 1, 'x_%i_%i' % (i, j))
for i in data["items"]:
for j in data["bins"]:
x[(i, j)] = solver.IntVar(0, 1, "x_%i_%i" % (i, j))
# y[j] = 1 if bin j is used.
y = {}
for j in data['bins']:
y[j] = solver.IntVar(0, 1, 'y[%i]' % j)
for j in data["bins"]:
y[j] = solver.IntVar(0, 1, "y[%i]" % j)
# [END variables]
# [START constraints]
# Constraints
# Each item must be in exactly one bin.
for i in data['items']:
solver.Add(sum(x[i, j] for j in data['bins']) == 1)
for i in data["items"]:
solver.Add(sum(x[i, j] for j in data["bins"]) == 1)
# The amount packed in each bin cannot exceed its capacity.
for j in data['bins']:
for j in data["bins"]:
solver.Add(
sum(x[(i, j)] * data['weights'][i] for i in data['items']) <= y[j] *
data['bin_capacity'])
sum(x[(i, j)] * data["weights"][i] for i in data["items"])
<= y[j] * data["bin_capacity"]
)
# [END constraints]
# [START objective]
# Objective: minimize the number of bins used.
solver.Minimize(solver.Sum([y[j] for j in data['bins']]))
solver.Minimize(solver.Sum([y[j] for j in data["bins"]]))
# [END objective]
# [START solve]
@@ -87,29 +89,29 @@ def main():
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
num_bins = 0
for j in data['bins']:
for j in data["bins"]:
if y[j].solution_value() == 1:
bin_items = []
bin_weight = 0
for i in data['items']:
for i in data["items"]:
if x[i, j].solution_value() > 0:
bin_items.append(i)
bin_weight += data['weights'][i]
bin_weight += data["weights"][i]
if bin_items:
num_bins += 1
print('Bin number', j)
print(' Items packed:', bin_items)
print(' Total weight:', bin_weight)
print("Bin number", j)
print(" Items packed:", bin_items)
print(" Total weight:", bin_weight)
print()
print()
print('Number of bins used:', num_bins)
print('Time = ', solver.WallTime(), ' milliseconds')
print("Number of bins used:", num_bins)
print("Time = ", solver.WallTime(), " milliseconds")
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program_part2]
# [END program]

View File

@@ -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.
"""Small example to illustrate solving a MIP problem."""
# [START program]
# [START import]
@@ -22,16 +23,16 @@ def IntegerProgrammingExample():
"""Integer programming sample."""
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
# [END solver]
# [START variables]
# x, y, and z are non-negative integer variables.
x = solver.IntVar(0.0, solver.infinity(), 'x')
y = solver.IntVar(0.0, solver.infinity(), 'y')
z = solver.IntVar(0.0, solver.infinity(), 'z')
x = solver.IntVar(0.0, solver.infinity(), "x")
y = solver.IntVar(0.0, solver.infinity(), "y")
z = solver.IntVar(0.0, solver.infinity(), "z")
# [END variables]
# [START constraints]
@@ -67,11 +68,11 @@ def IntegerProgrammingExample():
# [START print_solution]
solver.Solve()
# Print the objective value of the solution.
print('Maximum objective function value = %d' % solver.Objective().Value())
print("Maximum objective function value = %d" % solver.Objective().Value())
print()
# Print the value of each variable in the solution.
for variable in [x, y, z]:
print('%s = %d' % (variable.name(), variable.solution_value()))
print("%s = %d" % (variable.name(), variable.solution_value()))
# [END print_solution]

View File

@@ -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.
"""Linear optimization example."""
# [START program]
# [START import]
@@ -22,17 +23,17 @@ def LinearProgrammingExample():
"""Linear programming sample."""
# Instantiate a Glop solver, naming it LinearExample.
# [START solver]
solver = pywraplp.Solver.CreateSolver('GLOP')
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
return
# [END solver]
# Create the two variables and let them take on any non-negative value.
# [START variables]
x = solver.NumVar(0, solver.infinity(), 'x')
y = solver.NumVar(0, solver.infinity(), 'y')
x = solver.NumVar(0, solver.infinity(), "x")
y = solver.NumVar(0, solver.infinity(), "y")
print('Number of variables =', solver.NumVariables())
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
@@ -45,7 +46,7 @@ def LinearProgrammingExample():
# Constraint 2: x - y <= 2.
solver.Add(x - y <= 2.0)
print('Number of constraints =', solver.NumConstraints())
print("Number of constraints =", solver.NumConstraints())
# [END constraints]
# [START objective]
@@ -60,18 +61,18 @@ def LinearProgrammingExample():
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
print("Solution:")
print("Objective value =", solver.Objective().Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in %f milliseconds' % solver.wall_time())
print('Problem solved in %d iterations' % solver.iterations())
print("\nAdvanced usage:")
print("Problem solved in %f milliseconds" % solver.wall_time())
print("Problem solved in %d iterations" % solver.iterations())
# [END advanced]

49
ortools/linear_solver/samples/mip_var_array.py Executable file → Normal file
View File

@@ -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.
"""MIP example that uses a variable array."""
# [START program]
# [START import]
@@ -23,16 +24,16 @@ from ortools.linear_solver import pywraplp
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['constraint_coeffs'] = [
data["constraint_coeffs"] = [
[5, 7, 9, 2, 1],
[18, 4, -9, 10, 12],
[4, 7, 3, 8, 5],
[5, 13, 16, 3, -7],
]
data['bounds'] = [250, 285, 211, 315]
data['obj_coeffs'] = [7, 8, 2, 9, 6]
data['num_vars'] = 5
data['num_constraints'] = 4
data["bounds"] = [250, 285, 211, 315]
data["obj_coeffs"] = [7, 8, 2, 9, 6]
data["num_vars"] = 5
data["num_constraints"] = 4
return data
# [END data_model]
@@ -45,7 +46,7 @@ def main():
# [END program_part1]
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if not solver:
return
# [END solver]
@@ -54,17 +55,17 @@ def main():
# [START variables]
infinity = solver.infinity()
x = {}
for j in range(data['num_vars']):
x[j] = solver.IntVar(0, infinity, 'x[%i]' % j)
print('Number of variables =', solver.NumVariables())
for j in range(data["num_vars"]):
x[j] = solver.IntVar(0, infinity, "x[%i]" % j)
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
for i in range(data['num_constraints']):
constraint = solver.RowConstraint(0, data['bounds'][i], '')
for j in range(data['num_vars']):
constraint.SetCoefficient(x[j], data['constraint_coeffs'][i][j])
print('Number of constraints =', solver.NumConstraints())
for i in range(data["num_constraints"]):
constraint = solver.RowConstraint(0, data["bounds"][i], "")
for j in range(data["num_vars"]):
constraint.SetCoefficient(x[j], data["constraint_coeffs"][i][j])
print("Number of constraints =", solver.NumConstraints())
# In Python, you can also set the constraints as follows.
# for i in range(data['num_constraints']):
# constraint_expr = \
@@ -74,8 +75,8 @@ def main():
# [START objective]
objective = solver.Objective()
for j in range(data['num_vars']):
objective.SetCoefficient(x[j], data['obj_coeffs'][j])
for j in range(data["num_vars"]):
objective.SetCoefficient(x[j], data["obj_coeffs"][j])
objective.SetMaximization()
# In Python, you can also set the objective as follows.
# obj_expr = [data['obj_coeffs'][j] * x[j] for j in range(data['num_vars'])]
@@ -88,19 +89,19 @@ def main():
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
print('Objective value =', solver.Objective().Value())
for j in range(data['num_vars']):
print(x[j].name(), ' = ', x[j].solution_value())
print("Objective value =", solver.Objective().Value())
for j in range(data["num_vars"]):
print(x[j].name(), " = ", x[j].solution_value())
print()
print('Problem solved in %f milliseconds' % solver.wall_time())
print('Problem solved in %d iterations' % solver.iterations())
print('Problem solved in %d branch-and-bound nodes' % solver.nodes())
print("Problem solved in %f milliseconds" % solver.wall_time())
print("Problem solved in %d iterations" % solver.iterations())
print("Problem solved in %d branch-and-bound nodes" % solver.nodes())
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program_part2]
# [END program]

69
ortools/linear_solver/samples/multiple_knapsack_mip.py Executable file → Normal file
View File

@@ -22,26 +22,22 @@ from ortools.linear_solver import pywraplp
def main():
# [START data]
data = {}
data['weights'] = [
48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36
]
data['values'] = [
10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25
]
assert len(data['weights']) == len(data['values'])
data['num_items'] = len(data['weights'])
data['all_items'] = range(data['num_items'])
data["weights"] = [48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36]
data["values"] = [10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25]
assert len(data["weights"]) == len(data["values"])
data["num_items"] = len(data["weights"])
data["all_items"] = range(data["num_items"])
data['bin_capacities'] = [100, 100, 100, 100, 100]
data['num_bins'] = len(data['bin_capacities'])
data['all_bins'] = range(data['num_bins'])
data["bin_capacities"] = [100, 100, 100, 100, 100]
data["num_bins"] = len(data["bin_capacities"])
data["all_bins"] = range(data["num_bins"])
# [END data]
# Create the mip solver with the SCIP backend.
# [START solver]
solver = pywraplp.Solver.CreateSolver('SCIP')
solver = pywraplp.Solver.CreateSolver("SCIP")
if solver is None:
print('SCIP solver unavailable.')
print("SCIP solver unavailable.")
return
# [END solver]
@@ -49,31 +45,32 @@ def main():
# [START variables]
# x[i, b] = 1 if item i is packed in bin b.
x = {}
for i in data['all_items']:
for b in data['all_bins']:
x[i, b] = solver.BoolVar(f'x_{i}_{b}')
for i in data["all_items"]:
for b in data["all_bins"]:
x[i, b] = solver.BoolVar(f"x_{i}_{b}")
# [END variables]
# Constraints.
# [START constraints]
# Each item is assigned to at most one bin.
for i in data['all_items']:
solver.Add(sum(x[i, b] for b in data['all_bins']) <= 1)
for i in data["all_items"]:
solver.Add(sum(x[i, b] for b in data["all_bins"]) <= 1)
# The amount packed in each bin cannot exceed its capacity.
for b in data['all_bins']:
for b in data["all_bins"]:
solver.Add(
sum(x[i, b] * data['weights'][i]
for i in data['all_items']) <= data['bin_capacities'][b])
sum(x[i, b] * data["weights"][i] for i in data["all_items"])
<= data["bin_capacities"][b]
)
# [END constraints]
# Objective.
# [START objective]
# Maximize total value of packed items.
objective = solver.Objective()
for i in data['all_items']:
for b in data['all_bins']:
objective.SetCoefficient(x[i, b], data['values'][i])
for i in data["all_items"]:
for b in data["all_bins"]:
objective.SetCoefficient(x[i, b], data["values"][i])
objective.SetMaximization()
# [END objective]
@@ -83,28 +80,28 @@ def main():
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
print(f'Total packed value: {objective.Value()}')
print(f"Total packed value: {objective.Value()}")
total_weight = 0
for b in data['all_bins']:
print(f'Bin {b}')
for b in data["all_bins"]:
print(f"Bin {b}")
bin_weight = 0
bin_value = 0
for i in data['all_items']:
for i in data["all_items"]:
if x[i, b].solution_value() > 0:
print(
f"Item {i} weight: {data['weights'][i]} value: {data['values'][i]}"
)
bin_weight += data['weights'][i]
bin_value += data['values'][i]
print(f'Packed bin weight: {bin_weight}')
print(f'Packed bin value: {bin_value}\n')
bin_weight += data["weights"][i]
bin_value += data["values"][i]
print(f"Packed bin weight: {bin_weight}")
print(f"Packed bin value: {bin_value}\n")
total_weight += bin_weight
print(f'Total packed weight: {total_weight}')
print(f"Total packed weight: {total_weight}")
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

31
ortools/linear_solver/samples/simple_lp_program.py Executable file → Normal file
View File

@@ -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.
"""Minimal example to call the GLOP solver."""
# [START program]
# [START import]
@@ -21,7 +22,7 @@ from ortools.linear_solver import pywraplp
def main():
# [START solver]
# Create the linear solver with the GLOP backend.
solver = pywraplp.Solver.CreateSolver('GLOP')
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
return
# [END solver]
@@ -29,10 +30,10 @@ def main():
# [START variables]
infinity = solver.infinity()
# Create the variables x and y.
x = solver.NumVar(0.0, infinity, 'x')
y = solver.NumVar(0.0, infinity, 'y')
x = solver.NumVar(0.0, infinity, "x")
y = solver.NumVar(0.0, infinity, "y")
print('Number of variables =', solver.NumVariables())
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
@@ -42,7 +43,7 @@ def main():
# x <= 3.5.
solver.Add(x <= 3.5)
print('Number of constraints =', solver.NumConstraints())
print("Number of constraints =", solver.NumConstraints())
# [END constraints]
# [START objective]
@@ -51,27 +52,27 @@ def main():
# [END objective]
# [START solve]
print(f'Solving with {solver.SolverVersion()}')
print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()
# [END solve]
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
print("Solution:")
print("Objective value =", solver.Objective().Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in %f milliseconds' % solver.wall_time())
print('Problem solved in %d iterations' % solver.iterations())
print("\nAdvanced usage:")
print("Problem solved in %f milliseconds" % solver.wall_time())
print("Problem solved in %d iterations" % solver.iterations())
# [END advanced]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

View File

@@ -29,10 +29,14 @@ def main():
# [START variables]
# Create the variables x and y.
x = model.new_num_var(0.0, math.inf, 'x') # pytype: disable=wrong-arg-types # numpy-scalars
y = model.new_num_var(0.0, math.inf, 'y') # pytype: disable=wrong-arg-types # numpy-scalars
x = model.new_num_var(
0.0, math.inf, "x"
) # pytype: disable=wrong-arg-types # numpy-scalars
y = model.new_num_var(
0.0, math.inf, "y"
) # pytype: disable=wrong-arg-types # numpy-scalars
print('Number of variables =', model.num_variables)
print("Number of variables =", model.num_variables)
# [END variables]
# [START constraints]
@@ -42,7 +46,7 @@ def main():
# x <= 3.5.
model.add(x <= 3.5)
print('Number of constraints =', model.num_constraints)
print("Number of constraints =", model.num_constraints)
# [END constraints]
# [START objective]
@@ -52,29 +56,29 @@ def main():
# [START solve]
# Create the solver with the GLOP backend, and solve the model.
solver = model_builder.ModelSolver('glop')
solver = model_builder.ModelSolver("glop")
status = solver.solve(model)
# [END solve]
# [START print_solution]
if status == model_builder.SolveStatus.OPTIMAL:
print('Solution:')
print('Objective value =', solver.objective_value)
print('x =', solver.value(x))
print('y =', solver.value(y))
print("Solution:")
print("Objective value =", solver.objective_value)
print("x =", solver.value(x))
print("y =", solver.value(y))
print('dual_value(ct) =', solver.dual_value(ct))
print('reduced_cost(x) =', solver.reduced_cost(x))
print("dual_value(ct) =", solver.dual_value(ct))
print("reduced_cost(x) =", solver.reduced_cost(x))
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in %f seconds' % solver.wall_time)
print("\nAdvanced usage:")
print("Problem solved in %f seconds" % solver.wall_time)
# [END advanced]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

33
ortools/linear_solver/samples/simple_mip_program.py Executable file → Normal file
View File

@@ -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.
"""Integer programming examples that show how to use the APIs."""
# [START program]
# [START import]
@@ -21,7 +22,7 @@ from ortools.linear_solver import pywraplp
def main():
# [START solver]
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SAT')
solver = pywraplp.Solver.CreateSolver("SAT")
if not solver:
return
# [END solver]
@@ -29,10 +30,10 @@ def main():
# [START variables]
infinity = solver.infinity()
# x and y are integer non-negative variables.
x = solver.IntVar(0.0, infinity, 'x')
y = solver.IntVar(0.0, infinity, 'y')
x = solver.IntVar(0.0, infinity, "x")
y = solver.IntVar(0.0, infinity, "y")
print('Number of variables =', solver.NumVariables())
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
@@ -42,7 +43,7 @@ def main():
# x <= 3.5.
solver.Add(x <= 3.5)
print('Number of constraints =', solver.NumConstraints())
print("Number of constraints =", solver.NumConstraints())
# [END constraints]
# [START objective]
@@ -51,28 +52,28 @@ def main():
# [END objective]
# [START solve]
print(f'Solving with {solver.SolverVersion()}')
print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()
# [END solve]
# [START print_solution]
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', x.solution_value())
print('y =', y.solution_value())
print("Solution:")
print("Objective value =", solver.Objective().Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in %f milliseconds' % solver.wall_time())
print('Problem solved in %d iterations' % solver.iterations())
print('Problem solved in %d branch-and-bound nodes' % solver.nodes())
print("\nAdvanced usage:")
print("Problem solved in %f milliseconds" % solver.wall_time())
print("Problem solved in %d iterations" % solver.iterations())
print("Problem solved in %d branch-and-bound nodes" % solver.nodes())
# [END advanced]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

View File

@@ -29,10 +29,14 @@ def main():
# [START variables]
# x and y are integer non-negative variables.
x = model.new_int_var(0.0, math.inf, 'x') # pytype: disable=wrong-arg-types # numpy-scalars
y = model.new_int_var(0.0, math.inf, 'y') # pytype: disable=wrong-arg-types # numpy-scalars
x = model.new_int_var(
0.0, math.inf, "x"
) # pytype: disable=wrong-arg-types # numpy-scalars
y = model.new_int_var(
0.0, math.inf, "y"
) # pytype: disable=wrong-arg-types # numpy-scalars
print('Number of variables =', model.num_variables)
print("Number of variables =", model.num_variables)
# [END variables]
# [START constraints]
@@ -42,7 +46,7 @@ def main():
# x <= 3.5.
model.add(x <= 3.5)
print('Number of constraints =', model.num_constraints)
print("Number of constraints =", model.num_constraints)
# [END constraints]
# [START objective]
@@ -52,26 +56,26 @@ def main():
# [START solve]
# Create the solver with the SCIP backend, and solve the model.
solver = model_builder.ModelSolver('scip')
solver = model_builder.ModelSolver("scip")
status = solver.solve(model)
# [END solve]
# [START print_solution]
if status == model_builder.SolveStatus.OPTIMAL:
print('Solution:')
print('Objective value =', solver.objective_value)
print('x =', solver.value(x))
print('y =', solver.value(y))
print("Solution:")
print("Objective value =", solver.objective_value)
print("x =", solver.value(x))
print("y =", solver.value(y))
else:
print('The problem does not have an optimal solution.')
print("The problem does not have an optimal solution.")
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in %f seconds' % solver.wall_time)
print("\nAdvanced usage:")
print("Problem solved in %f seconds" % solver.wall_time)
# [END advanced]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]

View File

@@ -29,15 +29,15 @@ def main():
# [START data_model]
# Nutrient minimums.
nutrients = [
['Calories (kcal)', 3],
['Protein (g)', 70],
['Calcium (g)', 0.8],
['Iron (mg)', 12],
['Vitamin A (KIU)', 5],
['Vitamin B1 (mg)', 1.8],
['Vitamin B2 (mg)', 2.7],
['Niacin (mg)', 18],
['Vitamin C (mg)', 75],
["Calories (kcal)", 3],
["Protein (g)", 70],
["Calcium (g)", 0.8],
["Iron (mg)", 12],
["Vitamin A (KIU)", 5],
["Vitamin B1 (mg)", 1.8],
["Vitamin B2 (mg)", 2.7],
["Niacin (mg)", 18],
["Vitamin C (mg)", 75],
]
# Commodity, Unit, 1939 price (cents), Calories (kcal), Protein (g),
@@ -45,187 +45,179 @@ def main():
# Niacin (mg), Vitamin C (mg)
data = [
[
'Wheat Flour (Enriched)', '10 lb.', 36, 44.7, 1411, 2, 365, 0, 55.4,
33.3, 441, 0
"Wheat Flour (Enriched)",
"10 lb.",
36,
44.7,
1411,
2,
365,
0,
55.4,
33.3,
441,
0,
],
['Macaroni', '1 lb.', 14.1, 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0],
["Macaroni", "1 lb.", 14.1, 11.6, 418, 0.7, 54, 0, 3.2, 1.9, 68, 0],
[
'Wheat Cereal (Enriched)', '28 oz.', 24.2, 11.8, 377, 14.4, 175, 0,
14.4, 8.8, 114, 0
"Wheat Cereal (Enriched)",
"28 oz.",
24.2,
11.8,
377,
14.4,
175,
0,
14.4,
8.8,
114,
0,
],
['Corn Flakes', '8 oz.', 7.1, 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0],
["Corn Flakes", "8 oz.", 7.1, 11.4, 252, 0.1, 56, 0, 13.5, 2.3, 68, 0],
["Corn Meal", "1 lb.", 4.6, 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106, 0],
["Hominy Grits", "24 oz.", 8.5, 28.6, 680, 0.8, 80, 0, 10.6, 1.6, 110, 0],
["Rice", "1 lb.", 7.5, 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0],
["Rolled Oats", "1 lb.", 7.1, 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0],
[
'Corn Meal', '1 lb.', 4.6, 36.0, 897, 1.7, 99, 30.9, 17.4, 7.9, 106,
0
"White Bread (Enriched)",
"1 lb.",
7.9,
15.0,
488,
2.5,
115,
0,
13.8,
8.5,
126,
0,
],
["Whole Wheat Bread", "1 lb.", 9.1, 12.2, 484, 2.7, 125, 0, 13.9, 6.4, 160, 0],
["Rye Bread", "1 lb.", 9.1, 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0],
["Pound Cake", "1 lb.", 24.8, 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0],
["Soda Crackers", "1 lb.", 15.1, 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0],
["Milk", "1 qt.", 11, 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177],
[
"Evaporated Milk (can)",
"14.5 oz.",
6.7,
8.4,
422,
15.1,
9,
26,
3,
23.5,
11,
60,
],
["Butter", "1 lb.", 30.8, 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0],
["Oleomargarine", "1 lb.", 16.1, 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0],
["Eggs", "1 doz.", 32.6, 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0],
["Cheese (Cheddar)", "1 lb.", 24.2, 7.4, 448, 16.4, 19, 28.1, 0.8, 10.3, 4, 0],
["Cream", "1/2 pt.", 14.1, 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17],
["Peanut Butter", "1 lb.", 17.9, 15.7, 661, 1.0, 48, 0, 9.6, 8.1, 471, 0],
["Mayonnaise", "1/2 pt.", 16.7, 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0],
["Crisco", "1 lb.", 20.3, 20.1, 0, 0, 0, 0, 0, 0, 0, 0],
["Lard", "1 lb.", 9.8, 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0],
["Sirloin Steak", "1 lb.", 39.6, 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9, 69, 0],
["Round Steak", "1 lb.", 36.4, 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0],
["Rib Roast", "1 lb.", 29.2, 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0],
["Chuck Roast", "1 lb.", 22.6, 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0],
["Plate", "1 lb.", 14.6, 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0],
["Liver (Beef)", "1 lb.", 26.8, 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8, 316, 525],
["Leg of Lamb", "1 lb.", 27.6, 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0],
["Lamb Chops (Rib)", "1 lb.", 36.6, 3.3, 140, 0.1, 15, 0, 1.7, 2.7, 54, 0],
["Pork Chops", "1 lb.", 30.7, 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0],
["Pork Loin Roast", "1 lb.", 24.2, 4.4, 249, 0.3, 37, 0, 18.2, 3.6, 79, 0],
["Bacon", "1 lb.", 25.6, 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0],
["Ham, smoked", "1 lb.", 27.4, 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0],
["Salt Pork", "1 lb.", 16, 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0],
["Roasting Chicken", "1 lb.", 30.3, 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8, 68, 46],
["Veal Cutlets", "1 lb.", 42.3, 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0],
["Salmon, Pink (can)", "16 oz.", 13, 5.8, 705, 6.8, 45, 3.5, 1, 4.9, 209, 0],
["Apples", "1 lb.", 4.4, 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544],
["Bananas", "1 lb.", 6.1, 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498],
["Lemons", "1 doz.", 26, 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952],
["Oranges", "1 doz.", 30.9, 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998],
["Green Beans", "1 lb.", 7.1, 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862],
["Cabbage", "1 lb.", 3.7, 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369],
["Carrots", "1 bunch", 4.7, 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608],
["Celery", "1 stalk", 7.3, 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313],
["Lettuce", "1 head", 8.2, 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449],
["Onions", "1 lb.", 3.6, 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184],
["Potatoes", "15 lb.", 34, 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198, 2522],
["Spinach", "1 lb.", 8.1, 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755],
["Sweet Potatoes", "1 lb.", 5.1, 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4, 83, 1912],
["Peaches (can)", "No. 2 1/2", 16.8, 3.7, 20, 0.4, 10, 21.5, 0.5, 1, 31, 196],
["Pears (can)", "No. 2 1/2", 20.4, 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5, 81],
["Pineapple (can)", "No. 2 1/2", 21.3, 2.4, 16, 0.4, 8, 2, 2.8, 0.8, 7, 399],
["Asparagus (can)", "No. 2", 27.7, 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1, 17, 272],
["Green Beans (can)", "No. 2", 10, 1.0, 54, 2, 65, 53.9, 1.6, 4.3, 32, 431],
["Pork and Beans (can)", "16 oz.", 7.1, 7.5, 364, 4, 134, 3.5, 8.3, 7.7, 56, 0],
["Corn (can)", "No. 2", 10.4, 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218],
["Peas (can)", "No. 2", 13.8, 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37, 370],
["Tomatoes (can)", "No. 2", 8.6, 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5, 36, 1253],
[
"Tomato Soup (can)",
"10 1/2 oz.",
7.6,
1.6,
71,
0.6,
43,
57.9,
3.5,
2.4,
67,
862,
],
["Peaches, Dried", "1 lb.", 15.7, 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3, 55, 57],
["Prunes, Dried", "1 lb.", 9, 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65, 257],
["Raisins, Dried", "15 oz.", 9.4, 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4, 24, 136],
["Peas, Dried", "1 lb.", 7.9, 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4, 162, 0],
[
"Lima Beans, Dried",
"1 lb.",
8.9,
17.4,
1055,
3.7,
459,
5.1,
26.9,
38.2,
93,
0,
],
[
'Hominy Grits', '24 oz.', 8.5, 28.6, 680, 0.8, 80, 0, 10.6, 1.6,
110, 0
],
['Rice', '1 lb.', 7.5, 21.2, 460, 0.6, 41, 0, 2, 4.8, 60, 0],
['Rolled Oats', '1 lb.', 7.1, 25.3, 907, 5.1, 341, 0, 37.1, 8.9, 64, 0],
[
'White Bread (Enriched)', '1 lb.', 7.9, 15.0, 488, 2.5, 115, 0,
13.8, 8.5, 126, 0
],
[
'Whole Wheat Bread', '1 lb.', 9.1, 12.2, 484, 2.7, 125, 0, 13.9,
6.4, 160, 0
],
['Rye Bread', '1 lb.', 9.1, 12.4, 439, 1.1, 82, 0, 9.9, 3, 66, 0],
['Pound Cake', '1 lb.', 24.8, 8.0, 130, 0.4, 31, 18.9, 2.8, 3, 17, 0],
['Soda Crackers', '1 lb.', 15.1, 12.5, 288, 0.5, 50, 0, 0, 0, 0, 0],
['Milk', '1 qt.', 11, 6.1, 310, 10.5, 18, 16.8, 4, 16, 7, 177],
[
'Evaporated Milk (can)', '14.5 oz.', 6.7, 8.4, 422, 15.1, 9, 26, 3,
23.5, 11, 60
],
['Butter', '1 lb.', 30.8, 10.8, 9, 0.2, 3, 44.2, 0, 0.2, 2, 0],
['Oleomargarine', '1 lb.', 16.1, 20.6, 17, 0.6, 6, 55.8, 0.2, 0, 0, 0],
['Eggs', '1 doz.', 32.6, 2.9, 238, 1.0, 52, 18.6, 2.8, 6.5, 1, 0],
[
'Cheese (Cheddar)', '1 lb.', 24.2, 7.4, 448, 16.4, 19, 28.1, 0.8,
10.3, 4, 0
],
['Cream', '1/2 pt.', 14.1, 3.5, 49, 1.7, 3, 16.9, 0.6, 2.5, 0, 17],
[
'Peanut Butter', '1 lb.', 17.9, 15.7, 661, 1.0, 48, 0, 9.6, 8.1,
471, 0
],
['Mayonnaise', '1/2 pt.', 16.7, 8.6, 18, 0.2, 8, 2.7, 0.4, 0.5, 0, 0],
['Crisco', '1 lb.', 20.3, 20.1, 0, 0, 0, 0, 0, 0, 0, 0],
['Lard', '1 lb.', 9.8, 41.7, 0, 0, 0, 0.2, 0, 0.5, 5, 0],
[
'Sirloin Steak', '1 lb.', 39.6, 2.9, 166, 0.1, 34, 0.2, 2.1, 2.9,
69, 0
],
['Round Steak', '1 lb.', 36.4, 2.2, 214, 0.1, 32, 0.4, 2.5, 2.4, 87, 0],
['Rib Roast', '1 lb.', 29.2, 3.4, 213, 0.1, 33, 0, 0, 2, 0, 0],
['Chuck Roast', '1 lb.', 22.6, 3.6, 309, 0.2, 46, 0.4, 1, 4, 120, 0],
['Plate', '1 lb.', 14.6, 8.5, 404, 0.2, 62, 0, 0.9, 0, 0, 0],
[
'Liver (Beef)', '1 lb.', 26.8, 2.2, 333, 0.2, 139, 169.2, 6.4, 50.8,
316, 525
],
['Leg of Lamb', '1 lb.', 27.6, 3.1, 245, 0.1, 20, 0, 2.8, 3.9, 86, 0],
[
'Lamb Chops (Rib)', '1 lb.', 36.6, 3.3, 140, 0.1, 15, 0, 1.7, 2.7,
54, 0
],
['Pork Chops', '1 lb.', 30.7, 3.5, 196, 0.2, 30, 0, 17.4, 2.7, 60, 0],
[
'Pork Loin Roast', '1 lb.', 24.2, 4.4, 249, 0.3, 37, 0, 18.2, 3.6,
79, 0
],
['Bacon', '1 lb.', 25.6, 10.4, 152, 0.2, 23, 0, 1.8, 1.8, 71, 0],
['Ham, smoked', '1 lb.', 27.4, 6.7, 212, 0.2, 31, 0, 9.9, 3.3, 50, 0],
['Salt Pork', '1 lb.', 16, 18.8, 164, 0.1, 26, 0, 1.4, 1.8, 0, 0],
[
'Roasting Chicken', '1 lb.', 30.3, 1.8, 184, 0.1, 30, 0.1, 0.9, 1.8,
68, 46
],
['Veal Cutlets', '1 lb.', 42.3, 1.7, 156, 0.1, 24, 0, 1.4, 2.4, 57, 0],
[
'Salmon, Pink (can)', '16 oz.', 13, 5.8, 705, 6.8, 45, 3.5, 1, 4.9,
209, 0
],
['Apples', '1 lb.', 4.4, 5.8, 27, 0.5, 36, 7.3, 3.6, 2.7, 5, 544],
['Bananas', '1 lb.', 6.1, 4.9, 60, 0.4, 30, 17.4, 2.5, 3.5, 28, 498],
['Lemons', '1 doz.', 26, 1.0, 21, 0.5, 14, 0, 0.5, 0, 4, 952],
['Oranges', '1 doz.', 30.9, 2.2, 40, 1.1, 18, 11.1, 3.6, 1.3, 10, 1998],
['Green Beans', '1 lb.', 7.1, 2.4, 138, 3.7, 80, 69, 4.3, 5.8, 37, 862],
['Cabbage', '1 lb.', 3.7, 2.6, 125, 4.0, 36, 7.2, 9, 4.5, 26, 5369],
['Carrots', '1 bunch', 4.7, 2.7, 73, 2.8, 43, 188.5, 6.1, 4.3, 89, 608],
['Celery', '1 stalk', 7.3, 0.9, 51, 3.0, 23, 0.9, 1.4, 1.4, 9, 313],
['Lettuce', '1 head', 8.2, 0.4, 27, 1.1, 22, 112.4, 1.8, 3.4, 11, 449],
['Onions', '1 lb.', 3.6, 5.8, 166, 3.8, 59, 16.6, 4.7, 5.9, 21, 1184],
[
'Potatoes', '15 lb.', 34, 14.3, 336, 1.8, 118, 6.7, 29.4, 7.1, 198,
2522
],
['Spinach', '1 lb.', 8.1, 1.1, 106, 0, 138, 918.4, 5.7, 13.8, 33, 2755],
[
'Sweet Potatoes', '1 lb.', 5.1, 9.6, 138, 2.7, 54, 290.7, 8.4, 5.4,
83, 1912
],
[
'Peaches (can)', 'No. 2 1/2', 16.8, 3.7, 20, 0.4, 10, 21.5, 0.5, 1,
31, 196
],
[
'Pears (can)', 'No. 2 1/2', 20.4, 3.0, 8, 0.3, 8, 0.8, 0.8, 0.8, 5,
81
],
[
'Pineapple (can)', 'No. 2 1/2', 21.3, 2.4, 16, 0.4, 8, 2, 2.8, 0.8,
7, 399
],
[
'Asparagus (can)', 'No. 2', 27.7, 0.4, 33, 0.3, 12, 16.3, 1.4, 2.1,
17, 272
],
[
'Green Beans (can)', 'No. 2', 10, 1.0, 54, 2, 65, 53.9, 1.6, 4.3,
32, 431
],
[
'Pork and Beans (can)', '16 oz.', 7.1, 7.5, 364, 4, 134, 3.5, 8.3,
7.7, 56, 0
],
['Corn (can)', 'No. 2', 10.4, 5.2, 136, 0.2, 16, 12, 1.6, 2.7, 42, 218],
[
'Peas (can)', 'No. 2', 13.8, 2.3, 136, 0.6, 45, 34.9, 4.9, 2.5, 37,
370
],
[
'Tomatoes (can)', 'No. 2', 8.6, 1.3, 63, 0.7, 38, 53.2, 3.4, 2.5,
36, 1253
],
[
'Tomato Soup (can)', '10 1/2 oz.', 7.6, 1.6, 71, 0.6, 43, 57.9, 3.5,
2.4, 67, 862
],
[
'Peaches, Dried', '1 lb.', 15.7, 8.5, 87, 1.7, 173, 86.8, 1.2, 4.3,
55, 57
],
[
'Prunes, Dried', '1 lb.', 9, 12.8, 99, 2.5, 154, 85.7, 3.9, 4.3, 65,
257
],
[
'Raisins, Dried', '15 oz.', 9.4, 13.5, 104, 2.5, 136, 4.5, 6.3, 1.4,
24, 136
],
[
'Peas, Dried', '1 lb.', 7.9, 20.0, 1367, 4.2, 345, 2.9, 28.7, 18.4,
162, 0
],
[
'Lima Beans, Dried', '1 lb.', 8.9, 17.4, 1055, 3.7, 459, 5.1, 26.9,
38.2, 93, 0
],
[
'Navy Beans, Dried', '1 lb.', 5.9, 26.9, 1691, 11.4, 792, 0, 38.4,
24.6, 217, 0
],
['Coffee', '1 lb.', 22.4, 0, 0, 0, 0, 0, 4, 5.1, 50, 0],
['Tea', '1/4 lb.', 17.4, 0, 0, 0, 0, 0, 0, 2.3, 42, 0],
['Cocoa', '8 oz.', 8.6, 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0],
['Chocolate', '8 oz.', 16.2, 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0],
['Sugar', '10 lb.', 51.7, 34.9, 0, 0, 0, 0, 0, 0, 0, 0],
['Corn Syrup', '24 oz.', 13.7, 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0],
['Molasses', '18 oz.', 13.6, 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0],
[
'Strawberry Preserves', '1 lb.', 20.5, 6.4, 11, 0.4, 7, 0.2, 0.2,
0.4, 3, 0
"Navy Beans, Dried",
"1 lb.",
5.9,
26.9,
1691,
11.4,
792,
0,
38.4,
24.6,
217,
0,
],
["Coffee", "1 lb.", 22.4, 0, 0, 0, 0, 0, 4, 5.1, 50, 0],
["Tea", "1/4 lb.", 17.4, 0, 0, 0, 0, 0, 0, 2.3, 42, 0],
["Cocoa", "8 oz.", 8.6, 8.7, 237, 3, 72, 0, 2, 11.9, 40, 0],
["Chocolate", "8 oz.", 16.2, 8.0, 77, 1.3, 39, 0, 0.9, 3.4, 14, 0],
["Sugar", "10 lb.", 51.7, 34.9, 0, 0, 0, 0, 0, 0, 0, 0],
["Corn Syrup", "24 oz.", 13.7, 14.7, 0, 0.5, 74, 0, 0, 0, 5, 0],
["Molasses", "18 oz.", 13.6, 9.0, 0, 10.3, 244, 0, 1.9, 7.5, 146, 0],
["Strawberry Preserves", "1 lb.", 20.5, 6.4, 11, 0.4, 7, 0.2, 0.2, 0.4, 3, 0],
]
# [END data_model]
# [START solver]
# Instantiate a Glop solver and naming it.
solver = pywraplp.Solver.CreateSolver('GLOP')
solver = pywraplp.Solver.CreateSolver("GLOP")
if not solver:
return
# [END solver]
@@ -234,7 +226,7 @@ def main():
# Declare an array to hold our variables.
foods = [solver.NumVar(0.0, solver.infinity(), item[0]) for item in data]
print('Number of variables =', solver.NumVariables())
print("Number of variables =", solver.NumVariables())
# [END variables]
# [START constraints]
@@ -245,7 +237,7 @@ def main():
for j, item in enumerate(data):
constraints[i].SetCoefficient(foods[j], item[i + 3])
print('Number of constraints =', solver.NumConstraints())
print("Number of constraints =", solver.NumConstraints())
# [END constraints]
# [START objective]
@@ -263,36 +255,37 @@ def main():
# [START print_solution]
# Check that the problem has an optimal solution.
if status != solver.OPTIMAL:
print('The problem does not have an optimal solution!')
print("The problem does not have an optimal solution!")
if status == solver.FEASIBLE:
print('A potentially suboptimal solution was found.')
print("A potentially suboptimal solution was found.")
else:
print('The solver could not solve the problem.')
print("The solver could not solve the problem.")
exit(1)
# Display the amounts (in dollars) to purchase of each food.
nutrients_result = [0] * len(nutrients)
print('\nAnnual Foods:')
print("\nAnnual Foods:")
for i, food in enumerate(foods):
if food.solution_value() > 0.0:
print('{}: ${}'.format(data[i][0], 365. * food.solution_value()))
print("{}: ${}".format(data[i][0], 365.0 * food.solution_value()))
for j, _ in enumerate(nutrients):
nutrients_result[j] += data[i][j + 3] * food.solution_value()
print('\nOptimal annual price: ${:.4f}'.format(365. * objective.Value()))
print("\nOptimal annual price: ${:.4f}".format(365.0 * objective.Value()))
print('\nNutrients per day:')
print("\nNutrients per day:")
for i, nutrient in enumerate(nutrients):
print('{}: {:.2f} (min {})'.format(nutrient[0], nutrients_result[i],
nutrient[1]))
print(
"{}: {:.2f} (min {})".format(nutrient[0], nutrients_result[i], nutrient[1])
)
# [END print_solution]
# [START advanced]
print('\nAdvanced usage:')
print('Problem solved in ', solver.wall_time(), ' milliseconds')
print('Problem solved in ', solver.iterations(), ' iterations')
print("\nAdvanced usage:")
print("Problem solved in ", solver.wall_time(), " milliseconds")
print("Problem solved in ", solver.iterations(), " iterations")
# [END advanced]
if __name__ == '__main__':
if __name__ == "__main__":
main()
# [END program]