python rewrite

This commit is contained in:
lperron@google.com
2014-07-09 11:17:29 +00:00
parent 98cd32d785
commit 4de8aa77ab
23 changed files with 2191 additions and 881 deletions

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -23,7 +23,7 @@ def RunIntegerExampleNaturalLanguageAPI(optimization_problem_type):
"""Example of simple integer program with natural language API."""
solver = pywraplp.Solver('RunIntegerExampleNaturalLanguageAPI',
optimization_problem_type)
infinity = solver.Infinity()
infinity = solver.infinity()
# x1 and x2 are integer non-negative variables.
x1 = solver.IntVar(0.0, infinity, 'x1')
x2 = solver.IntVar(0.0, infinity, 'x2')
@@ -38,7 +38,7 @@ def RunIntegerExampleCppStyleAPI(optimization_problem_type):
"""Example of simple integer program with the C++ style API."""
solver = pywraplp.Solver('RunIntegerExampleCppStyleAPI',
optimization_problem_type)
infinity = solver.Infinity()
infinity = solver.infinity()
# x1 and x2 are integer non-negative variables.
x1 = solver.IntVar(0.0, infinity, 'x1')
x2 = solver.IntVar(0.0, infinity, 'x2')
@@ -58,25 +58,29 @@ def RunIntegerExampleCppStyleAPI(optimization_problem_type):
def SolveAndPrint(solver, variable_list):
"""Solve the problem and print the solution."""
print('Number of variables = %d' % solver.NumVariables())
print('Number of constraints = %d' % solver.NumConstraints())
print 'Number of variables = %d' % solver.NumVariables()
print 'Number of constraints = %d' % solver.NumConstraints()
result_status = solver.Solve()
# The problem has an optimal solution.
assert result_status == pywraplp.Solver.OPTIMAL
print('Problem solved in %f milliseconds' % solver.WallTime())
# The solution looks legit (when using solvers others than
# GLOP_LINEAR_PROGRAMMING, verifying the solution is highly recommended!).
assert solver.VerifySolution(1e-7, True)
print 'Problem solved in %f milliseconds' % solver.wall_time()
# The objective value of the solution.
print('Optimal objective value = %f' % solver.Objective().Value())
print 'Optimal objective value = %f' % solver.Objective().Value()
# The value of each variable in the solution.
for variable in variable_list:
print('%s = %f' % (variable.name(), variable.SolutionValue()))
print '%s = %f' % (variable.name(), variable.solution_value())
print('Advanced usage:')
print('Problem solved in %d branch-and-bound nodes' % solver.Nodes())
print 'Advanced usage:'
print 'Problem solved in %d branch-and-bound nodes' % solver.nodes()
def Announce(solver, api_type):

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -45,7 +45,7 @@ def main(unused_argv):
solver.Init(profits, weights, capacities)
computed_profit = solver.Solve()
print('optimal profit = %i/%i' % (computed_profit, optimal_profit))
print 'optimal profit = ' + str(computed_profit) + '/' + str(optimal_profit)
if __name__ == '__main__':

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -16,6 +16,7 @@
from google.apputils import app
from ortools.linear_solver import linear_solver2_pb2
from ortools.linear_solver import pywraplp
@@ -23,27 +24,28 @@ def RunLinearExampleNaturalLanguageAPI(optimization_problem_type):
"""Example of simple linear program with natural language API."""
solver = pywraplp.Solver('RunLinearExampleNaturalLanguageAPI',
optimization_problem_type)
infinity = solver.Infinity()
infinity = solver.infinity()
# 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')
solver.Maximize(10 * x1 + 6 * x2 + 4 * x3)
c0 = solver.Add(x1 + x2 + x3 <= 100.0)
c1 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600)
c2 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300)
# TODO(user): Add example that uses sum()
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])
c2 = solver.Add(sum_of_vars <= 100.0, 'OtherConstraintName')
SolveAndPrint(solver, [x1, x2, x3], [c0, c1, c2])
# Print a linear expression's solution value.
print 'Sum of vars: %s = %s' % (sum_of_vars, sum_of_vars.solution_value())
def RunLinearExampleCppStyleAPI(optimization_problem_type):
"""Example of simple linear program with the C++ style API."""
solver = pywraplp.Solver('RunLinearExampleCppStyle',
optimization_problem_type)
infinity = solver.Infinity()
infinity = solver.infinity()
# x1, x2 and x3 are continuous non-negative variables.
x1 = solver.NumVar(0.0, infinity, 'x1')
x2 = solver.NumVar(0.0, infinity, 'x2')
@@ -79,65 +81,52 @@ def RunLinearExampleCppStyleAPI(optimization_problem_type):
def SolveAndPrint(solver, variable_list, constraint_list):
"""Solve the problem and print the solution."""
print('Number of variables = %d' % solver.NumVariables())
print('Number of constraints = %d' % solver.NumConstraints())
print 'Number of variables = %d' % solver.NumVariables()
print 'Number of constraints = %d' % solver.NumConstraints()
result_status = solver.Solve()
# The problem has an optimal solution.
assert result_status == pywraplp.Solver.OPTIMAL
print('Problem solved in %f milliseconds' % solver.WallTime())
# The solution looks legit (when using solvers others than
# GLOP_LINEAR_PROGRAMMING, verifying the solution is highly recommended!).
assert solver.VerifySolution(1e-7, True)
print 'Problem solved in %f milliseconds' % solver.wall_time()
# The objective value of the solution.
print('Optimal objective value = %f' % solver.Objective().Value())
print 'Optimal objective value = %f' % solver.Objective().Value()
# The value of each variable in the solution.
for variable in variable_list:
print('%s = %f' % (variable.name(), variable.SolutionValue()))
print '%s = %f' % (variable.name(), variable.solution_value())
print('Advanced usage:')
print('Problem solved in %d iterations' % solver.Iterations())
print 'Advanced usage:'
print 'Problem solved in %d iterations' % solver.iterations()
for variable in variable_list:
print('%s: reduced cost = %f' % (variable.name(), variable.ReducedCost()))
print '%s: reduced cost = %f' % (variable.name(), variable.reduced_cost())
for i, constraint in enumerate(constraint_list):
print ('constraint %d: dual value = %f\n'
' activity = %f' %
(i, constraint.DualValue(), constraint.Activity()))
def Announce(solver, api_type):
print ('---- Linear programming example with ' + solver + ' (' +
api_type + ') -----')
def RunAllLinearExampleNaturalLanguageAPI():
if hasattr(pywraplp.Solver, 'GLOP_LINEAR_PROGRAMMING'):
Announce('GLOP', 'natural language API')
RunLinearExampleNaturalLanguageAPI(pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
if hasattr(pywraplp.Solver, 'GLPK_LINEAR_PROGRAMMING'):
Announce('GLPK', 'natural language API')
RunLinearExampleNaturalLanguageAPI(pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)
if hasattr(pywraplp.Solver, 'CLP_LINEAR_PROGRAMMING'):
Announce('CLP', 'natural language API')
RunLinearExampleNaturalLanguageAPI(pywraplp.Solver.CLP_LINEAR_PROGRAMMING)
def RunAllLinearExampleCppStyleAPI():
if hasattr(pywraplp.Solver, 'GLOP_LINEAR_PROGRAMMING'):
Announce('GLOP', 'C++ style API')
RunLinearExampleCppStyleAPI(pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
if hasattr(pywraplp.Solver, 'GLPK_LINEAR_PROGRAMMING'):
Announce('GLPK', 'C++ style API')
RunLinearExampleCppStyleAPI(pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)
if hasattr(pywraplp.Solver, 'CLP_LINEAR_PROGRAMMING'):
Announce('CLP', 'C++ style API')
RunLinearExampleCppStyleAPI(pywraplp.Solver.CLP_LINEAR_PROGRAMMING)
(i, constraint.dual_value(), constraint.activity()))
def main(unused_argv):
RunAllLinearExampleNaturalLanguageAPI()
RunAllLinearExampleCppStyleAPI()
all_names_and_problem_types = (
linear_solver2_pb2.MPModelRequest.SolverType.items())
for name, problem_type in all_names_and_problem_types:
# Skip non-LP problem types.
if not name.endswith('LINEAR_PROGRAMMING'):
continue
# Skip problem types that aren't supported by the current binary.
if not pywraplp.Solver.SupportsProblemType(problem_type):
continue
print '\n------ Linear programming example with %s ------' % name
print '\n*** Natural language API ***'
RunLinearExampleNaturalLanguageAPI(problem_type)
print '\n*** C++ style API ***'
RunLinearExampleCppStyleAPI(problem_type)
if __name__ == '__main__':

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,13 +14,14 @@
"""MaxFlow and MinCostFlow examples."""
from google.apputils import app
from ortools.graph import pywrapgraph
def MaxFlow():
"""MaxFlow simple interface example."""
print('MaxFlow on a simple network.')
print 'MaxFlow on a simple network.'
tails = [0, 0, 0, 0, 1, 2, 3, 3, 4]
heads = [1, 2, 3, 4, 3, 4, 4, 5, 5]
capacities = [5, 8, 5, 3, 4, 5, 6, 6, 4]
@@ -29,17 +30,17 @@ def MaxFlow():
for i in range(0, len(tails)):
max_flow.AddArcWithCapacity(tails[i], heads[i], capacities[i])
if max_flow.Solve(0, 5) == max_flow.OPTIMAL:
print('Total flow %i/%i' % (max_flow.OptimalFlow(), expected_total_flow))
print 'Total flow', max_flow.OptimalFlow(), '/', expected_total_flow
for i in range(max_flow.NumArcs()):
print('From source %d to target %d: %d / %d' % (
print 'From source %d to target %d: %d / %d' % (
max_flow.Tail(i),
max_flow.Head(i),
max_flow.Flow(i),
max_flow.Capacity(i)))
print('Source side min-cut:', max_flow.GetSourceSideMinCut())
print('Sink side min-cut:', max_flow.GetSinkSideMinCut())
max_flow.Capacity(i))
print 'Source side min-cut:', max_flow.GetSourceSideMinCut()
print 'Sink side min-cut:', max_flow.GetSinkSideMinCut()
else:
print('There was an issue with the max flow input.')
print 'There was an issue with the max flow input.'
def MinCostFlow():
@@ -48,7 +49,7 @@ def MinCostFlow():
Note that this example is actually a linear sum assignment example and will
be more efficiently solved with the pywrapgraph.LinearSumAssignement class.
"""
print('MinCostFlow on 4x4 matrix.')
print 'MinCostFlow on 4x4 matrix.'
num_sources = 4
num_targets = 4
costs = [[90, 75, 75, 80],
@@ -66,15 +67,15 @@ def MinCostFlow():
min_cost_flow.SetNodeSupply(num_sources + node, -1)
status = min_cost_flow.Solve()
if status == min_cost_flow.OPTIMAL:
print('Total flow %i/%i' % (min_cost_flow.OptimalCost(), expected_cost))
print 'Total flow', min_cost_flow.OptimalCost(), '/', expected_cost
for i in range(0, min_cost_flow.NumArcs()):
if min_cost_flow.Flow(i) > 0:
print('From source %d to target %d: cost %d' % (
print 'From source %d to target %d: cost %d' % (
min_cost_flow.Tail(i),
min_cost_flow.Head(i) - num_sources,
min_cost_flow.UnitCost(i)))
min_cost_flow.UnitCost(i))
else:
print('There was an issue with the min cost flow input.')
print 'There was an issue with the min cost flow input.'
def main(unused_argv):

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -10,7 +10,6 @@
# 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.
#
"""Rabbit + Pheasant puzzle.
@@ -22,16 +21,17 @@ flavors of constraint programming interfaces.
"""
from ortools.constraint_solver import pywrapcp
def main():
# Create the solver.
solver = pywrapcp.Solver("rabbit+pheasant")
solver = pywrapcp.Solver('rabbit+pheasant')
# Create the variables.
pheasant = solver.IntVar(0, 100, "pheasant")
rabbit = solver.IntVar(0, 100, "rabbit")
pheasant = solver.IntVar(0, 100, 'pheasant')
rabbit = solver.IntVar(0, 100, 'rabbit')
# Create the constraints.
solver.Add(pheasant + rabbit == 20)
@@ -52,5 +52,5 @@ def main():
solver.EndSearch()
print solver
if __name__ == "__main__":
if __name__ == '__main__':
main()

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -10,7 +10,6 @@
# 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.
#
"""Send + more = money.
@@ -20,6 +19,7 @@ Each letter corresponds to one figure and all letters have different values.
"""
from google.apputils import app
import gflags
from ortools.constraint_solver import pywrapcp
@@ -43,8 +43,10 @@ def main(unused_argv):
letters = [s, e, n, d, m, o, r, y]
solver.Add(1000 * s + 100 * e + 10 * n + d + 1000 * m + 100 * o + 10 * r + e ==
10000 * m + 1000 * o + 100 * n + 10 * e + y)
solver.Add(
1000 * s + 100 * e + 10 * n + d +
1000 * m + 100 * o + 10 * r + e ==
10000 * m + 1000 * o + 100 * n + 10 * e + y)
# pylint: disable=g-explicit-bool-comparison
solver.Add(s != 0)

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -10,7 +10,6 @@
# 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 meeting scheduler.
@@ -27,6 +26,7 @@ in the meeting and a maximum of non mandatory people are also in the meeting.
"""
from google.apputils import app
import gflags
from ortools.constraint_solver import pywrapcp

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -10,11 +10,11 @@
# 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.
#
"""This model implements a sudoku solver."""
from google.apputils import app
import gflags
from ortools.constraint_solver import pywrapcp

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -10,7 +10,6 @@
# 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.
#
"""Traveling Salesman Sample.
@@ -25,6 +24,7 @@
"""
import random
from google.apputils import app
@@ -34,11 +34,11 @@ from ortools.constraint_solver import pywrapcp
FLAGS = gflags.FLAGS
gflags.DEFINE_integer('tsp_size', 10,
'Size of Traveling Salesman Problem instance.')
'Size of Traveling Salesman Problem instance.')
gflags.DEFINE_boolean('tsp_use_random_matrix', True,
'Use random cost matrix.')
'Use random cost matrix.')
gflags.DEFINE_integer('tsp_random_forbidden_connections', 0,
'Number of random forbidden connections.')
'Number of random forbidden connections.')
gflags.DEFINE_integer('tsp_random_seed', 0, 'Random seed.')
gflags.DEFINE_boolean('light_propagation', False, 'Use light propagation')
@@ -62,9 +62,9 @@ class RandomMatrix(object):
rand.seed(FLAGS.tsp_random_seed)
distance_max = 100
self.matrix = {}
for from_node in range(size):
for from_node in xrange(size):
self.matrix[from_node] = {}
for to_node in range(size):
for to_node in xrange(size):
if from_node == to_node:
self.matrix[from_node][to_node] = 0
else:
@@ -113,7 +113,7 @@ def main(_):
from_node = rand.randrange(FLAGS.tsp_size - 1)
to_node = rand.randrange(FLAGS.tsp_size - 1) + 1
if routing.NextVar(from_node).Contains(to_node):
print('Forbidding connection %i -> %i' % (from_node, to_node))
print 'Forbidding connection ' + str(from_node) + ' -> ' + str(to_node)
routing.NextVar(from_node).RemoveValue(to_node)
forbidden_connections += 1
@@ -121,7 +121,7 @@ def main(_):
assignment = routing.SolveWithParameters(parameters, None)
if assignment:
# Solution cost.
print(assignment.ObjectiveValue())
print assignment.ObjectiveValue()
# Inspect solution.
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1
route_number = 0
@@ -131,11 +131,11 @@ def main(_):
route += str(node) + ' -> '
node = assignment.Value(routing.NextVar(node))
route += '0'
print(route)
print route
else:
print('No solution found.')
print 'No solution found.'
else:
print('Specify an instance greater than 0.')
print 'Specify an instance greater than 0.'
if __name__ == '__main__':
app.run()

