reformat linear_solver python code to BLACK; support pybind11_protobuf
This commit is contained in:
@@ -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
|
||||
|
||||
15
WORKSPACE
15
WORKSPACE
@@ -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(
|
||||
|
||||
@@ -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
|
||||
# ##############################################################################
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
1598
ortools/linear_solver/python/pandas_model.py
Normal file
1598
ortools/linear_solver/python/pandas_model.py
Normal file
File diff suppressed because it is too large
Load Diff
1748
ortools/linear_solver/python/pandas_model_test.py
Normal file
1748
ortools/linear_solver/python/pandas_model_test.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
18
ortools/linear_solver/python/pywraplp_test.py
Executable file → Normal 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
35
ortools/linear_solver/samples/assignment_groups_mip.py
Executable file → Normal 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]
|
||||
|
||||
@@ -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
14
ortools/linear_solver/samples/assignment_mip.py
Executable file → Normal 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]
|
||||
|
||||
27
ortools/linear_solver/samples/assignment_task_sizes_mip.py
Executable file → Normal file
27
ortools/linear_solver/samples/assignment_task_sizes_mip.py
Executable file → Normal 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
24
ortools/linear_solver/samples/assignment_teams_mip.py
Executable file → Normal 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
30
ortools/linear_solver/samples/basic_example.py
Executable file → Normal 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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
13
ortools/linear_solver/samples/integer_programming_example.py
Executable file → Normal file
13
ortools/linear_solver/samples/integer_programming_example.py
Executable file → Normal 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]
|
||||
|
||||
|
||||
|
||||
27
ortools/linear_solver/samples/linear_programming_example.py
Executable file → Normal file
27
ortools/linear_solver/samples/linear_programming_example.py
Executable file → Normal 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
49
ortools/linear_solver/samples/mip_var_array.py
Executable file → Normal 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
69
ortools/linear_solver/samples/multiple_knapsack_mip.py
Executable file → Normal 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
31
ortools/linear_solver/samples/simple_lp_program.py
Executable file → Normal 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]
|
||||
|
||||
@@ -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
33
ortools/linear_solver/samples/simple_mip_program.py
Executable file → Normal 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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user