View File

@@ -1,4 +1,4 @@
# Copyright 2010-2013 Google
# Copyright 2010-2014 Google
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -114,8 +114,8 @@ def main(unused_argv):
people = [englishman, spaniard, japanese, ukrainian, norwegian]
water_drinker = [p for p in people if p.Value() == water.Value()][0]
zebra_owner = [p for p in people if p.Value() == zebra.Value()][0]
print 'The %s drinks water.' % water_drinker.name()
print 'The %s owns the zebra.' % zebra_owner.name()
print 'The %s drinks water.' % water_drinker.Name()
print 'The %s owns the zebra.' % zebra_owner.Name()
else:
print 'No solutions to the zebra problem, this is unusual!'
solver.EndSearch()

View File

@@ -141,7 +141,7 @@ class DumbGreaterOrEqualToFive(pywrapcp.PyConstraint):
if self._x.Bound():
if self._x.Value() < 5:
print 'Reject %d' % self._x.Value()
self.solver().Fail()
self.Solver().Fail()
else:
print 'Accept %d' % self._x.Value()
@@ -235,8 +235,8 @@ def main():
test_member()
test_sparse_var()
test_modulo()
test_limit()
test_export()
# test_limit()
# test_export()
test_search_monitor()
test_demon()
test_failing_constraint()

View File

@@ -52,7 +52,7 @@ def test_proto():
def main():
test_sum_no_brackets()
test_proto()
# test_proto()
if __name__ == '__main__':

View File

@@ -0,0 +1,145 @@
// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SWIG wrapping of some Callbacks in python.
// This doesn't directly expose a C++ API; rather it provides typemaps that can
// be used by other .swig files to easily expose APIs that use callbacks.
// See its usage in ../../constraint_solver/python/constraint_solver.swig.
//
// TODO(user): Nuke this file and use the callback wrapping code in
// base/swig/python/... when it is available.
%include "base/base.swig"
%import "base/callback.h"
%{
using std::string;
static string PyCallbackString(PyObject* pyfunc) {
PyObject* pyresult = PyObject_CallFunctionObjArgs(pyfunc, nullptr);
string result;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback<string> invocation failed.");
} else {
result = PyString_AsString(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback<string>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallbackString, $input);
}
%{
static int64 PyCallback1Int64Int64(PyObject* pyfunc, int64 i) {
// () needed to force creation of one-element tuple
PyObject* pyresult = PyEval_CallFunction(pyfunc, "(l)", static_cast<long>(i));
int64 result = 0;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback1<int64, int64> invocation failed.");
} else {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback1<int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback1Int64Int64, $input);
}
%{
static int64 PyCallback2Int64Int64Int64(PyObject* pyfunc, int64 i, int64 j) {
PyObject* pyresult = PyEval_CallFunction(pyfunc, "ll", static_cast<long>(i),
static_cast<long>(j));
int64 result = 0;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback2<int64, int64, int64> invocation failed.");
} else {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback2<int64, int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback2Int64Int64Int64, $input);
}
%{
static int64 PyCallback3Int64Int64Int64Int64(PyObject* pyfunc,
int64 i, int64 j, int64 k) {
PyObject* pyresult = PyEval_CallFunction(pyfunc, "lll", static_cast<long>(i),
static_cast<long>(j),
static_cast<long>(k));
int64 result = 0;
if (!pyresult) {
PyErr_SetString(
PyExc_RuntimeError,
"ResultCallback3<int64, int64, int64, int64> invocation failed.");
} else {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback3<int64, int64, int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback3Int64Int64Int64Int64, $input);
}
%{
static bool PyCallbackBool(PyObject* pyfunc) {
PyObject* pyresult = PyObject_CallFunctionObjArgs(pyfunc, nullptr);
bool result = false;
if (!pyresult) {
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback<bool> invocation failed.");
} else {
result = PyObject_IsTrue(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback<bool>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallbackBool, $input);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This .h file cannot be used in isolation!
// It represents some of the inlined C++ content of ./constraint_solver.swig,
// and was split out because it's a large enough chunk of C++ code.
//
// It can only be interpreted in the context of ./constraint_solver.swig, where
// it is included.
#ifndef OR_TOOLS_CONSTRAINT_SOLVER_PYTHON_PYWRAPCP_UTIL_H_
#define OR_TOOLS_CONSTRAINT_SOLVER_PYTHON_PYWRAPCP_UTIL_H_
#include <setjmp.h> // For FailureProtect. See below.
#include <string>
#include "constraint_solver/constraint_solver.h"
#include "constraint_solver/constraint_solveri.h"
using std::string;
// Used in the PROTECT_FROM_FAILURE macro. See below.
struct FailureProtect {
jmp_buf exception_buffer;
void JumpBack() { longjmp(exception_buffer, 1); }
};
class CallPyDecisionBuilder : public operations_research::DecisionBuilder {
public:
explicit CallPyDecisionBuilder(PyObject* pydb)
: pysolver_(nullptr), pyarg_(nullptr) {
Py_INCREF(pydb);
pydb_ = pydb;
func_ = PyObject_GetAttrString(pydb_, "NextWrapper");
Py_XINCREF(func_);
str_func_ = PyObject_GetAttrString(pydb_, "DebugString");
Py_XINCREF(str_func_);
}
virtual ~CallPyDecisionBuilder() {
Py_CLEAR(pydb_);
Py_CLEAR(func_);
Py_CLEAR(str_func_);
Py_CLEAR(pysolver_);
Py_CLEAR(pyarg_);
}
virtual operations_research::Decision* Next(
operations_research::Solver* const s) {
if (pysolver_ == nullptr) {
pysolver_ = SWIG_NewPointerObj(s, SWIGTYPE_p_operations_research__Solver,
SWIG_POINTER_EXCEPTION);
pyarg_ = Py_BuildValue("(O)", pysolver_);
}
operations_research::Decision* result = nullptr;
PyObject* pyresult = PyEval_CallObject(func_, pyarg_);
if (pyresult) {
if (SWIG_ConvertPtr(pyresult, reinterpret_cast<void**>(&result),
SWIGTYPE_p_operations_research__Decision,
SWIG_POINTER_EXCEPTION | 0) == -1) {
LOG(INFO) << "Error in type from python Decision";
}
Py_DECREF(pyresult);
} else { // something went wrong, we fail.
PyErr_SetString(PyExc_RuntimeError,
"ResultCallback<std::string> invocation failed.");
s->FinishCurrentSearch();
}
return result;
}
virtual std::string DebugString() const {
std::string result = "PyDecisionBuilder";
if (str_func_) {
PyObject* pyresult = PyEval_CallObject(str_func_, nullptr);
if (pyresult) {
result = PyString_AsString(pyresult);
Py_DECREF(pyresult);
}
}
return result;
}
private:
PyObject* pysolver_;
PyObject* pyarg_;
PyObject* pydb_;
PyObject* func_;
PyObject* str_func_;
};
class PyLNSNoValues : public operations_research::BaseLNS {
public:
PyLNSNoValues(const std::vector<operations_research::IntVar*>& vars, PyObject* op)
: BaseLNS(vars), op_(op) {
Py_INCREF(op_);
init_func_ = PyObject_GetAttrString(op_, "InitFragments");
Py_XINCREF(init_func_);
fragment_func_ = PyObject_GetAttrString(op_, "NextFragment");
Py_XINCREF(fragment_func_);
}
virtual ~PyLNSNoValues() {
Py_CLEAR(op_);
Py_CLEAR(init_func_);
Py_CLEAR(fragment_func_);
}
virtual void InitFragments() {
if (init_func_) {
PyObject* pyresult = PyEval_CallObject(init_func_, nullptr);
Py_XDECREF(pyresult);
}
}
virtual bool NextFragment(std::vector<int>* fragment) {
PyObject* list = PyList_New(0);
PyObject* args = Py_BuildValue(const_cast<char*>("(O)"), list);
PyObject* pyresult = PyEval_CallObject(fragment_func_, args);
Py_DECREF(args);
const int size = PyList_Size(list);
for (size_t i = 0; i < size; ++i) {
const int val = PyInt_AsLong(PyList_GetItem(list, i));
fragment->push_back(val);
}
Py_DECREF(list);
bool result = false;
if (pyresult) {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
virtual std::string DebugString() const { return "PyLNSNoValues()"; }
private:
PyObject* op_;
PyObject* init_func_;
PyObject* fragment_func_;
};
class PyLNS : public operations_research::BaseLNS {
public:
PyLNS(const std::vector<operations_research::IntVar*>& vars, PyObject* op)
: BaseLNS(vars), op_(op) {
Py_INCREF(op_);
init_func_ = nullptr;
if (PyObject_HasAttrString(op_, "InitFragments")) {
init_func_ = PyObject_GetAttrString(op_, "InitFragments");
Py_INCREF(init_func_);
}
fragment_func_ = nullptr;
if (PyObject_HasAttrString(op_, "NextFragment")) {
fragment_func_ = PyObject_GetAttrString(op_, "NextFragment");
Py_INCREF(fragment_func_);
}
base_lns_ = SWIG_NewPointerObj(
this, SWIGTYPE_p_operations_research__BaseLNS, SWIG_POINTER_EXCEPTION);
Py_INCREF(base_lns_);
}
virtual ~PyLNS() {
Py_CLEAR(op_);
Py_CLEAR(init_func_);
Py_CLEAR(fragment_func_);
Py_CLEAR(base_lns_);
}
virtual void InitFragments() {
if (init_func_) {
PyObject* pyresult = PyEval_CallObject(init_func_, nullptr);
Py_XDECREF(pyresult);
}
}
virtual bool NextFragment(std::vector<int>* fragment) {
PyObject* list = PyList_New(0);
PyObject* args = Py_BuildValue(const_cast<char*>("(OO)"), list, base_lns_);
PyObject* pyresult = PyEval_CallObject(fragment_func_, args);
Py_DECREF(args);
const int size = PyList_Size(list);
for (size_t i = 0; i < size; ++i) {
const int val = PyInt_AsLong(PyList_GetItem(list, i));
fragment->push_back(val);
}
Py_DECREF(list);
bool result = false;
if (pyresult) {
result = PyInt_AsLong(pyresult);
Py_DECREF(pyresult);
}
return result;
}
virtual std::string DebugString() const { return "PyLNS()"; }
private:
PyObject* op_;
PyObject* init_func_;
PyObject* fragment_func_;
PyObject* base_lns_;
};
// Conversion helpers. In SWIG python, "PyObjAs" is the method that determines
// wheter a python object can be interpreted as a C++ object.
#endif // OR_TOOLS_CONSTRAINT_SOLVER_PYTHON_PYWRAPCP_UTIL_H_

View File

@@ -1,4 +1,4 @@
// Copyright 2010-2013 Google
// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -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.
// TODO(user): Refactor this file to adhere to the SWIG style guide.
%include "constraint_solver/python/constraint_solver.swig"
@@ -38,7 +39,7 @@ bool PyObjAs(PyObject *py, operations_research::RoutingModel::NodeIndex* i) {
%}
PY_LIST_OUTPUT_TYPEMAP(operations_research::RoutingModel::NodeIndex,
PyInt_Check, PyInt_FromLong);
// TODO(user): also support std::vector<std::vector<>> <-> list of list for python.
// TODO(user): also support std::vector<std::vector<>> <-> list of list.
// Create input mapping for NodeEvaluator2
%{

View File

@@ -1,4 +1,4 @@
// Copyright 2010-2013 Google
// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -10,7 +10,6 @@
// 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.
// This .swig files exposes some of the C++ classes in ../, namely :
// - SimpleMaxFlow, from ../max_flow.h
// - SimpleMinCostFlow, from ../min_cost_flow.h