diff --git a/examples/contrib/fsdiet.fs b/examples/contrib/fsdiet.fs index 7f8b949787..43a29b702c 100644 --- a/examples/contrib/fsdiet.fs +++ b/examples/contrib/fsdiet.fs @@ -38,7 +38,7 @@ solver.Add( x.ScalProd(chocolate).solver().MakeGreaterOrEqual(x.ScalProd(chocola solver.Add( x.ScalProd(sugar).solver().MakeGreaterOrEqual(x.ScalProd(sugar), limits.[2])) solver.Add( x.ScalProd(fat).solver().MakeGreaterOrEqual(x.ScalProd(fat), limits.[3])) -let obj = cost.Minimize(1L) +let obj = cost.Minimize(1) let db = solver.MakePhase(new IntVarVector(x), Solver.CHOOSE_PATH, Solver.ASSIGN_MIN_VALUE) solver.NewSearch(db, obj) diff --git a/examples/java/IntegerProgramming.java b/examples/java/IntegerProgramming.java index 935a5db699..2d48a6c379 100644 --- a/examples/java/IntegerProgramming.java +++ b/examples/java/IntegerProgramming.java @@ -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. + package com.google.ortools.examples; import com.google.ortools.linearsolver.MPConstraint; @@ -27,17 +28,8 @@ public class IntegerProgramming { System.loadLibrary("jniortools"); } - private static MPSolver createSolver(String solverType) { - try { - return new MPSolver( - "IntegerProgrammingExample", MPSolver.OptimizationProblemType.valueOf(solverType)); - } catch (java.lang.IllegalArgumentException e) { - return null; - } - } - private static void runIntegerProgrammingExample(String solverType) { - MPSolver solver = createSolver(solverType); + MPSolver solver = MPSolver.createSolver("IntegerProgramming", solverType); if (solver == null) { System.out.println("Could not create solver " + solverType); return; @@ -91,7 +83,7 @@ public class IntegerProgramming { runIntegerProgrammingExample("SCIP_MIXED_INTEGER_PROGRAMMING"); System.out.println("---- Integer programming example with CBC ----"); runIntegerProgrammingExample("CBC_MIXED_INTEGER_PROGRAMMING"); - System.out.println("---- Integer programming example with GLPK ----"); - runIntegerProgrammingExample("GLPK_MIXED_INTEGER_PROGRAMMING"); + System.out.println("---- Integer programming example with CP-SAT ----"); + runIntegerProgrammingExample("SAT_INTEGER_PROGRAMMING"); } } diff --git a/examples/java/LinearProgramming.java b/examples/java/LinearProgramming.java index 05710a76fb..c6cf0e5900 100644 --- a/examples/java/LinearProgramming.java +++ b/examples/java/LinearProgramming.java @@ -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. + package com.google.ortools.examples; import com.google.ortools.linearsolver.MPConstraint; @@ -27,17 +28,8 @@ public class LinearProgramming { System.loadLibrary("jniortools"); } - private static MPSolver createSolver(String solverType) { - try { - return new MPSolver( - "LinearProgrammingExample", MPSolver.OptimizationProblemType.valueOf(solverType)); - } catch (java.lang.IllegalArgumentException e) { - return null; - } - } - private static void runLinearProgrammingExample(String solverType, boolean printModel) { - MPSolver solver = createSolver(solverType); + MPSolver solver = MPSolver.createSolver("IntegerProgramming", solverType); if (solver == null) { System.out.println("Could not create solver " + solverType); return; @@ -127,7 +119,5 @@ public class LinearProgramming { runLinearProgrammingExample("GLOP_LINEAR_PROGRAMMING", true); System.out.println("---- Linear programming example with CLP ----"); runLinearProgrammingExample("CLP_LINEAR_PROGRAMMING", false); - System.out.println("---- Linear programming example with GLPK ----"); - runLinearProgrammingExample("GLPK_LINEAR_PROGRAMMING", false); } } diff --git a/examples/python/integer_programming.py b/examples/python/integer_programming.py index 039a297ef7..e1693eac48 100644 --- a/examples/python/integer_programming.py +++ b/examples/python/integer_programming.py @@ -17,10 +17,21 @@ from __future__ import print_function from ortools.linear_solver import pywraplp +def Announce(solver, api_type): + print('---- Integer programming example with ' + solver + ' (' + api_type + + ') -----') + + def RunIntegerExampleNaturalLanguageAPI(optimization_problem_type): """Example of simple integer program with natural language API.""" - solver = pywraplp.Solver('RunIntegerExampleNaturalLanguageAPI', - optimization_problem_type) + + solver = pywraplp.Solver.CreateSolver('RunIntegerExampleNaturalLanguageAPI', + optimization_problem_type) + if not solver: + return + + Announce(optimization_problem_type, 'natural language API') + infinity = solver.infinity() # x1 and x2 are integer non-negative variables. x1 = solver.IntVar(0.0, infinity, 'x1') @@ -34,8 +45,13 @@ def RunIntegerExampleNaturalLanguageAPI(optimization_problem_type): def RunIntegerExampleCppStyleAPI(optimization_problem_type): """Example of simple integer program with the C++ style API.""" - solver = pywraplp.Solver('RunIntegerExampleCppStyleAPI', - optimization_problem_type) + solver = pywraplp.Solver.CreateSolver('RunIntegerExampleCppStyleAPI', + optimization_problem_type) + if not solver: + return + + Announce(optimization_problem_type, 'C++ style API') + infinity = solver.infinity() # x1 and x2 are integer non-negative variables. x1 = solver.IntVar(0.0, infinity, 'x1') @@ -59,7 +75,6 @@ def SolveAndPrint(solver, variable_list): print('Number of variables = %d' % solver.NumVariables()) print('Number of constraints = %d' % solver.NumConstraints()) - solver.SetNumThreads(8) result_status = solver.Solve() # The problem has an optimal solution. @@ -82,55 +97,18 @@ def SolveAndPrint(solver, variable_list): print('Problem solved in %d branch-and-bound nodes' % solver.nodes()) -def Announce(solver, api_type): - print('---- Integer programming example with ' + solver + ' (' + api_type + - ') -----') - - def RunAllIntegerExampleNaturalLanguageAPI(): - if hasattr(pywraplp.Solver, 'GLPK_MIXED_INTEGER_PROGRAMMING'): - Announce('GLPK', 'natural language API') - RunIntegerExampleNaturalLanguageAPI( - pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'CBC_MIXED_INTEGER_PROGRAMMING'): - Announce('CBC', 'natural language API') - RunIntegerExampleNaturalLanguageAPI( - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'SCIP_MIXED_INTEGER_PROGRAMMING'): - Announce('SCIP', 'natural language API') - RunIntegerExampleNaturalLanguageAPI( - pywraplp.Solver.SCIP_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'GUROBI_MIXED_INTEGER_PROGRAMMING'): - Announce('GUROBI', 'natural language API') - RunIntegerExampleNaturalLanguageAPI( - pywraplp.Solver.GUROBI_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'CPLEX_MIXED_INTEGER_PROGRAMMING'): - Announce('CPLEX', 'natural language API') - RunIntegerExampleNaturalLanguageAPI( - pywraplp.Solver.CPLEX_MIXED_INTEGER_PROGRAMMING) + RunIntegerExampleNaturalLanguageAPI('GLPK') + RunIntegerExampleNaturalLanguageAPI('CBC') + RunIntegerExampleNaturalLanguageAPI('SCIP') + RunIntegerExampleNaturalLanguageAPI('SAT') def RunAllIntegerExampleCppStyleAPI(): - if hasattr(pywraplp.Solver, 'GLPK_MIXED_INTEGER_PROGRAMMING'): - Announce('GLPK', 'C++ style API') - RunIntegerExampleCppStyleAPI( - pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'CBC_MIXED_INTEGER_PROGRAMMING'): - Announce('CBC', 'C++ style API') - RunIntegerExampleCppStyleAPI( - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'SCIP_MIXED_INTEGER_PROGRAMMING'): - Announce('SCIP', 'C++ style API') - RunIntegerExampleCppStyleAPI( - pywraplp.Solver.SCIP_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'GUROBI_MIXED_INTEGER_PROGRAMMING'): - Announce('GUROBI', 'C++ style API') - RunIntegerExampleCppStyleAPI( - pywraplp.Solver.GUROBI_MIXED_INTEGER_PROGRAMMING) - if hasattr(pywraplp.Solver, 'CPLEX_MIXED_INTEGER_PROGRAMMING'): - Announce('CPLEX', 'C++ style API') - RunIntegerExampleCppStyleAPI( - pywraplp.Solver.CPLEX_MIXED_INTEGER_PROGRAMMING) + RunIntegerExampleCppStyleAPI('GLPK') + RunIntegerExampleCppStyleAPI('CBC') + RunIntegerExampleCppStyleAPI('SCIP') + RunIntegerExampleCppStyleAPI('SAT') def main(): diff --git a/examples/python/linear_programming.py b/examples/python/linear_programming.py index 40740e7c72..4f404bb60e 100644 --- a/examples/python/linear_programming.py +++ b/examples/python/linear_programming.py @@ -1,6 +1,4 @@ -#!/usr/bin/env python -# This Python file uses the following encoding: utf-8 -# Copyright 2018 Google LLC +# Copyright 2010-2018 Google LLC # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -12,73 +10,130 @@ # 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""" +"""Linear programming examples that show how to use the APIs.""" from __future__ import print_function from ortools.linear_solver import pywraplp -def main(): - """Entry point of the program""" - # Instantiate a Glop solver, naming it LinearExample. - solver = pywraplp.Solver('LinearExample', - pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) +def Announce(solver, api_type): + print('---- Linear programming example with ' + solver + ' (' + api_type + + ') -----') - # Create the two variables and let them take on any value. - x = solver.NumVar(-solver.infinity(), solver.infinity(), 'x') - y = solver.NumVar(-solver.infinity(), solver.infinity(), 'y') - # Objective function: Maximize 3x + 4y. +def RunLinearExampleNaturalLanguageAPI(optimization_problem_type): + """Example of simple linear program with natural language API.""" + solver = pywraplp.Solver.CreateSolver('RunLinearExampleNaturalLanguageAPI', + optimization_problem_type) + + if not solver: + return + + Announce(optimization_problem_type, 'natural language API') + + 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(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.CreateSolver('RunLinearExampleCppStyle', + optimization_problem_type) + if not solver: + return + + Announce(optimization_problem_type, 'C++ style API') + + 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') + + # Maximize 10 * x1 + 6 * x2 + 4 * x3. objective = solver.Objective() - objective.SetCoefficient(x, 3) - objective.SetCoefficient(y, 4) + objective.SetCoefficient(x1, 10) + objective.SetCoefficient(x2, 6) + objective.SetCoefficient(x3, 4) objective.SetMaximization() - # Constraint 0: x + 2y <= 14. - constraint0 = solver.Constraint(-solver.infinity(), 14) - constraint0.SetCoefficient(x, 1) - constraint0.SetCoefficient(y, 2) + # x1 + x2 + x3 <= 100. + c0 = solver.Constraint(-infinity, 100.0, 'c0') + c0.SetCoefficient(x1, 1) + c0.SetCoefficient(x2, 1) + c0.SetCoefficient(x3, 1) - # Constraint 1: 3x - y >= 0. - constraint1 = solver.Constraint(0, solver.infinity()) - constraint1.SetCoefficient(x, 3) - constraint1.SetCoefficient(y, -1) + # 10 * x1 + 4 * x2 + 5 * x3 <= 600. + c1 = solver.Constraint(-infinity, 600.0, 'c1') + c1.SetCoefficient(x1, 10) + c1.SetCoefficient(x2, 4) + c1.SetCoefficient(x3, 5) - # Constraint 2: x - y <= 2. - constraint2 = solver.Constraint(-solver.infinity(), 2) - constraint2.SetCoefficient(x, 1) - constraint2.SetCoefficient(y, -1) + # 2 * x1 + 2 * x2 + 6 * x3 <= 300. + c2 = solver.Constraint(-infinity, 300.0, 'c2') + c2.SetCoefficient(x1, 2) + c2.SetCoefficient(x2, 2) + c2.SetCoefficient(x3, 6) - print('Number of variables =', solver.NumVariables()) - print('Number of constraints =', solver.NumConstraints()) + SolveAndPrint(solver, [x1, x2, x3], [c0, c1, c2]) - # Solve the system. - status = solver.Solve() - # Check that the problem has an optimal solution. - if status != pywraplp.Solver.OPTIMAL: - print("The problem does not have an optimal solution!") - exit(1) - print('Solution:') - print('x =', x.solution_value()) - print('y =', y.solution_value()) - print('Optimal objective value =', objective.Value()) - print('') +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()) + + result_status = solver.Solve() + + # The problem has an optimal solution. + assert result_status == pywraplp.Solver.OPTIMAL + + # 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()) + + # The value of each variable in the solution. + for variable in variable_list: + print('%s = %f' % (variable.name(), variable.solution_value())) + print('Advanced usage:') - print('Problem solved in ', solver.wall_time(), ' milliseconds') - print('Problem solved in ', solver.iterations(), ' iterations') - print('x: reduced cost =', x.reduced_cost()) - print('y: reduced cost =', y.reduced_cost()) + print('Problem solved in %d iterations' % solver.iterations()) + for variable in variable_list: + print('%s: reduced cost = %f' % + (variable.name(), variable.reduced_cost())) activities = solver.ComputeConstraintActivities() - print('constraint0: dual value =', - constraint0.dual_value(), ' activities =', - activities[constraint0.index()]) - print('constraint1: dual value =', - constraint1.dual_value(), ' activities =', - activities[constraint1.index()]) - print('constraint2: dual value =', - constraint2.dual_value(), ' activities =', - activities[constraint2.index()]) + for i, constraint in enumerate(constraint_list): + print(('constraint %d: dual value = %f\n' + ' activity = %f' % + (i, constraint.dual_value(), activities[constraint.index()]))) + + +def main(): + RunLinearExampleNaturalLanguageAPI('GLOP') + RunLinearExampleNaturalLanguageAPI('GLPK_LP') + RunLinearExampleNaturalLanguageAPI('CLP') + + RunLinearExampleCppStyleAPI('GLOP') + RunLinearExampleCppStyleAPI('GLPK_LP') + RunLinearExampleCppStyleAPI('CLP') if __name__ == '__main__': diff --git a/examples/tests/LinearSolverTests.cs b/examples/tests/LinearSolverTests.cs index d284555419..f7f61c2db1 100644 --- a/examples/tests/LinearSolverTests.cs +++ b/examples/tests/LinearSolverTests.cs @@ -6,9 +6,7 @@ namespace Google.OrTools.Tests { public class LinearSolverTest { [Fact] public void VarOperator() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -46,9 +44,7 @@ namespace Google.OrTools.Tests { [Fact] public void VarAddition() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -77,9 +73,7 @@ namespace Google.OrTools.Tests { [Fact] public void VarMultiplication() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -113,9 +107,7 @@ namespace Google.OrTools.Tests { [Fact] public void BinaryOperator() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -148,9 +140,7 @@ namespace Google.OrTools.Tests { [Fact] public void Inequalities() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -186,9 +176,7 @@ namespace Google.OrTools.Tests { [Fact] public void SumArray() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable[] x = solver.MakeBoolVarArray(10, "x"); Constraint ct1 = solver.Add(x.Sum() == 3); @@ -206,9 +194,7 @@ namespace Google.OrTools.Tests { [Fact] public void Objective() { - Solver solver = new Solver( - "Solver", - Solver.OptimizationProblemType.CLP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("Solver", "CLP"); Variable x = solver.MakeNumVar(0.0, 100.0, "x"); Assert.Equal(0.0, x.Lb()); Assert.Equal(100.0, x.Ub()); @@ -260,8 +246,12 @@ namespace Google.OrTools.Tests { } } - void RunLinearProgrammingExample(in Solver.OptimizationProblemType problemType) { - Solver solver = new Solver("LinearProgrammingExample", problemType); + void RunLinearProgrammingExample(in String problemType) { + Console.WriteLine($"------ Linear programming example with {problemType} ------"); + + Solver solver = Solver.CreateSolver("LinearProgrammingExample", problemType); + if (solver == null) return; + // x and y are continuous non-negative variables. Variable x = solver.MakeNumVar(0.0, double.PositiveInfinity, "x"); Variable y = solver.MakeNumVar(0.0, double.PositiveInfinity, "y"); @@ -289,8 +279,12 @@ namespace Google.OrTools.Tests { SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1, c2 }); } - void RunMixedIntegerProgrammingExample(in Solver.OptimizationProblemType problemType) { - Solver solver = new Solver("MixedIntegerProgrammingExample", problemType); + void RunMixedIntegerProgrammingExample(in String problemType) { + Console.WriteLine($"------ Mixed integer programming example with {problemType} ------"); + + Solver solver = Solver.CreateSolver("MixedIntegerProgrammingExample", problemType); + if (solver == null) return; + // x and y are integers non-negative variables. Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x"); Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y"); @@ -313,8 +307,12 @@ namespace Google.OrTools.Tests { SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1 }); } - void RunBooleanProgrammingExample(in Solver.OptimizationProblemType problemType) { - Solver solver = new Solver("BooleanProgrammingExample", problemType); + void RunBooleanProgrammingExample(in String problemType) { + Console.WriteLine($"------ Boolean programming example with {problemType} ------"); + + Solver solver = Solver.CreateSolver("BooleanProgrammingExample", problemType); + if (solver == null) return; + // x and y are boolean variables. Variable x = solver.MakeBoolVar("x"); Variable y = solver.MakeBoolVar("y"); @@ -335,28 +333,24 @@ namespace Google.OrTools.Tests { [Fact] public void OptimizationProblemType() { - Array problem_types = Enum.GetValues(typeof(Solver.OptimizationProblemType)); - foreach (Solver.OptimizationProblemType problem_type in problem_types) { - if (problem_type.ToString().EndsWith("LINEAR_PROGRAMMING")) { - Console.WriteLine($"------ Linear programming example with {problem_type} ------"); - RunLinearProgrammingExample(problem_type); - } else if (problem_type.ToString().EndsWith("MIXED_INTEGER_PROGRAMMING")) { - Console.WriteLine($"------ Mixed Integer programming example with {problem_type} ------"); - RunMixedIntegerProgrammingExample(problem_type); - } else if (problem_type.ToString().EndsWith("INTEGER_PROGRAMMING")) { - Console.WriteLine($"------ Boolean programming example with {problem_type} ------"); - RunBooleanProgrammingExample(problem_type); - } else { - Console.WriteLine($"Problem type {problem_type} unknow !"); - } - } + RunLinearProgrammingExample("GLOP"); + RunLinearProgrammingExample("GLPK_LP"); + RunLinearProgrammingExample("CLP"); + RunLinearProgrammingExample("GUROBI_LP"); + + RunMixedIntegerProgrammingExample("GLPK"); + RunMixedIntegerProgrammingExample("CBC"); + RunMixedIntegerProgrammingExample("SCIP"); + RunMixedIntegerProgrammingExample("SAT"); + + RunBooleanProgrammingExample("SAT"); + RunBooleanProgrammingExample("BOP"); } [Fact] static void testSetHintAndSolverGetters() { Console.WriteLine("testSetHintAndSolverGetters"); - Solver solver = new Solver("testSetHintAndSolverGetters", - Solver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING); + Solver solver = Solver.CreateSolver("testSetHintAndSolverGetters", "glop"); // x and y are continuous non-negative variables. Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x"); Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y"); diff --git a/examples/tests/TestLinearSolver.java b/examples/tests/TestLinearSolver.java index 3f2d253d62..98871efa87 100644 --- a/examples/tests/TestLinearSolver.java +++ b/examples/tests/TestLinearSolver.java @@ -50,6 +50,8 @@ public class TestLinearSolver { logger.info("Advanced usage:"); logger.info("Problem solved in " + solver.wallTime() + " milliseconds"); logger.info("Problem solved in " + solver.iterations() + " iterations"); + if (solver.isMip()) return; + vars.forEach( var-> logger.info(var.name() + ": reduced cost " + var.reducedCost()) ); @@ -62,8 +64,12 @@ public class TestLinearSolver { ); } - static void runLinearProgrammingExample(MPSolver.OptimizationProblemType problem_type) { - MPSolver solver = new MPSolver("LinearProgrammingExample", problem_type); + static void runLinearProgrammingExample(String problem_type) { + logger.info("------ Linear programming example with " + problem_type + " ------"); + + MPSolver solver = MPSolver.createSolver("LinearProgrammingExample", problem_type); + if (solver == null) return; + // x and y are continuous non-negative variables. MPVariable x = solver.makeNumVar(0.0, Double.POSITIVE_INFINITY, "x"); MPVariable y = solver.makeNumVar(0.0, Double.POSITIVE_INFINITY, "y"); @@ -92,8 +98,12 @@ public class TestLinearSolver { solveAndPrint(solver, new MPVariable[] {x, y}, new MPConstraint[] {c0, c1, c2}); } - static void runMixedIntegerProgrammingExample(MPSolver.OptimizationProblemType problem_type) { - MPSolver solver = new MPSolver("MixedIntegerProgrammingExample", problem_type); + static void runMixedIntegerProgrammingExample(String problem_type) { + logger.info("------ Mixed integer programming example with " + problem_type + " ------"); + + MPSolver solver = MPSolver.createSolver("MixedIntegerProgrammingExample", problem_type); + if (solver == null) return; + // x and y are continuous non-negative variables. MPVariable x = solver.makeIntVar(0.0, Double.POSITIVE_INFINITY, "x"); MPVariable y = solver.makeIntVar(0.0, Double.POSITIVE_INFINITY, "y"); @@ -117,8 +127,12 @@ public class TestLinearSolver { solveAndPrint(solver, new MPVariable[] {x, y}, new MPConstraint[] {c0, c1}); } - static void runBooleanProgrammingExample(MPSolver.OptimizationProblemType problem_type) { - MPSolver solver = new MPSolver("BooleanProgrammingExample", problem_type); + static void runBooleanProgrammingExample(String problem_type) { + logger.info("------ Boolean programming example with " + problem_type + " ------"); + + MPSolver solver = MPSolver.createSolver("BooleanProgrammingExample", problem_type); + if (solver == null) return; + // x and y are continuous non-negative variables. MPVariable x = solver.makeBoolVar("x"); MPVariable y = solver.makeBoolVar("y"); @@ -138,9 +152,7 @@ public class TestLinearSolver { } static void testSameConstraintName() { - MPSolver solver = new MPSolver( - "My_solver_name", - MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("testSameConstraintName", "CBC"); boolean success = true; solver.makeConstraint("my_const_name"); try { @@ -153,8 +165,8 @@ public class TestLinearSolver { } static void testSetHintAndSolverGetters() { - MPSolver solver = new MPSolver("testSetHintAndSolverGetters", - MPSolver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("testSetHintAndSolverGetters", "GLOP"); + // x and y are continuous non-negative variables. MPVariable x = solver.makeIntVar(0.0, Double.POSITIVE_INFINITY, "x"); MPVariable y = solver.makeIntVar(0.0, Double.POSITIVE_INFINITY, "y"); @@ -191,20 +203,17 @@ public class TestLinearSolver { testSameConstraintName(); testSetHintAndSolverGetters(); - MPSolver.OptimizationProblemType problem_types[] = MPSolver.OptimizationProblemType.values(); - for (MPSolver.OptimizationProblemType problem_type : problem_types) { - if (problem_type.name().endsWith("LINEAR_PROGRAMMING")) { - logger.info("------ Linear programming example with " + problem_type + " ------"); - runLinearProgrammingExample(problem_type); - } else if (problem_type.name().endsWith("MIXED_INTEGER_PROGRAMMING")) { - logger.info("------ Mixed Integer programming example with " + problem_type + " ------"); - runMixedIntegerProgrammingExample(problem_type); - } else if (problem_type.name().endsWith("INTEGER_PROGRAMMING")) { - logger.info("------ Boolean programming example with " + problem_type + " ------"); - runBooleanProgrammingExample(problem_type); - } else { - logger.severe("Problem type " + problem_type + " unknow !"); - } - } + runLinearProgrammingExample("GLOP"); + runLinearProgrammingExample("GLPK_LP"); + runLinearProgrammingExample("CLP"); + runLinearProgrammingExample("GUROBI_LP"); + + runMixedIntegerProgrammingExample("GLPK"); + runMixedIntegerProgrammingExample("CBC"); + runMixedIntegerProgrammingExample("SCIP"); + runMixedIntegerProgrammingExample("SAT"); + + runBooleanProgrammingExample("SAT"); + runBooleanProgrammingExample("BOP"); } } diff --git a/makefiles/Makefile.third_party.unix.mk b/makefiles/Makefile.third_party.unix.mk index 011e888bd7..d5e7c086e6 100644 --- a/makefiles/Makefile.third_party.unix.mk +++ b/makefiles/Makefile.third_party.unix.mk @@ -95,9 +95,6 @@ endif ifndef UNIX_GLPK_DIR $(info GLPK: not found) endif -ifndef UNIX_GUROBI_DIR - $(info GUROBI: not found) -endif ifndef UNIX_SCIP_DIR $(info SCIP: not found) else @@ -165,8 +162,6 @@ Makefile.local: makefiles/Makefile.third_party.$(SYSTEM).mk @echo "# Define UNIX_GLPK_DIR to point to a compiled version of GLPK to use it" >> Makefile.local @echo "# e.g. UNIX_GLPK_DIR = /opt/glpk-x.y.z" >> Makefile.local @echo >> Makefile.local - @echo "# Define UNIX_GUROBI_DIR and GUROBI_LIB_VERSION to use Gurobi" >> Makefile.local - @echo >> Makefile.local @echo "# Define UNIX_SCIP_DIR to point to a installed version of SCIP to use it ">> Makefile.local @echo "# e.g. UNIX_SCIP_DIR = /scipoptsuite-6.0.2" >> Makefile.local @echo "# On Mac OS X, compile scip with: " >> Makefile.local @@ -875,11 +870,6 @@ ifdef UNIX_CPLEX_DIR @echo UNIX_CPLEX_DIR = $(UNIX_CPLEX_DIR) @echo CPLEX_INC = $(CPLEX_INC) @echo CPLEX_LNK = $(CPLEX_LNK) -endif -ifdef UNIX_GUROBI_DIR - @echo UNIX_GUROBI_DIR = $(UNIX_GUROBI_DIR) - @echo GUROBI_INC = $(GUROBI_INC) - @echo GUROBI_LNK = $(GUROBI_LNK) endif @echo SWIG_VERSION = $(SWIG_VERSION) @echo diff --git a/makefiles/Makefile.third_party.win.mk b/makefiles/Makefile.third_party.win.mk index b8eec3fbe8..585d6fefc5 100644 --- a/makefiles/Makefile.third_party.win.mk +++ b/makefiles/Makefile.third_party.win.mk @@ -108,9 +108,6 @@ endif ifndef WINDOWS_GLPK_DIR @echo GLPK: not found endif -ifndef WINDOWS_GUROBI_DIR - @echo GUROBI: not found -endif ifndef WINDOWS_SCIP_DIR @echo SCIP: not found else @@ -183,9 +180,6 @@ Makefile.local: makefiles/Makefile.third_party.$(SYSTEM).mk @echo # e.g.: WINDOWS_SCIP_DIR = C:\Progra~1\SCIPOP~1.2 >> Makefile.local @echo # note: You can use: 'dir "%ProgramFiles%\SCIPOp*" /x' to find the shortname >> Makefile.local @echo # >> Makefile.local - @echo # Define WINDOWS_GUROBI_DIR and GUROBI_LIB_VERSION to use Gurobi >> Makefile.local - @echo # e.g.: WINDOWS_GUROBI_DIR = C:\Progra~1\Gurobi >> Makefile.local - @echo # >> Makefile.local @echo ## REQUIRED DEPENDENCIES ## >> Makefile.local @echo # By default they will be automatically built -> nothing to define >> Makefile.local @echo # Define WINDOWS_GFLAGS_DIR to depend on external Gflags library >> Makefile.local @@ -586,11 +580,5 @@ ifdef WINDOWS_CPLEX_DIR @echo CPLEX_INC = $(CPLEX_INC) @echo DYNAMIC_CPLEX_LNK = $(DYNAMIC_CPLEX_LNK) @echo STATIC_CPLEX_LNK = $(STATIC_CPLEX_LNK) -endif -ifdef WINDOWS_GUROBI_DIR - @echo WINDOWS_GUROBI_DIR = $(WINDOWS_GUROBI_DIR) - @echo GUROBI_INC = $(GUROBI_INC) - @echo DYNAMIC_GUROBI_LNK = $(DYNAMIC_GUROBI_LNK) - @echo STATIC_GUROBI_LNK = $(STATIC_GUROBI_LNK) endif @echo off & echo( diff --git a/ortools/base/cleanup.h b/ortools/base/cleanup.h index df0680184a..e00be3273c 100644 --- a/ortools/base/cleanup.h +++ b/ortools/base/cleanup.h @@ -17,6 +17,7 @@ #include #include "absl/base/macros.h" +#include "ortools/base/logging.h" namespace absl { @@ -61,7 +62,7 @@ class Storage { void CancelCallback() { contains_callback_ = false; } - void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS { + void InvokeCallback() { CancelCallback(); std::move(callback_)(); diff --git a/ortools/base/dynamic_library.h b/ortools/base/dynamic_library.h index f300f0e911..83774fc5f6 100644 --- a/ortools/base/dynamic_library.h +++ b/ortools/base/dynamic_library.h @@ -1,4 +1,4 @@ -// Copyright 2010-2020 Google +// Copyright 2010-2018 Google LLC // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18,8 +18,10 @@ #include #include +#include "ortools/base/logging.h" + #if defined(_MSC_VER) -#define WIN32_LEAN_AND_MEAN // disables several conflicting macros +#define WIN32_LEAN_AND_MEAN // disables several conflicting macros #include #elif defined(__GNUC__) #include @@ -28,15 +30,9 @@ #define NAMEOF(x) #x class DynamicLibrary { -public: - explicit DynamicLibrary(const std::string &library_name) - : library_name_(std::string(library_name)) { -#if defined(_MSC_VER) - library_handle_ = static_cast(LoadLibrary(library_name)); -#elif defined(__GNUC__) - library_handle_ = dlopen(library_name.c_str(), RTLD_NOW); -#endif - } + public: + DynamicLibrary() : library_handle_(nullptr) {} + ~DynamicLibrary() { if (library_handle_ == nullptr) { return; @@ -49,16 +45,27 @@ public: #endif } + bool TryToLoad(const std::string& library_name) { + library_name_ = std::string(library_name); +#if defined(_MSC_VER) + library_handle_ = static_cast(LoadLibrary(library_name)); +#elif defined(__GNUC__) + library_handle_ = dlopen(library_name.c_str(), RTLD_NOW); +#endif + return library_handle_ != nullptr; + } + + bool LibraryIsLoaded() const { return library_handle_ != nullptr; } template std::function GetFunction(const char* function_name) { const void* function_address = #if defined(_MSC_VER) - static_cast(GetProcAddress(static_cast(library_handle_), - function_name)); + static_cast(GetProcAddress( + static_cast(library_handle_), function_name)); #else - dlsym(library_handle_, function_name); + dlsym(library_handle_, function_name); #endif CHECK(function_address != nullptr) @@ -86,17 +93,19 @@ public: private: void* library_handle_ = nullptr; - const std::string library_name_; + std::string library_name_; - template struct TypeParser {}; + template + struct TypeParser {}; - template struct TypeParser { - static std::function - CreateFunction(const void *function_address) { + template + struct TypeParser { + static std::function CreateFunction( + const void* function_address) { return std::function( - reinterpret_cast(function_address)); + reinterpret_cast(const_cast(function_address))); } }; }; -#endif +#endif // OR_TOOLS_BASE_DYNAMIC_LIBRARY_H_ diff --git a/ortools/linear_solver/csharp/SolverHelper.cs b/ortools/linear_solver/csharp/SolverHelper.cs index af46970860..85b654b820 100644 --- a/ortools/linear_solver/csharp/SolverHelper.cs +++ b/ortools/linear_solver/csharp/SolverHelper.cs @@ -190,16 +190,6 @@ public partial class Solver { } } - public static Solver CreateSolver(String name, String type) { - Solver.OptimizationProblemType solver_type = - Solver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING; - if (Enum.TryParse(type, true, out solver_type)) { - return new Solver(name, solver_type); - } else { - return null; - } - } - public Constraint Add(LinearConstraint constraint) { return constraint.Extract(this); } diff --git a/ortools/linear_solver/csharp/linear_solver.i b/ortools/linear_solver/csharp/linear_solver.i index 733e96ce81..25c7d9b1ea 100644 --- a/ortools/linear_solver/csharp/linear_solver.i +++ b/ortools/linear_solver/csharp/linear_solver.i @@ -93,6 +93,7 @@ CONVERT_VECTOR(operations_research::MPVariable, MPVariable) %unignore operations_research::MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING; %unignore operations_research::MPSolver::GUROBI_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING; +%unignore operations_research::MPSolver::SetGurobiLibraryPath; %unignore operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING; %unignore operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING; @@ -123,6 +124,7 @@ CONVERT_VECTOR(operations_research::MPVariable, MPVariable) // Expose the MPSolver's basic API, with trivial renames when needed. %unignore operations_research::MPSolver::MPSolver; %unignore operations_research::MPSolver::~MPSolver; +%unignore operations_research::MPSolver::CreateSolver; %unignore operations_research::MPSolver::MakeBoolVar; %unignore operations_research::MPSolver::MakeIntVar; %unignore operations_research::MPSolver::MakeNumVar; diff --git a/ortools/linear_solver/gurobi_environment.cc b/ortools/linear_solver/gurobi_environment.cc index a5823c35f1..28076daa41 100644 --- a/ortools/linear_solver/gurobi_environment.cc +++ b/ortools/linear_solver/gurobi_environment.cc @@ -11,18 +11,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if defined(USE_GUROBI) #include "ortools/linear_solver/gurobi_environment.h" #include #include "absl/status/status.h" #include "absl/strings/match.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "ortools/base/logging.h" +#include "ortools/linear_solver/linear_solver.h" namespace operations_research { -absl::Status LoadGurobiEnvironment(GRBenv** env) { +absl::Status LoadGurobiEnvironment(GRBenv **env) { constexpr int GRB_OK = 0; const char kGurobiEnvErrorMsg[] = "Could not load Gurobi environment. Is gurobi correctly installed and " @@ -34,5 +35,222 @@ absl::Status LoadGurobiEnvironment(GRBenv** env) { } return absl::OkStatus(); } + +std::function + GRBaddrangeconstr = nullptr; +std::function + GRBaddvars = nullptr; +std::function GRBfreeenv = nullptr; +std::function GRBfreemodel = nullptr; +std::function + GRBgetcharattrelement = nullptr; +std::function GRBgetdblattr = nullptr; +std::function + GRBgetdblattrarray = nullptr; +std::function + GRBgetdblattrelement = nullptr; +std::function GRBgetdblparam = nullptr; +std::function GRBgetenv = nullptr; +std::function GRBgeterrormsg = nullptr; +std::function GRBgetintattr = nullptr; +std::function GRBgetintattrelement = + nullptr; +std::function GRBloadenv = nullptr; +std::function + GRBnewmodel = nullptr; +std::function GRBoptimize = nullptr; +std::function GRBreadparams = nullptr; +std::function GRBresetparams = nullptr; +std::function GRBsetcharattrelement = + nullptr; +std::function GRBsetdblattr = nullptr; +std::function GRBsetdblattrelement = + nullptr; +std::function GRBsetdblparam = nullptr; +std::function GRBsetintattr = nullptr; +std::function GRBsetintparam = nullptr; +std::function GRBterminate = nullptr; +std::function GRBupdatemodel = nullptr; +std::function GRBversion = nullptr; +std::function GRBwrite = nullptr; +std::function GRBcbget = + nullptr; +std::function + GRBcbcut = nullptr; +std::function + GRBcblazy = nullptr; +std::function + GRBcbsolution = nullptr; +std::function + GRBaddconstr = nullptr; +std::function + GRBaddgenconstrIndicator = nullptr; +std::function + GRBsetintattrelement = nullptr; +std::function + GRBsetcallbackfunc = nullptr; +std::function + GRBsetparam = nullptr; +std::function + GRBaddsos = nullptr; +std::function + GRBaddqconstr = nullptr; +std::function + GRBaddgenconstrMax = nullptr; +std::function + GRBaddgenconstrMin = nullptr; +std::function + GRBaddgenconstrAbs = nullptr; +std::function + GRBaddgenconstrAnd = nullptr; +std::function + GRBaddgenconstrOr = nullptr; +std::function + GRBaddqpterms = nullptr; + +std::unique_ptr gurobi_dynamic_library; +std::string gurobi_library_path; + +void LoadGurobiFunctions() { + gurobi_dynamic_library->GetFunction(&GRBaddrangeconstr, + NAMEOF(GRBaddrangeconstr)); + gurobi_dynamic_library->GetFunction(&GRBaddvars, NAMEOF(GRBaddvars)); + gurobi_dynamic_library->GetFunction(&GRBfreeenv, NAMEOF(GRBfreeenv)); + gurobi_dynamic_library->GetFunction(&GRBfreemodel, NAMEOF(GRBfreemodel)); + gurobi_dynamic_library->GetFunction(&GRBgetcharattrelement, + NAMEOF(GRBgetcharattrelement)); + gurobi_dynamic_library->GetFunction(&GRBgetdblattr, NAMEOF(GRBgetdblattr)); + gurobi_dynamic_library->GetFunction(&GRBgetdblattrarray, + NAMEOF(GRBgetdblattrarray)); + gurobi_dynamic_library->GetFunction(&GRBgetdblattrelement, + NAMEOF(GRBgetdblattrelement)); + gurobi_dynamic_library->GetFunction(&GRBgetdblparam, NAMEOF(GRBgetdblparam)); + gurobi_dynamic_library->GetFunction(&GRBgetenv, NAMEOF(GRBgetenv)); + gurobi_dynamic_library->GetFunction(&GRBgeterrormsg, NAMEOF(GRBgeterrormsg)); + gurobi_dynamic_library->GetFunction(&GRBgetintattr, NAMEOF(GRBgetintattr)); + gurobi_dynamic_library->GetFunction(&GRBgetintattrelement, + NAMEOF(GRBgetintattrelement)); + gurobi_dynamic_library->GetFunction(&GRBloadenv, NAMEOF(GRBloadenv)); + gurobi_dynamic_library->GetFunction(&GRBnewmodel, NAMEOF(GRBnewmodel)); + gurobi_dynamic_library->GetFunction(&GRBoptimize, NAMEOF(GRBoptimize)); + gurobi_dynamic_library->GetFunction(&GRBreadparams, NAMEOF(GRBreadparams)); + gurobi_dynamic_library->GetFunction(&GRBresetparams, NAMEOF(GRBresetparams)); + gurobi_dynamic_library->GetFunction(&GRBsetcharattrelement, + NAMEOF(GRBsetcharattrelement)); + gurobi_dynamic_library->GetFunction(&GRBsetdblattr, NAMEOF(GRBsetdblattr)); + gurobi_dynamic_library->GetFunction(&GRBsetdblattrelement, + NAMEOF(GRBsetdblattrelement)); + gurobi_dynamic_library->GetFunction(&GRBsetdblparam, NAMEOF(GRBsetdblparam)); + gurobi_dynamic_library->GetFunction(&GRBsetintattr, NAMEOF(GRBsetintattr)); + gurobi_dynamic_library->GetFunction(&GRBsetintparam, NAMEOF(GRBsetintparam)); + gurobi_dynamic_library->GetFunction(&GRBterminate, NAMEOF(GRBterminate)); + gurobi_dynamic_library->GetFunction(&GRBupdatemodel, NAMEOF(GRBupdatemodel)); + gurobi_dynamic_library->GetFunction(&GRBversion, NAMEOF(GRBversion)); + gurobi_dynamic_library->GetFunction(&GRBwrite, NAMEOF(GRBwrite)); + gurobi_dynamic_library->GetFunction(&GRBcbget, NAMEOF(GRBcbget)); + gurobi_dynamic_library->GetFunction(&GRBcbcut, NAMEOF(GRBcbcut)); + gurobi_dynamic_library->GetFunction(&GRBcblazy, NAMEOF(GRBcblazy)); + gurobi_dynamic_library->GetFunction(&GRBcbsolution, NAMEOF(GRBcbsolution)); + gurobi_dynamic_library->GetFunction(&GRBaddconstr, NAMEOF(GRBaddconstr)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrIndicator, + NAMEOF(GRBaddgenconstrIndicator)); + gurobi_dynamic_library->GetFunction(&GRBsetintattrelement, + NAMEOF(GRBsetintattrelement)); + gurobi_dynamic_library->GetFunction(&GRBsetcallbackfunc, + NAMEOF(GRBsetcallbackfunc)); + gurobi_dynamic_library->GetFunction(&GRBsetparam, NAMEOF(GRBsetparam)); + gurobi_dynamic_library->GetFunction(&GRBaddsos, NAMEOF(GRBaddsos)); + gurobi_dynamic_library->GetFunction(&GRBaddqconstr, NAMEOF(GRBaddqconstr)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrMax, + NAMEOF(GRBaddgenconstrMax)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrMin, + NAMEOF(GRBaddgenconstrMin)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrAbs, + NAMEOF(GRBaddgenconstrAbs)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrAnd, + NAMEOF(GRBaddgenconstrAnd)); + gurobi_dynamic_library->GetFunction(&GRBaddgenconstrOr, + NAMEOF(GRBaddgenconstrOr)); + gurobi_dynamic_library->GetFunction(&GRBaddqpterms, NAMEOF(GRBaddqpterms)); +} + +bool LoadSpecificGurobiLibrary(const std::string &full_library_path) { + CHECK(gurobi_dynamic_library.get() != nullptr); + VLOG(1) << "Try to load from " << full_library_path; + return gurobi_dynamic_library->TryToLoad(full_library_path); +} + +bool SearchForGurobiDynamicLibrary() { +#if defined(_MSC_VER) // Windows + if (!gurobi_library_path.empty() && + LoadSpecificGurobiLibrary(gurobi_library_path)) { + return true; + } + if (LoadSpecificGurobiLibrary( + "C:\\Program Files\\gurobi902\\win64\\lib\\gurobi90.dll")) { + return true; + } +#elif defined(__APPLE__) // OS X + if (!gurobi_library_path.empty() && + LoadSpecificGurobiLibrary(gurobi_library_path)) { + return true; + } + if (LoadSpecificGurobiLibrary( + "/Library/gurobi902/mac64/lib/libgurobi90.dylib")) { + return true; + } +#elif defined(__GNUC__) // Linux + if (!gurobi_library_path.empty() && + LoadSpecificGurobiLibrary(gurobi_library_path)) { + return true; + } +#endif + + return false; +} + +bool MPSolver::LoadGurobiSharedLibrary() { + if (gurobi_dynamic_library.get() != nullptr) { + return gurobi_dynamic_library->LibraryIsLoaded(); + } + + gurobi_dynamic_library.reset(new DynamicLibrary()); + + if (SearchForGurobiDynamicLibrary()) { + LoadGurobiFunctions(); + return true; + } + + return false; +} + +void MPSolver::SetGurobiLibraryPath(const std::string &full_library_path) { + gurobi_library_path = full_library_path; +} + +bool MPSolver::GurobiIsCorrectlyInstalled() { + if (!LoadGurobiSharedLibrary()) return false; + GRBenv *env; + if (GRBloadenv(&env, nullptr) != 0 || env == nullptr) return false; + + return true; +} + } // namespace operations_research -#endif // #if defined(USE_GUROBI) diff --git a/ortools/linear_solver/gurobi_environment.h b/ortools/linear_solver/gurobi_environment.h index a5e689e83a..aa1de1175b 100644 --- a/ortools/linear_solver/gurobi_environment.h +++ b/ortools/linear_solver/gurobi_environment.h @@ -11,20 +11,644 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if defined(USE_GUROBI) #ifndef OR_TOOLS_LINEAR_SOLVER_GUROBI_ENVIRONMENT_H_ #define OR_TOOLS_LINEAR_SOLVER_GUROBI_ENVIRONMENT_H_ #include "absl/status/status.h" #include "ortools/base/commandlineflags.h" +#include "ortools/base/dynamic_library.h" +#include "ortools/base/logging.h" extern "C" { -#include "gurobi_c.h" +typedef struct _GRBmodel GRBmodel; +typedef struct _GRBenv GRBenv; } namespace operations_research { absl::Status LoadGurobiEnvironment(GRBenv** env); -} + +#define CB_ARGS GRBmodel *model, void *cbdata, int where, void *usrdata +extern std::function + GRBaddrangeconstr; +extern std::function + GRBaddvars; +extern std::function GRBfreeenv; +extern std::function GRBfreemodel; +extern std::function + GRBgetcharattrelement; +extern std::function GRBgetdblattr; +extern std::function + GRBgetdblattrarray; +extern std::function + GRBgetdblattrelement; +extern std::function GRBgetdblparam; +extern std::function GRBgetenv; +extern std::function GRBgeterrormsg; +extern std::function GRBgetintattr; +extern std::function + GRBgetintattrelement; +extern std::function GRBloadenv; +extern std::function + GRBnewmodel; +extern std::function GRBoptimize; +extern std::function GRBreadparams; +extern std::function GRBresetparams; +extern std::function + GRBsetcharattrelement; +extern std::function GRBsetdblattr; +extern std::function + GRBsetdblattrelement; +extern std::function GRBsetdblparam; +extern std::function GRBsetintattr; +extern std::function GRBsetintparam; +extern std::function GRBterminate; +extern std::function GRBupdatemodel; +extern std::function GRBversion; +extern std::function GRBwrite; +extern std::function + GRBcbget; +extern std::function + GRBcbcut; +extern std::function + GRBcblazy; +extern std::function + GRBcbsolution; +extern std::function + GRBaddconstr; +extern std::function + GRBaddgenconstrIndicator; +extern std::function + GRBsetintattrelement; +extern std::function + GRBsetcallbackfunc; +extern std::function + GRBsetparam; +extern std::function + GRBaddsos; + +extern std::function + GRBaddqconstr; +extern std::function + GRBaddgenconstrMax; +extern std::function + GRBaddgenconstrMin; +extern std::function + GRBaddgenconstrAbs; +extern std::function + GRBaddgenconstrAnd; +extern std::function + GRBaddgenconstrOr; +extern std::function + GRBaddqpterms; + +#define GRB_VERSION_MAJOR 9 +#define GRB_VERSION_MINOR 0 +#define GRB_VERSION_TECHNICAL 2 +#define GRB_ERROR_OUT_OF_MEMORY 10001 +#define GRB_ERROR_NULL_ARGUMENT 10002 +#define GRB_ERROR_INVALID_ARGUMENT 10003 +#define GRB_ERROR_UNKNOWN_ATTRIBUTE 10004 +#define GRB_ERROR_DATA_NOT_AVAILABLE 10005 +#define GRB_ERROR_INDEX_OUT_OF_RANGE 10006 +#define GRB_ERROR_UNKNOWN_PARAMETER 10007 +#define GRB_ERROR_VALUE_OUT_OF_RANGE 10008 +#define GRB_ERROR_NO_LICENSE 10009 +#define GRB_ERROR_SIZE_LIMIT_EXCEEDED 10010 +#define GRB_ERROR_CALLBACK 10011 +#define GRB_ERROR_FILE_READ 10012 +#define GRB_ERROR_FILE_WRITE 10013 +#define GRB_ERROR_NUMERIC 10014 +#define GRB_ERROR_IIS_NOT_INFEASIBLE 10015 +#define GRB_ERROR_NOT_FOR_MIP 10016 +#define GRB_ERROR_OPTIMIZATION_IN_PROGRESS 10017 +#define GRB_ERROR_DUPLICATES 10018 +#define GRB_ERROR_NODEFILE 10019 +#define GRB_ERROR_Q_NOT_PSD 10020 +#define GRB_ERROR_QCP_EQUALITY_CONSTRAINT 10021 +#define GRB_ERROR_NETWORK 10022 +#define GRB_ERROR_JOB_REJECTED 10023 +#define GRB_ERROR_NOT_SUPPORTED 10024 +#define GRB_ERROR_EXCEED_2B_NONZEROS 10025 +#define GRB_ERROR_INVALID_PIECEWISE_OBJ 10026 +#define GRB_ERROR_UPDATEMODE_CHANGE 10027 +#define GRB_ERROR_CLOUD 10028 +#define GRB_ERROR_MODEL_MODIFICATION 10029 +#define GRB_ERROR_CSWORKER 10030 +#define GRB_ERROR_TUNE_MODEL_TYPES 10031 +#define GRB_ERROR_SECURITY 10032 +#define GRB_LESS_EQUAL '<' +#define GRB_GREATER_EQUAL '>' +#define GRB_EQUAL '=' +#define GRB_CONTINUOUS 'C' +#define GRB_BINARY 'B' +#define GRB_INTEGER 'I' +#define GRB_SEMICONT 'S' +#define GRB_SEMIINT 'N' +#define GRB_MINIMIZE 1 +#define GRB_MAXIMIZE -1 +#define GRB_SOS_TYPE1 1 +#define GRB_SOS_TYPE2 2 +#define GRB_INFINITY 1e100 +#define GRB_UNDEFINED 1e101 +#define GRB_MAXINT 2000000000 +#define GRB_MAX_NAMELEN 255 +#define GRB_MAX_STRLEN 512 +#define GRB_MAX_TAGLEN 10240 +#define GRB_MAX_CONCURRENT 64 +#define GRB_INT_ATTR_NUMCONSTRS "NumConstrs" /* # of constraints */ +#define GRB_INT_ATTR_NUMVARS "NumVars" /* # of vars */ +#define GRB_INT_ATTR_NUMSOS "NumSOS" /* # of sos constraints */ +#define GRB_INT_ATTR_NUMQCONSTRS "NumQConstrs" /* # of quadratic constraints */ +#define GRB_INT_ATTR_NUMGENCONSTRS "NumGenConstrs" /* # of general constraints */ +#define GRB_INT_ATTR_NUMNZS "NumNZs" /* # of nz in A */ +#define GRB_DBL_ATTR_DNUMNZS "DNumNZs" /* # of nz in A */ +#define GRB_INT_ATTR_NUMQNZS "NumQNZs" /* # of nz in Q */ +#define GRB_INT_ATTR_NUMQCNZS "NumQCNZs" /* # of nz in q constraints */ +#define GRB_INT_ATTR_NUMINTVARS "NumIntVars" /* # of integer vars */ +#define GRB_INT_ATTR_NUMBINVARS "NumBinVars" /* # of binary vars */ +#define GRB_INT_ATTR_NUMPWLOBJVARS "NumPWLObjVars" /* # of variables with PWL obj. */ +#define GRB_STR_ATTR_MODELNAME "ModelName" /* model name */ +#define GRB_INT_ATTR_MODELSENSE "ModelSense" /* 1=min, -1=max */ +#define GRB_DBL_ATTR_OBJCON "ObjCon" /* Objective constant */ +#define GRB_INT_ATTR_IS_MIP "IsMIP" /* Is model a MIP? */ +#define GRB_INT_ATTR_IS_QP "IsQP" /* Model has quadratic obj? */ +#define GRB_INT_ATTR_IS_QCP "IsQCP" /* Model has quadratic constr? */ +#define GRB_INT_ATTR_IS_MULTIOBJ "IsMultiObj" /* Model has multiple objectives? */ +#define GRB_STR_ATTR_SERVER "Server" /* Name of Compute Server */ +#define GRB_STR_ATTR_JOBID "JobID" /* Compute Server job ID */ +#define GRB_INT_ATTR_LICENSE_EXPIRATION "LicenseExpiration" /* License expiration date */ +#define GRB_INT_ATTR_NUMTAGGED "NumTagged" /* number of tagged elements in model */ +#define GRB_INT_ATTR_BATCHERRORCODE "BatchErrorCode" +#define GRB_STR_ATTR_BATCHERRORMESSAGE "BatchErrorMessage" +#define GRB_STR_ATTR_BATCHID "BatchID" +#define GRB_INT_ATTR_BATCHSTATUS "BatchStatus" +#define GRB_DBL_ATTR_LB "LB" /* Lower bound */ +#define GRB_DBL_ATTR_UB "UB" /* Upper bound */ +#define GRB_DBL_ATTR_OBJ "Obj" /* Objective coeff */ +#define GRB_CHAR_ATTR_VTYPE "VType" /* Integrality type */ +#define GRB_DBL_ATTR_START "Start" /* MIP start value */ +#define GRB_DBL_ATTR_PSTART "PStart" /* LP primal solution warm start */ +#define GRB_INT_ATTR_BRANCHPRIORITY "BranchPriority" /* MIP branch priority */ +#define GRB_STR_ATTR_VARNAME "VarName" /* Variable name */ +#define GRB_INT_ATTR_PWLOBJCVX "PWLObjCvx" /* Convexity of variable PWL obj */ +#define GRB_DBL_ATTR_VARHINTVAL "VarHintVal" +#define GRB_INT_ATTR_VARHINTPRI "VarHintPri" +#define GRB_INT_ATTR_PARTITION "Partition" +#define GRB_STR_ATTR_VTAG "VTag" /* variable tags */ +#define GRB_STR_ATTR_CTAG "CTag" /* linear constraint tags */ +#define GRB_DBL_ATTR_RHS "RHS" /* RHS */ +#define GRB_DBL_ATTR_DSTART "DStart" /* LP dual solution warm start */ +#define GRB_CHAR_ATTR_SENSE "Sense" /* Sense ('<', '>', or '=') */ +#define GRB_STR_ATTR_CONSTRNAME "ConstrName" /* Constraint name */ +#define GRB_INT_ATTR_LAZY "Lazy" /* Lazy constraint? */ +#define GRB_STR_ATTR_QCTAG "QCTag" /* quadratic constraint tags */ +#define GRB_DBL_ATTR_QCRHS "QCRHS" /* QC RHS */ +#define GRB_CHAR_ATTR_QCSENSE "QCSense" /* QC sense ('<', '>', or '=') */ +#define GRB_STR_ATTR_QCNAME "QCName" /* QC name */ +#define GRB_INT_ATTR_GENCONSTRTYPE "GenConstrType" /* Type of general constraint */ +#define GRB_STR_ATTR_GENCONSTRNAME "GenConstrName" /* Name of general constraint */ +#define GRB_INT_ATTR_FUNCPIECES "FuncPieces" /* An option for PWL translation */ +#define GRB_DBL_ATTR_FUNCPIECEERROR "FuncPieceError" /* An option for PWL translation */ +#define GRB_DBL_ATTR_FUNCPIECELENGTH "FuncPieceLength" /* An option for PWL translation */ +#define GRB_DBL_ATTR_FUNCPIECERATIO "FuncPieceRatio" /* An option for PWL translation */ +#define GRB_DBL_ATTR_MAX_COEFF "MaxCoeff" /* Max (abs) nz coeff in A */ +#define GRB_DBL_ATTR_MIN_COEFF "MinCoeff" /* Min (abs) nz coeff in A */ +#define GRB_DBL_ATTR_MAX_BOUND "MaxBound" /* Max (abs) finite var bd */ +#define GRB_DBL_ATTR_MIN_BOUND "MinBound" /* Min (abs) var bd */ +#define GRB_DBL_ATTR_MAX_OBJ_COEFF "MaxObjCoeff" /* Max (abs) obj coeff */ +#define GRB_DBL_ATTR_MIN_OBJ_COEFF "MinObjCoeff" /* Min (abs) obj coeff */ +#define GRB_DBL_ATTR_MAX_RHS "MaxRHS" /* Max (abs) rhs coeff */ +#define GRB_DBL_ATTR_MIN_RHS "MinRHS" /* Min (abs) rhs coeff */ +#define GRB_DBL_ATTR_MAX_QCCOEFF "MaxQCCoeff" /* Max (abs) nz coeff in Q */ +#define GRB_DBL_ATTR_MIN_QCCOEFF "MinQCCoeff" /* Min (abs) nz coeff in Q */ +#define GRB_DBL_ATTR_MAX_QOBJ_COEFF "MaxQObjCoeff" /* Max (abs) obj coeff of quadratic part */ +#define GRB_DBL_ATTR_MIN_QOBJ_COEFF "MinQObjCoeff" /* Min (abs) obj coeff of quadratic part */ +#define GRB_DBL_ATTR_MAX_QCLCOEFF "MaxQCLCoeff" /* Max (abs) nz coeff in linear part of Q */ +#define GRB_DBL_ATTR_MIN_QCLCOEFF "MinQCLCoeff" /* Min (abs) nz coeff in linear part of Q */ +#define GRB_DBL_ATTR_MAX_QCRHS "MaxQCRHS" /* Max (abs) rhs of Q */ +#define GRB_DBL_ATTR_MIN_QCRHS "MinQCRHS" /* Min (abs) rhs of Q */ +#define GRB_DBL_ATTR_RUNTIME "Runtime" /* Run time for optimization */ +#define GRB_INT_ATTR_STATUS "Status" /* Optimization status */ +#define GRB_DBL_ATTR_OBJVAL "ObjVal" /* Solution objective */ +#define GRB_DBL_ATTR_OBJBOUND "ObjBound" /* Best bound on solution */ +#define GRB_DBL_ATTR_OBJBOUNDC "ObjBoundC" /* Continuous bound */ +#define GRB_DBL_ATTR_POOLOBJBOUND "PoolObjBound" /* Best bound on pool solution */ +#define GRB_DBL_ATTR_POOLOBJVAL "PoolObjVal" /* Solution objective for solutionnumber */ +#define GRB_DBL_ATTR_MIPGAP "MIPGap" /* MIP optimality gap */ +#define GRB_INT_ATTR_SOLCOUNT "SolCount" /* # of solutions found */ +#define GRB_DBL_ATTR_ITERCOUNT "IterCount" /* Iters performed (simplex) */ +#define GRB_INT_ATTR_BARITERCOUNT "BarIterCount" /* Iters performed (barrier) */ +#define GRB_DBL_ATTR_NODECOUNT "NodeCount" /* Nodes explored (B&C) */ +#define GRB_DBL_ATTR_OPENNODECOUNT "OpenNodeCount" /* Unexplored nodes (B&C) */ +#define GRB_INT_ATTR_HASDUALNORM "HasDualNorm" /* 0, no basis, */ +#define GRB_DBL_ATTR_X "X" /* Solution value */ +#define GRB_DBL_ATTR_XN "Xn" /* Alternate MIP solution */ +#define GRB_DBL_ATTR_BARX "BarX" /* Best barrier iterate */ +#define GRB_DBL_ATTR_RC "RC" /* Reduced costs */ +#define GRB_DBL_ATTR_VDUALNORM "VDualNorm" /* Dual norm square */ +#define GRB_INT_ATTR_VBASIS "VBasis" /* Variable basis status */ +#define GRB_DBL_ATTR_PI "Pi" /* Dual value */ +#define GRB_DBL_ATTR_QCPI "QCPi" /* Dual value for QC */ +#define GRB_DBL_ATTR_SLACK "Slack" /* Constraint slack */ +#define GRB_DBL_ATTR_QCSLACK "QCSlack" /* QC Constraint slack */ +#define GRB_DBL_ATTR_CDUALNORM "CDualNorm" /* Dual norm square */ +#define GRB_INT_ATTR_CBASIS "CBasis" /* Constraint basis status */ +#define GRB_DBL_ATTR_BOUND_VIO "BoundVio" +#define GRB_DBL_ATTR_BOUND_SVIO "BoundSVio" +#define GRB_INT_ATTR_BOUND_VIO_INDEX "BoundVioIndex" +#define GRB_INT_ATTR_BOUND_SVIO_INDEX "BoundSVioIndex" +#define GRB_DBL_ATTR_BOUND_VIO_SUM "BoundVioSum" +#define GRB_DBL_ATTR_BOUND_SVIO_SUM "BoundSVioSum" +#define GRB_DBL_ATTR_CONSTR_VIO "ConstrVio" +#define GRB_DBL_ATTR_CONSTR_SVIO "ConstrSVio" +#define GRB_INT_ATTR_CONSTR_VIO_INDEX "ConstrVioIndex" +#define GRB_INT_ATTR_CONSTR_SVIO_INDEX "ConstrSVioIndex" +#define GRB_DBL_ATTR_CONSTR_VIO_SUM "ConstrVioSum" +#define GRB_DBL_ATTR_CONSTR_SVIO_SUM "ConstrSVioSum" +#define GRB_DBL_ATTR_CONSTR_RESIDUAL "ConstrResidual" +#define GRB_DBL_ATTR_CONSTR_SRESIDUAL "ConstrSResidual" +#define GRB_INT_ATTR_CONSTR_RESIDUAL_INDEX "ConstrResidualIndex" +#define GRB_INT_ATTR_CONSTR_SRESIDUAL_INDEX "ConstrSResidualIndex" +#define GRB_DBL_ATTR_CONSTR_RESIDUAL_SUM "ConstrResidualSum" +#define GRB_DBL_ATTR_CONSTR_SRESIDUAL_SUM "ConstrSResidualSum" +#define GRB_DBL_ATTR_DUAL_VIO "DualVio" +#define GRB_DBL_ATTR_DUAL_SVIO "DualSVio" +#define GRB_INT_ATTR_DUAL_VIO_INDEX "DualVioIndex" +#define GRB_INT_ATTR_DUAL_SVIO_INDEX "DualSVioIndex" +#define GRB_DBL_ATTR_DUAL_VIO_SUM "DualVioSum" +#define GRB_DBL_ATTR_DUAL_SVIO_SUM "DualSVioSum" +#define GRB_DBL_ATTR_DUAL_RESIDUAL "DualResidual" +#define GRB_DBL_ATTR_DUAL_SRESIDUAL "DualSResidual" +#define GRB_INT_ATTR_DUAL_RESIDUAL_INDEX "DualResidualIndex" +#define GRB_INT_ATTR_DUAL_SRESIDUAL_INDEX "DualSResidualIndex" +#define GRB_DBL_ATTR_DUAL_RESIDUAL_SUM "DualResidualSum" +#define GRB_DBL_ATTR_DUAL_SRESIDUAL_SUM "DualSResidualSum" +#define GRB_DBL_ATTR_INT_VIO "IntVio" +#define GRB_INT_ATTR_INT_VIO_INDEX "IntVioIndex" +#define GRB_DBL_ATTR_INT_VIO_SUM "IntVioSum" +#define GRB_DBL_ATTR_COMPL_VIO "ComplVio" +#define GRB_INT_ATTR_COMPL_VIO_INDEX "ComplVioIndex" +#define GRB_DBL_ATTR_COMPL_VIO_SUM "ComplVioSum" +#define GRB_DBL_ATTR_KAPPA "Kappa" +#define GRB_DBL_ATTR_KAPPA_EXACT "KappaExact" +#define GRB_DBL_ATTR_N2KAPPA "N2Kappa" +#define GRB_DBL_ATTR_SA_OBJLOW "SAObjLow" +#define GRB_DBL_ATTR_SA_OBJUP "SAObjUp" +#define GRB_DBL_ATTR_SA_LBLOW "SALBLow" +#define GRB_DBL_ATTR_SA_LBUP "SALBUp" +#define GRB_DBL_ATTR_SA_UBLOW "SAUBLow" +#define GRB_DBL_ATTR_SA_UBUP "SAUBUp" +#define GRB_DBL_ATTR_SA_RHSLOW "SARHSLow" +#define GRB_DBL_ATTR_SA_RHSUP "SARHSUp" +#define GRB_INT_ATTR_IIS_MINIMAL "IISMinimal" /* Boolean: Is IIS Minimal? */ +#define GRB_INT_ATTR_IIS_LB "IISLB" /* Boolean: Is var LB in IIS? */ +#define GRB_INT_ATTR_IIS_UB "IISUB" /* Boolean: Is var UB in IIS? */ +#define GRB_INT_ATTR_IIS_CONSTR "IISConstr" /* Boolean: Is constr in IIS? */ +#define GRB_INT_ATTR_IIS_SOS "IISSOS" /* Boolean: Is SOS in IIS? */ +#define GRB_INT_ATTR_IIS_QCONSTR "IISQConstr" /* Boolean: Is QConstr in IIS? */ +#define GRB_INT_ATTR_IIS_GENCONSTR "IISGenConstr" /* Boolean: Is general constr in IIS? */ +#define GRB_INT_ATTR_TUNE_RESULTCOUNT "TuneResultCount" +#define GRB_DBL_ATTR_FARKASDUAL "FarkasDual" +#define GRB_DBL_ATTR_FARKASPROOF "FarkasProof" +#define GRB_DBL_ATTR_UNBDRAY "UnbdRay" +#define GRB_INT_ATTR_INFEASVAR "InfeasVar" +#define GRB_INT_ATTR_UNBDVAR "UnbdVar" +#define GRB_INT_ATTR_VARPRESTAT "VarPreStat" +#define GRB_DBL_ATTR_PREFIXVAL "PreFixVal" +#define GRB_DBL_ATTR_OBJN "ObjN" /* ith objective */ +#define GRB_DBL_ATTR_OBJNVAL "ObjNVal" /* Solution objective for Multi-objectives */ +#define GRB_DBL_ATTR_OBJNCON "ObjNCon" /* constant term */ +#define GRB_DBL_ATTR_OBJNWEIGHT "ObjNWeight" /* weight */ +#define GRB_INT_ATTR_OBJNPRIORITY "ObjNPriority" /* priority */ +#define GRB_DBL_ATTR_OBJNRELTOL "ObjNRelTol" /* relative tolerance */ +#define GRB_DBL_ATTR_OBJNABSTOL "ObjNAbsTol" /* absolute tolerance */ +#define GRB_STR_ATTR_OBJNNAME "ObjNName" /* name */ +#define GRB_DBL_ATTR_SCENNLB "ScenNLB" /* lower bound in scenario i */ +#define GRB_DBL_ATTR_SCENNUB "ScenNUB" /* upper bound in scenario i */ +#define GRB_DBL_ATTR_SCENNOBJ "ScenNObj" /* objective in scenario i */ +#define GRB_DBL_ATTR_SCENNRHS "ScenNRHS" /* right hand side in scenario i */ +#define GRB_STR_ATTR_SCENNNAME "ScenNName" /* name of scenario i */ +#define GRB_DBL_ATTR_SCENNX "ScenNX" /* solution value in scenario i */ +#define GRB_DBL_ATTR_SCENNOBJBOUND "ScenNObjBound" /* objective bound for scenario i */ +#define GRB_DBL_ATTR_SCENNOBJVAL "ScenNObjVal" /* objective value for scenario i */ +#define GRB_INT_ATTR_NUMOBJ "NumObj" /* number of objectives */ +#define GRB_INT_ATTR_NUMSCENARIOS "NumScenarios" /* number of scenarios */ +#define GRB_INT_ATTR_NUMSTART "NumStart" /* number of MIP starts */ +#define GRB_DBL_ATTR_Xn "Xn" +#define GRB_GENCONSTR_MAX 0 +#define GRB_GENCONSTR_MIN 1 +#define GRB_GENCONSTR_ABS 2 +#define GRB_GENCONSTR_AND 3 +#define GRB_GENCONSTR_OR 4 +#define GRB_GENCONSTR_INDICATOR 5 +#define GRB_GENCONSTR_PWL 6 +#define GRB_GENCONSTR_POLY 7 +#define GRB_GENCONSTR_EXP 8 +#define GRB_GENCONSTR_EXPA 9 +#define GRB_GENCONSTR_LOG 10 +#define GRB_GENCONSTR_LOGA 11 +#define GRB_GENCONSTR_POW 12 +#define GRB_GENCONSTR_SIN 13 +#define GRB_GENCONSTR_COS 14 +#define GRB_GENCONSTR_TAN 15 +#define GRB_CB_POLLING 0 +#define GRB_CB_PRESOLVE 1 +#define GRB_CB_SIMPLEX 2 +#define GRB_CB_MIP 3 +#define GRB_CB_MIPSOL 4 +#define GRB_CB_MIPNODE 5 +#define GRB_CB_MESSAGE 6 +#define GRB_CB_BARRIER 7 +#define GRB_CB_MULTIOBJ 8 +#define GRB_CB_PRE_COLDEL 1000 +#define GRB_CB_PRE_ROWDEL 1001 +#define GRB_CB_PRE_SENCHG 1002 +#define GRB_CB_PRE_BNDCHG 1003 +#define GRB_CB_PRE_COECHG 1004 +#define GRB_CB_SPX_ITRCNT 2000 +#define GRB_CB_SPX_OBJVAL 2001 +#define GRB_CB_SPX_PRIMINF 2002 +#define GRB_CB_SPX_DUALINF 2003 +#define GRB_CB_SPX_ISPERT 2004 +#define GRB_CB_MIP_OBJBST 3000 +#define GRB_CB_MIP_OBJBND 3001 +#define GRB_CB_MIP_NODCNT 3002 +#define GRB_CB_MIP_SOLCNT 3003 +#define GRB_CB_MIP_CUTCNT 3004 +#define GRB_CB_MIP_NODLFT 3005 +#define GRB_CB_MIP_ITRCNT 3006 +#define GRB_CB_MIP_OBJBNDC 3007 +#define GRB_CB_MIPSOL_SOL 4001 +#define GRB_CB_MIPSOL_OBJ 4002 +#define GRB_CB_MIPSOL_OBJBST 4003 +#define GRB_CB_MIPSOL_OBJBND 4004 +#define GRB_CB_MIPSOL_NODCNT 4005 +#define GRB_CB_MIPSOL_SOLCNT 4006 +#define GRB_CB_MIPSOL_OBJBNDC 4007 +#define GRB_CB_MIPNODE_STATUS 5001 +#define GRB_CB_MIPNODE_REL 5002 +#define GRB_CB_MIPNODE_OBJBST 5003 +#define GRB_CB_MIPNODE_OBJBND 5004 +#define GRB_CB_MIPNODE_NODCNT 5005 +#define GRB_CB_MIPNODE_SOLCNT 5006 +#define GRB_CB_MIPNODE_BRVAR 5007 +#define GRB_CB_MIPNODE_OBJBNDC 5008 +#define GRB_CB_MSG_STRING 6001 +#define GRB_CB_RUNTIME 6002 +#define GRB_CB_BARRIER_ITRCNT 7001 +#define GRB_CB_BARRIER_PRIMOBJ 7002 +#define GRB_CB_BARRIER_DUALOBJ 7003 +#define GRB_CB_BARRIER_PRIMINF 7004 +#define GRB_CB_BARRIER_DUALINF 7005 +#define GRB_CB_BARRIER_COMPL 7006 +#define GRB_CB_MULTIOBJ_OBJCNT 8001 +#define GRB_CB_MULTIOBJ_SOLCNT 8002 +#define GRB_CB_MULTIOBJ_SOL 8003 +#define GRB_FEASRELAX_LINEAR 0 +#define GRB_FEASRELAX_QUADRATIC 1 +#define GRB_FEASRELAX_CARDINALITY 2 +#define GRB_LOADED 1 +#define GRB_OPTIMAL 2 +#define GRB_INFEASIBLE 3 +#define GRB_INF_OR_UNBD 4 +#define GRB_UNBOUNDED 5 +#define GRB_CUTOFF 6 +#define GRB_ITERATION_LIMIT 7 +#define GRB_NODE_LIMIT 8 +#define GRB_TIME_LIMIT 9 +#define GRB_SOLUTION_LIMIT 10 +#define GRB_INTERRUPTED 11 +#define GRB_NUMERIC 12 +#define GRB_SUBOPTIMAL 13 +#define GRB_INPROGRESS 14 +#define GRB_USER_OBJ_LIMIT 15 +#define GRB_BASIC 0 +#define GRB_NONBASIC_LOWER -1 +#define GRB_NONBASIC_UPPER -2 +#define GRB_SUPERBASIC -3 +#define GRB_INT_PAR_BARITERLIMIT "BarIterLimit" +#define GRB_DBL_PAR_CUTOFF "Cutoff" +#define GRB_DBL_PAR_ITERATIONLIMIT "IterationLimit" +#define GRB_DBL_PAR_NODELIMIT "NodeLimit" +#define GRB_INT_PAR_SOLUTIONLIMIT "SolutionLimit" +#define GRB_DBL_PAR_TIMELIMIT "TimeLimit" +#define GRB_DBL_PAR_BESTOBJSTOP "BestObjStop" +#define GRB_DBL_PAR_BESTBDSTOP "BestBdStop" +#define GRB_DBL_PAR_FEASIBILITYTOL "FeasibilityTol" +#define GRB_DBL_PAR_INTFEASTOL "IntFeasTol" +#define GRB_DBL_PAR_MARKOWITZTOL "MarkowitzTol" +#define GRB_DBL_PAR_MIPGAP "MIPGap" +#define GRB_DBL_PAR_MIPGAPABS "MIPGapAbs" +#define GRB_DBL_PAR_OPTIMALITYTOL "OptimalityTol" +#define GRB_DBL_PAR_PSDTOL "PSDTol" +#define GRB_INT_PAR_METHOD "Method" +#define GRB_DBL_PAR_PERTURBVALUE "PerturbValue" +#define GRB_DBL_PAR_OBJSCALE "ObjScale" +#define GRB_INT_PAR_SCALEFLAG "ScaleFlag" +#define GRB_INT_PAR_SIMPLEXPRICING "SimplexPricing" +#define GRB_INT_PAR_QUAD "Quad" +#define GRB_INT_PAR_NORMADJUST "NormAdjust" +#define GRB_INT_PAR_SIFTING "Sifting" +#define GRB_INT_PAR_SIFTMETHOD "SiftMethod" +#define GRB_DBL_PAR_BARCONVTOL "BarConvTol" +#define GRB_INT_PAR_BARCORRECTORS "BarCorrectors" +#define GRB_INT_PAR_BARHOMOGENEOUS "BarHomogeneous" +#define GRB_INT_PAR_BARORDER "BarOrder" +#define GRB_DBL_PAR_BARQCPCONVTOL "BarQCPConvTol" +#define GRB_INT_PAR_CROSSOVER "Crossover" +#define GRB_INT_PAR_CROSSOVERBASIS "CrossoverBasis" +#define GRB_INT_PAR_BRANCHDIR "BranchDir" +#define GRB_INT_PAR_DEGENMOVES "DegenMoves" +#define GRB_INT_PAR_DISCONNECTED "Disconnected" +#define GRB_DBL_PAR_HEURISTICS "Heuristics" +#define GRB_DBL_PAR_IMPROVESTARTGAP "ImproveStartGap" +#define GRB_DBL_PAR_IMPROVESTARTTIME "ImproveStartTime" +#define GRB_DBL_PAR_IMPROVESTARTNODES "ImproveStartNodes" +#define GRB_INT_PAR_MINRELNODES "MinRelNodes" +#define GRB_INT_PAR_MIPFOCUS "MIPFocus" +#define GRB_STR_PAR_NODEFILEDIR "NodefileDir" +#define GRB_DBL_PAR_NODEFILESTART "NodefileStart" +#define GRB_INT_PAR_NODEMETHOD "NodeMethod" +#define GRB_INT_PAR_NORELHEURISTIC "NoRelHeuristic" +#define GRB_INT_PAR_PUMPPASSES "PumpPasses" +#define GRB_INT_PAR_RINS "RINS" +#define GRB_STR_PAR_SOLFILES "SolFiles" +#define GRB_INT_PAR_STARTNODELIMIT "StartNodeLimit" +#define GRB_INT_PAR_SUBMIPNODES "SubMIPNodes" +#define GRB_INT_PAR_SYMMETRY "Symmetry" +#define GRB_INT_PAR_VARBRANCH "VarBranch" +#define GRB_INT_PAR_SOLUTIONNUMBER "SolutionNumber" +#define GRB_INT_PAR_ZEROOBJNODES "ZeroObjNodes" +#define GRB_INT_PAR_CUTS "Cuts" +#define GRB_INT_PAR_CLIQUECUTS "CliqueCuts" +#define GRB_INT_PAR_COVERCUTS "CoverCuts" +#define GRB_INT_PAR_FLOWCOVERCUTS "FlowCoverCuts" +#define GRB_INT_PAR_FLOWPATHCUTS "FlowPathCuts" +#define GRB_INT_PAR_GUBCOVERCUTS "GUBCoverCuts" +#define GRB_INT_PAR_IMPLIEDCUTS "ImpliedCuts" +#define GRB_INT_PAR_PROJIMPLIEDCUTS "ProjImpliedCuts" +#define GRB_INT_PAR_MIPSEPCUTS "MIPSepCuts" +#define GRB_INT_PAR_MIRCUTS "MIRCuts" +#define GRB_INT_PAR_STRONGCGCUTS "StrongCGCuts" +#define GRB_INT_PAR_MODKCUTS "ModKCuts" +#define GRB_INT_PAR_ZEROHALFCUTS "ZeroHalfCuts" +#define GRB_INT_PAR_NETWORKCUTS "NetworkCuts" +#define GRB_INT_PAR_SUBMIPCUTS "SubMIPCuts" +#define GRB_INT_PAR_INFPROOFCUTS "InfProofCuts" +#define GRB_INT_PAR_RLTCUTS "RLTCuts" +#define GRB_INT_PAR_RELAXLIFTCUTS "RelaxLiftCuts" +#define GRB_INT_PAR_BQPCUTS "BQPCuts" +#define GRB_INT_PAR_CUTAGGPASSES "CutAggPasses" +#define GRB_INT_PAR_CUTPASSES "CutPasses" +#define GRB_INT_PAR_GOMORYPASSES "GomoryPasses" +#define GRB_STR_PAR_WORKERPOOL "WorkerPool" +#define GRB_STR_PAR_WORKERPASSWORD "WorkerPassword" +#define GRB_STR_PAR_COMPUTESERVER "ComputeServer" +#define GRB_STR_PAR_TOKENSERVER "TokenServer" +#define GRB_STR_PAR_SERVERPASSWORD "ServerPassword" +#define GRB_INT_PAR_SERVERTIMEOUT "ServerTimeout" +#define GRB_STR_PAR_CSROUTER "CSRouter" +#define GRB_STR_PAR_CSGROUP "CSGroup" +#define GRB_DBL_PAR_CSQUEUETIMEOUT "CSQueueTimeout" +#define GRB_INT_PAR_CSPRIORITY "CSPriority" +#define GRB_INT_PAR_CSIDLETIMEOUT "CSIdleTimeout" +#define GRB_INT_PAR_CSTLSINSECURE "CSTLSInsecure" +#define GRB_INT_PAR_TSPORT "TSPort" +#define GRB_STR_PAR_CLOUDACCESSID "CloudAccessID" +#define GRB_STR_PAR_CLOUDSECRETKEY "CloudSecretKey" +#define GRB_STR_PAR_CLOUDPOOL "CloudPool" +#define GRB_STR_PAR_CLOUDHOST "CloudHost" +#define GRB_STR_PAR_CSMANAGER "CSManager" +#define GRB_STR_PAR_CSAUTHTOKEN "CSAuthToken" +#define GRB_STR_PAR_CSAPIACCESSID "CSAPIAccessID" +#define GRB_STR_PAR_CSAPISECRET "CSAPISecret" +#define GRB_INT_PAR_CSBATCHMODE "CSBatchMode" +#define GRB_STR_PAR_USERNAME "Username" +#define GRB_STR_PAR_CSAPPNAME "CSAppName" +#define GRB_INT_PAR_CSCLIENTLOG "CSClientLog" +#define GRB_INT_PAR_AGGREGATE "Aggregate" +#define GRB_INT_PAR_AGGFILL "AggFill" +#define GRB_INT_PAR_CONCURRENTMIP "ConcurrentMIP" +#define GRB_INT_PAR_CONCURRENTJOBS "ConcurrentJobs" +#define GRB_INT_PAR_DISPLAYINTERVAL "DisplayInterval" +#define GRB_INT_PAR_DISTRIBUTEDMIPJOBS "DistributedMIPJobs" +#define GRB_INT_PAR_DUALREDUCTIONS "DualReductions" +#define GRB_DBL_PAR_FEASRELAXBIGM "FeasRelaxBigM" +#define GRB_INT_PAR_IISMETHOD "IISMethod" +#define GRB_INT_PAR_INFUNBDINFO "InfUnbdInfo" +#define GRB_INT_PAR_JSONSOLDETAIL "JSONSolDetail" +#define GRB_INT_PAR_LAZYCONSTRAINTS "LazyConstraints" +#define GRB_STR_PAR_LOGFILE "LogFile" +#define GRB_INT_PAR_LOGTOCONSOLE "LogToConsole" +#define GRB_INT_PAR_MIQCPMETHOD "MIQCPMethod" +#define GRB_INT_PAR_NONCONVEX "NonConvex" +#define GRB_INT_PAR_NUMERICFOCUS "NumericFocus" +#define GRB_INT_PAR_OUTPUTFLAG "OutputFlag" +#define GRB_INT_PAR_PRECRUSH "PreCrush" +#define GRB_INT_PAR_PREDEPROW "PreDepRow" +#define GRB_INT_PAR_PREDUAL "PreDual" +#define GRB_INT_PAR_PREPASSES "PrePasses" +#define GRB_INT_PAR_PREQLINEARIZE "PreQLinearize" +#define GRB_INT_PAR_PRESOLVE "Presolve" +#define GRB_DBL_PAR_PRESOS1BIGM "PreSOS1BigM" +#define GRB_DBL_PAR_PRESOS2BIGM "PreSOS2BigM" +#define GRB_INT_PAR_PRESPARSIFY "PreSparsify" +#define GRB_INT_PAR_PREMIQCPFORM "PreMIQCPForm" +#define GRB_INT_PAR_QCPDUAL "QCPDual" +#define GRB_INT_PAR_RECORD "Record" +#define GRB_STR_PAR_RESULTFILE "ResultFile" +#define GRB_INT_PAR_SEED "Seed" +#define GRB_INT_PAR_THREADS "Threads" +#define GRB_DBL_PAR_TUNETIMELIMIT "TuneTimeLimit" +#define GRB_INT_PAR_TUNERESULTS "TuneResults" +#define GRB_INT_PAR_TUNECRITERION "TuneCriterion" +#define GRB_INT_PAR_TUNETRIALS "TuneTrials" +#define GRB_INT_PAR_TUNEOUTPUT "TuneOutput" +#define GRB_INT_PAR_TUNEJOBS "TuneJobs" +#define GRB_INT_PAR_UPDATEMODE "UpdateMode" +#define GRB_INT_PAR_OBJNUMBER "ObjNumber" +#define GRB_INT_PAR_MULTIOBJMETHOD "MultiObjMethod" +#define GRB_INT_PAR_MULTIOBJPRE "MultiObjPre" +#define GRB_INT_PAR_SCENARIONUMBER "ScenarioNumber" +#define GRB_INT_PAR_POOLSOLUTIONS "PoolSolutions" +#define GRB_DBL_PAR_POOLGAP "PoolGap" +#define GRB_INT_PAR_POOLSEARCHMODE "PoolSearchMode" +#define GRB_INT_PAR_IGNORENAMES "IgnoreNames" +#define GRB_INT_PAR_STARTNUMBER "StartNumber" +#define GRB_INT_PAR_PARTITIONPLACE "PartitionPlace" +#define GRB_INT_PAR_FUNCPIECES "FuncPieces" +#define GRB_DBL_PAR_FUNCPIECELENGTH "FuncPieceLength" +#define GRB_DBL_PAR_FUNCPIECEERROR "FuncPieceError" +#define GRB_DBL_PAR_FUNCPIECERATIO "FuncPieceRatio" +#define GRB_DBL_PAR_FUNCMAXVAL "FuncMaxVal" +#define GRB_STR_PAR_DUMMY "Dummy" +#define GRB_STR_PAR_JOBID "JobID" +#define GRB_CUTS_AUTO -1 +#define GRB_CUTS_OFF 0 +#define GRB_CUTS_CONSERVATIVE 1 +#define GRB_CUTS_AGGRESSIVE 2 +#define GRB_CUTS_VERYAGGRESSIVE 3 +#define GRB_PRESOLVE_AUTO -1 +#define GRB_PRESOLVE_OFF 0 +#define GRB_PRESOLVE_CONSERVATIVE 1 +#define GRB_PRESOLVE_AGGRESSIVE 2 +#define GRB_METHOD_AUTO -1 +#define GRB_METHOD_PRIMAL 0 +#define GRB_METHOD_DUAL 1 +#define GRB_METHOD_BARRIER 2 +#define GRB_METHOD_CONCURRENT 3 +#define GRB_METHOD_DETERMINISTIC_CONCURRENT 4 +#define GRB_METHOD_DETERMINISTIC_CONCURRENT_SIMPLEX 5 +#define GRB_BARHOMOGENEOUS_AUTO -1 +#define GRB_BARHOMOGENEOUS_OFF 0 +#define GRB_BARHOMOGENEOUS_ON 1 +#define GRB_MIPFOCUS_BALANCED 0 +#define GRB_MIPFOCUS_FEASIBILITY 1 +#define GRB_MIPFOCUS_OPTIMALITY 2 +#define GRB_MIPFOCUS_BESTBOUND 3 +#define GRB_BARORDER_AUTOMATIC -1 +#define GRB_BARORDER_AMD 0 +#define GRB_BARORDER_NESTEDDISSECTION 1 +#define GRB_SIMPLEXPRICING_AUTO -1 +#define GRB_SIMPLEXPRICING_PARTIAL 0 +#define GRB_SIMPLEXPRICING_STEEPEST_EDGE 1 +#define GRB_SIMPLEXPRICING_DEVEX 2 +#define GRB_SIMPLEXPRICING_STEEPEST_QUICK 3 +#define GRB_VARBRANCH_AUTO -1 +#define GRB_VARBRANCH_PSEUDO_REDUCED 0 +#define GRB_VARBRANCH_PSEUDO_SHADOW 1 +#define GRB_VARBRANCH_MAX_INFEAS 2 +#define GRB_VARBRANCH_STRONG 3 +#define GRB_PARTITION_EARLY 16 +#define GRB_PARTITION_ROOTSTART 8 +#define GRB_PARTITION_ROOTEND 4 +#define GRB_PARTITION_NODES 2 +#define GRB_PARTITION_CLEANUP 1 +#define GRB_BATCH_STATUS_UNKNOWN 0 +#define GRB_BATCH_CREATED 1 +#define GRB_BATCH_SUBMITTED 2 +#define GRB_BATCH_ABORTED 3 +#define GRB_BATCH_FAILED 4 +#define GRB_BATCH_COMPLETED 5 +} // namespace operations_research #endif // OR_TOOLS_LINEAR_SOLVER_GUROBI_ENVIRONMENT_H_ -#endif // #if defined(USE_GUROBI) diff --git a/ortools/linear_solver/gurobi_interface.cc b/ortools/linear_solver/gurobi_interface.cc index b24b4b376c..2777d54c18 100644 --- a/ortools/linear_solver/gurobi_interface.cc +++ b/ortools/linear_solver/gurobi_interface.cc @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if defined(USE_GUROBI) - #include #include #include @@ -1211,6 +1209,7 @@ std::string GurobiInterface::ValidFileExtensionForParameterFile() const { } MPSolverInterface* BuildGurobiInterface(bool mip, MPSolver* const solver) { + MPSolver::LoadGurobiSharedLibrary(); return new GurobiInterface(solver, mip); } @@ -1219,4 +1218,4 @@ void GurobiInterface::SetCallback(MPCallback* mp_callback) { } } // namespace operations_research -#endif // #if defined(USE_GUROBI) + diff --git a/ortools/linear_solver/gurobi_proto_solver.cc b/ortools/linear_solver/gurobi_proto_solver.cc index bcb2b7a702..5ae32556cf 100644 --- a/ortools/linear_solver/gurobi_proto_solver.cc +++ b/ortools/linear_solver/gurobi_proto_solver.cc @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if defined(USE_GUROBI) - #include "ortools/linear_solver/gurobi_proto_solver.h" #include @@ -526,4 +524,3 @@ absl::StatusOr GurobiSolveProto( } // namespace operations_research -#endif // #if defined(USE_GUROBI) diff --git a/ortools/linear_solver/java/linear_solver.i b/ortools/linear_solver/java/linear_solver.i index 8b00ee3db2..64b2eb539c 100644 --- a/ortools/linear_solver/java/linear_solver.i +++ b/ortools/linear_solver/java/linear_solver.i @@ -285,6 +285,7 @@ PROTO2_RETURN( %unignore operations_research::MPSolver; %unignore operations_research::MPSolver::MPSolver; %unignore operations_research::MPSolver::~MPSolver; +%rename (createSolver) operations_research::MPSolver::CreateSolver; %unignore operations_research::MPConstraint; %unignore operations_research::MPVariable; %unignore operations_research::MPObjective; @@ -303,6 +304,7 @@ PROTO2_RETURN( // These aren't unit tested, as they only run on machines with a Gurobi license. %unignore operations_research::MPSolver::GUROBI_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING; +%rename (setGurobiLibraryPath) operations_research::MPSolver::SetGurobiLibraryPath; %unignore operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING; %unignore operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING; @@ -338,6 +340,7 @@ PROTO2_RETURN( %rename (reset) operations_research::MPSolver::Reset; // no test %rename (infinity) operations_research::MPSolver::infinity; %rename (setTimeLimit) operations_research::MPSolver::set_time_limit; // no test +%rename (isMip) operations_research::MPSolver::IsMIP; // Proto-based API of the MPSolver. Use is encouraged. // Note: the following proto-based methods aren't listed here, but are diff --git a/ortools/linear_solver/linear_solver.cc b/ortools/linear_solver/linear_solver.cc index d177b54425..684f84dfb7 100644 --- a/ortools/linear_solver/linear_solver.cc +++ b/ortools/linear_solver/linear_solver.cc @@ -24,8 +24,10 @@ #include #include "absl/status/status.h" +#include "absl/strings/ascii.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" +#include "absl/strings/str_replace.h" #include "absl/synchronization/mutex.h" #include "ortools/base/accurate_sum.h" #include "ortools/base/commandlineflags.h" @@ -362,10 +364,8 @@ extern MPSolverInterface* BuildSatInterface(MPSolver* const solver); #if defined(USE_SCIP) extern MPSolverInterface* BuildSCIPInterface(MPSolver* const solver); #endif -#if defined(USE_GUROBI) extern MPSolverInterface* BuildGurobiInterface(bool mip, MPSolver* const solver); -#endif #if defined(USE_CPLEX) extern MPSolverInterface* BuildCplexInterface(bool mip, MPSolver* const solver); @@ -404,12 +404,10 @@ MPSolverInterface* BuildSolverInterface(MPSolver* const solver) { case MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING: return BuildSCIPInterface(solver); #endif -#if defined(USE_GUROBI) case MPSolver::GUROBI_LINEAR_PROGRAMMING: return BuildGurobiInterface(false, solver); case MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING: return BuildGurobiInterface(true, solver); -#endif #if defined(USE_CPLEX) case MPSolver::CPLEX_LINEAR_PROGRAMMING: return BuildCplexInterface(false, solver); @@ -468,10 +466,8 @@ bool MPSolver::SupportsProblemType(OptimizationProblemType problem_type) { if (problem_type == BOP_INTEGER_PROGRAMMING) return true; if (problem_type == SAT_INTEGER_PROGRAMMING) return true; if (problem_type == GLOP_LINEAR_PROGRAMMING) return true; -#ifdef USE_GUROBI if (problem_type == GUROBI_LINEAR_PROGRAMMING) return true; if (problem_type == GUROBI_MIXED_INTEGER_PROGRAMMING) return true; -#endif #ifdef USE_SCIP if (problem_type == SCIP_MIXED_INTEGER_PROGRAMMING) return true; #endif @@ -512,9 +508,7 @@ constexpr #if defined(USE_CLP) {MPSolver::CLP_LINEAR_PROGRAMMING, "clp"}, #endif -#if defined(USE_GUROBI) {MPSolver::GUROBI_LINEAR_PROGRAMMING, "gurobi_lp"}, -#endif #if defined(USE_CPLEX) {MPSolver::CPLEX_LINEAR_PROGRAMMING, "cplex_lp"}, #endif @@ -532,9 +526,7 @@ constexpr #endif {MPSolver::BOP_INTEGER_PROGRAMMING, "bop"}, {MPSolver::SAT_INTEGER_PROGRAMMING, "sat"}, -#if defined(USE_GUROBI) {MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING, "gurobi_mip"}, -#endif #if defined(USE_CPLEX) {MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING, "cplex_mip"}, #endif @@ -579,6 +571,96 @@ bool AbslParseFlag(const absl::string_view text, return result; } +/* static */ +MPSolver* MPSolver::CreateSolver(const std::string& name, + const std::string& solver_id) { + // Normalize the solver id. + const std::string id = + absl::StrReplaceAll(absl::AsciiStrToUpper(solver_id), {{"-", "_"}}); + + if (id == "CLP_LINEAR_PROGRAMMING" || id == "CLP") { +#if defined(USE_CLP) + return new MPSolver(name, MPSolver::CLP_LINEAR_PROGRAMMING); +#else + return nullptr; +#endif + } else if (id == "CBC_MIXED_INTEGER_PROGRAMMING" || id == "CBC") { +#if defined(USE_CBC) + return new MPSolver(name, MPSolver::CBC_MIXED_INTEGER_PROGRAMMING); +#else + return nullptr; +#endif + } else if (id == "GLOP_LINEAR_PROGRAMMING" || id == "GLOP") { + return new MPSolver(name, MPSolver::GLOP_LINEAR_PROGRAMMING); + } else if (id == "BOP_INTEGER_PROGRAMMING" || id == "BOP") { + return new MPSolver(name, MPSolver::BOP_INTEGER_PROGRAMMING); + } else if (id == "SAT_INTEGER_PROGRAMMING" || id == "SAT" || id == "CP_SAT") { + return new MPSolver(name, MPSolver::SAT_INTEGER_PROGRAMMING); + } else if (id == "SCIP_MIXED_INTEGER_PROGRAMMING" || id == "SCIP") { +#if defined(USE_SCIP) + return new MPSolver(name, MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING); +#else + return nullptr; +#endif + } else if (id == "GUROBI_LINEAR_PROGRAMMING" || id == "GUROBI_LP") { + return GurobiIsCorrectlyInstalled() + ? new MPSolver(name, MPSolver::GUROBI_LINEAR_PROGRAMMING) + : nullptr; + } else if (id == "GUROBI_MIXED_INTEGER_PROGRAMMING" || id == "GUROBI_MIP" || + id == "GUROBI") { + return GurobiIsCorrectlyInstalled() + ? new MPSolver(name, MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING) + : nullptr; + } else if (id == "CPLEX_MIXED_INTEGER_PROGRAMMING" || id == "CPLEX_MIP" || + id == "CPLEX") { +#if defined(USE_CPLEX) + return new MPSolver(name, MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING); +#else + return nullptr; +#endif + } else if (id == "CPLEX_LINEAR_PROGRAMMING" || id == "CPLEX_LP") { +#if defined(USE_CPLEX) + return new MPSolver(name, MPSolver::CPLEX_LINEAR_PROGRAMMING); +#else + return nullptr; +#endif +} +else if (id == "XPRESS_MIXED_INTEGER_PROGRAMMING" || id == "XPRESS" || + id == "XPRESS_MIP") { +#if defined(USE_XPRESS) + return new MPSolver(name, MPSolver::XPRESS_MIXED_INTEGER_PROGRAMMING); +#else + return nullptr; +#endif +} +else if (id == "XPRESS_LINEAR_PROGRAMMING" || id == "XPRESS_LP") { +#if defined(USE_XPRESS) + return new MPSolver(name, MPSolver::XPRESS_LINEAR_PROGRAMMING); +#else + return nullptr; +#endif +} +else if (id == "GLPK_MIXED_INTEGER_PROGRAMMING" || id == "GLPK_MIP" || + id == "GLPK") { +#if defined(USE_GLPK) + return new MPSolver(name, MPSolver::GLPK_MIXED_INTEGER_PROGRAMMING); +#else + return nullptr; +#endif +} +else if (id == "GLPK_LINEAR_PROGRAMMING" || id == "GLPK_LP") { +#if defined(USE_GLPK) + return new MPSolver(name, MPSolver::GLPK_LINEAR_PROGRAMMING); +#else + return nullptr; +#endif +} +else { + LOG(WARNING) << "Unrecognized solver id '" << solver_id << "'"; + return nullptr; +} +} // namespace operations_research + MPVariable* MPSolver::LookupVariableOrNull(const std::string& var_name) const { if (!variable_name_to_index_) GenerateVariableNameIndex(); diff --git a/ortools/linear_solver/linear_solver.h b/ortools/linear_solver/linear_solver.h index 9281022ce5..0ab7fbf26b 100644 --- a/ortools/linear_solver/linear_solver.h +++ b/ortools/linear_solver/linear_solver.h @@ -193,14 +193,16 @@ class MPSolver { #endif /// Linear Programming solver using GLOP (Recommended solver). GLOP_LINEAR_PROGRAMMING = 2, -#ifdef USE_GUROBI /// Linear Programming solver using GUROBI. GUROBI_LINEAR_PROGRAMMING = 6, -#endif #ifdef USE_CPLEX /// Linear Programming solver using CPLEX. CPLEX_LINEAR_PROGRAMMING = 10, #endif +#if defined(USE_XPRESS) + /// Linear Programming solver using XPRESS-MP. + XPRESS_LINEAR_PROGRAMMING = 101, +#endif // Integer programming problems. #ifdef USE_SCIP @@ -215,10 +217,8 @@ class MPSolver { /// Mixed integer Programming Solver using Coin CBC. CBC_MIXED_INTEGER_PROGRAMMING = 5, #endif -#if defined(USE_GUROBI) /// Mixed integer Programming Solver using GUROBI. GUROBI_MIXED_INTEGER_PROGRAMMING = 7, -#endif #if defined(USE_CPLEX) /// Mixed integer Programming Solver using CPLEX. CPLEX_MIXED_INTEGER_PROGRAMMING = 11, @@ -230,7 +230,7 @@ class MPSolver { /// integer values, and solve continuous variables as integral variables. SAT_INTEGER_PROGRAMMING = 14, #if defined(USE_XPRESS) - XPRESS_LINEAR_PROGRAMMING = 101, + /// Mixed integer Programming solver using XPRESS-MP. XPRESS_MIXED_INTEGER_PROGRAMMING = 102, #endif }; @@ -239,6 +239,35 @@ class MPSolver { MPSolver(const std::string& name, OptimizationProblemType problem_type); virtual ~MPSolver(); + /** + * Recommended factory method to create a MPSolver instance. + * It returns a newly created solver instance if successful, or a nullptr + * otherwise. This can occur if the relevant interface is not linked in, or if + * a needed license is not accessible for commercial solvers. + * + * Ownership of the solver is passed on to the caller of this method. + * It will accept both string names of the OptimizationProblemType enum, as + * well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP"). + * + * solver_id is case insensitive, and the following names are supported: + * - CLP_LINEAR_PROGRAMMING or CLP + * - CBC_MIXED_INTEGER_PROGRAMMING or CBC + * - GLOP_LINEAR_PROGRAMMING or GLOP + * - BOP_INTEGER_PROGRAMMING or BOP + * - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT + * - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP + * - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP + * - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP + * - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP + * - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP + * - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP + * - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP + * - GLPK_LINEAR_PROGRAMMING or GLPK_LP + * - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP + */ + static MPSolver* CreateSolver(const std::string& name, + const std::string& solver_id); + /** * Whether the given problem type is supported (this will depend on the * targets that you linked). @@ -768,6 +797,10 @@ class MPSolver { return absl::ToInt64Milliseconds(DurationSinceConstruction()); } + // Supports search and loading Gurobi shared library. + static bool LoadGurobiSharedLibrary(); + static void SetGurobiLibraryPath(const std::string &full_library_path); + friend class GLPKInterface; friend class CLPInterface; friend class CBCInterface; @@ -804,6 +837,10 @@ class MPSolver { // Generates the map from constraint names to their indices. void GenerateConstraintNameIndex() const; + // Checks licenses for commercial solver, and checks shared library loading + // for or-tools. + static bool GurobiIsCorrectlyInstalled(); + // The name of the linear programming problem. const std::string name_; @@ -1069,6 +1106,8 @@ class MPVariable { /** * Advanced usage: returns the basis status of the variable in the current * solution (only available for continuous problems). + * + * @see MPSolver::BasisStatus. */ MPSolver::BasisStatus basis_status() const; @@ -1222,6 +1261,8 @@ class MPConstraint { * into "linear_expression + slack = 0" with slack in [-ub, -lb], then this * status is the same as the status of the slack variable with AT_UPPER_BOUND * and AT_LOWER_BOUND swapped. + * + * @see MPSolver::BasisStatus. */ MPSolver::BasisStatus basis_status() const; diff --git a/ortools/linear_solver/python/linear_solver.i b/ortools/linear_solver/python/linear_solver.i index b48546c1f0..c8e96eb899 100644 --- a/ortools/linear_solver/python/linear_solver.i +++ b/ortools/linear_solver/python/linear_solver.i @@ -270,6 +270,7 @@ PY_CONVERT(MPVariable); // These aren't unit tested, as they only run on machines with a Gurobi license. %unignore operations_research::MPSolver::GUROBI_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::GUROBI_MIXED_INTEGER_PROGRAMMING; +%unignore operations_research::MPSolver::SetGurobiLibraryPath; %unignore operations_research::MPSolver::CPLEX_LINEAR_PROGRAMMING; %unignore operations_research::MPSolver::CPLEX_MIXED_INTEGER_PROGRAMMING; %unignore operations_research::MPSolver::XPRESS_LINEAR_PROGRAMMING; @@ -299,6 +300,7 @@ PY_CONVERT(MPVariable); %rename (Constraint) operations_research::MPSolver::MakeRowConstraint(double, double, const std::string&); %rename (Constraint) operations_research::MPSolver::MakeRowConstraint(const std::string&); %unignore operations_research::MPSolver::~MPSolver; +%unignore operations_research::MPSolver::CreateSolver; %unignore operations_research::MPSolver::Solve; %unignore operations_research::MPSolver::VerifySolution; %unignore operations_research::MPSolver::infinity; diff --git a/ortools/linear_solver/samples/AssignmentMip.cs b/ortools/linear_solver/samples/AssignmentMip.cs index e2c7e71fa5..7e34df46a9 100644 --- a/ortools/linear_solver/samples/AssignmentMip.cs +++ b/ortools/linear_solver/samples/AssignmentMip.cs @@ -36,7 +36,7 @@ public class AssignmentMip // Model. // [START model] - Solver solver = Solver.CreateSolver("AssignmentMip", "CBC_MIXED_INTEGER_PROGRAMMING"); + Solver solver = Solver.CreateSolver("AssignmentMip", "cbc"); // [END model] // Variables. diff --git a/ortools/linear_solver/samples/AssignmentMip.java b/ortools/linear_solver/samples/AssignmentMip.java index 4e260d8181..3d7310f974 100644 --- a/ortools/linear_solver/samples/AssignmentMip.java +++ b/ortools/linear_solver/samples/AssignmentMip.java @@ -43,8 +43,7 @@ public class AssignmentMip { // Solver // [START solver] // Create the linear solver with the CBC backend. - MPSolver solver = new MPSolver( - "AssignmentMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("AssignmentMip", "cbc"); // [END solver] // Variables diff --git a/ortools/linear_solver/samples/BinPackingMip.cs b/ortools/linear_solver/samples/BinPackingMip.cs index b07fca8f22..18ed6664c0 100644 --- a/ortools/linear_solver/samples/BinPackingMip.cs +++ b/ortools/linear_solver/samples/BinPackingMip.cs @@ -38,7 +38,7 @@ public class BinPackingMip // [START solver] // Create the linear solver with the CBC backend. - Solver solver = Solver.CreateSolver("BinPackingMip", "CBC_MIXED_INTEGER_PROGRAMMING"); + Solver solver = Solver.CreateSolver("BinPackingMip", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/BinPackingMip.java b/ortools/linear_solver/samples/BinPackingMip.java index 8ef4318da7..bb53a465bf 100644 --- a/ortools/linear_solver/samples/BinPackingMip.java +++ b/ortools/linear_solver/samples/BinPackingMip.java @@ -45,8 +45,7 @@ public class BinPackingMip { // [START solver] // Create the linear solver with the CBC backend. - MPSolver solver = new MPSolver( - "BinPackingMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("BinPackingMip", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/LinearProgrammingExample.cs b/ortools/linear_solver/samples/LinearProgrammingExample.cs index babdbba0a7..1573f841f6 100644 --- a/ortools/linear_solver/samples/LinearProgrammingExample.cs +++ b/ortools/linear_solver/samples/LinearProgrammingExample.cs @@ -20,7 +20,7 @@ public class LinearProgrammingExample static void Main() { // [START solver] - Solver solver = Solver.CreateSolver("LinearProgrammingExample", "GLOP_LINEAR_PROGRAMMING"); + Solver solver = Solver.CreateSolver("LinearProgrammingExample", "glop"); // [END solver] // x and y are continuous non-negative variables. // [START variables] diff --git a/ortools/linear_solver/samples/LinearProgrammingExample.java b/ortools/linear_solver/samples/LinearProgrammingExample.java index 8ccee728a7..39129716ae 100644 --- a/ortools/linear_solver/samples/LinearProgrammingExample.java +++ b/ortools/linear_solver/samples/LinearProgrammingExample.java @@ -27,8 +27,7 @@ public class LinearProgrammingExample { public static void main(String[] args) throws Exception { // [START solver] - MPSolver solver = new MPSolver( - "LinearProgrammingExample", MPSolver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("LinearProgrammingExample", "glop"); // [END solver] // [START variables] diff --git a/ortools/linear_solver/samples/MipVarArray.cs b/ortools/linear_solver/samples/MipVarArray.cs index d24da6727d..61c26e8a3d 100644 --- a/ortools/linear_solver/samples/MipVarArray.cs +++ b/ortools/linear_solver/samples/MipVarArray.cs @@ -44,7 +44,7 @@ public class MipVarArray // [START solver] // Create the linear solver with the CBC backend. - Solver solver = Solver.CreateSolver("SimpleMipProgram", "CBC_MIXED_INTEGER_PROGRAMMING"); + Solver solver = Solver.CreateSolver("MipVarArray", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/MipVarArray.java b/ortools/linear_solver/samples/MipVarArray.java index 8e5ee11d00..c523ad92b6 100644 --- a/ortools/linear_solver/samples/MipVarArray.java +++ b/ortools/linear_solver/samples/MipVarArray.java @@ -50,8 +50,7 @@ public class MipVarArray { // [START solver] // Create the linear solver with the CBC backend. - MPSolver solver = new MPSolver( - "SimpleMipProgram", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("MipVarArray", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/MultipleKnapsackMip.cs b/ortools/linear_solver/samples/MultipleKnapsackMip.cs index cfa98bb607..3c2a9c87c9 100644 --- a/ortools/linear_solver/samples/MultipleKnapsackMip.cs +++ b/ortools/linear_solver/samples/MultipleKnapsackMip.cs @@ -41,7 +41,7 @@ public class MultipleKnapsackMip // [START solver] // Create the linear solver with the CBC backend. - Solver solver = Solver.CreateSolver("MultipleKnapsackMip", "CBC_MIXED_INTEGER_PROGRAMMING"); + Solver solver = Solver.CreateSolver("MultipleKnapsackMip", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/MultipleKnapsackMip.java b/ortools/linear_solver/samples/MultipleKnapsackMip.java index 95234a5e52..36cd5e937a 100644 --- a/ortools/linear_solver/samples/MultipleKnapsackMip.java +++ b/ortools/linear_solver/samples/MultipleKnapsackMip.java @@ -46,8 +46,7 @@ public class MultipleKnapsackMip { // [START solver] // Create the linear solver with the CBC backend. - MPSolver solver = new MPSolver( - "MultipleKnapsackMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("MultipleKnapsackMip", "cbc"); // [END solver] // [START program_part2] diff --git a/ortools/linear_solver/samples/SimpleLpProgram.cs b/ortools/linear_solver/samples/SimpleLpProgram.cs index 4882a22e60..9f82556740 100644 --- a/ortools/linear_solver/samples/SimpleLpProgram.cs +++ b/ortools/linear_solver/samples/SimpleLpProgram.cs @@ -22,7 +22,7 @@ public class SimpleLpProgram { // [START solver] // Create the linear solver with the GLOP backend. - Solver solver = Solver.CreateSolver("SimpleLpProgram", "GLOP_LINEAR_PROGRAMMING"); + Solver solver = Solver.CreateSolver("SimpleLpProgram", "glop"); // [END solver] // [START variables] diff --git a/ortools/linear_solver/samples/SimpleLpProgram.java b/ortools/linear_solver/samples/SimpleLpProgram.java index b0f75f110a..83d30d6a86 100644 --- a/ortools/linear_solver/samples/SimpleLpProgram.java +++ b/ortools/linear_solver/samples/SimpleLpProgram.java @@ -30,8 +30,7 @@ public class SimpleLpProgram { public static void main(String[] args) throws Exception { // [START solver] // Create the linear solver with the GLOP backend. - MPSolver solver = - new MPSolver("SimpleLpProgram", MPSolver.OptimizationProblemType.GLOP_LINEAR_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("SimpleLpProgram", "glop"); // [END solver] // [START variables] diff --git a/ortools/linear_solver/samples/SimpleMipProgram.cs b/ortools/linear_solver/samples/SimpleMipProgram.cs index 895b31f34e..6d84e8787b 100644 --- a/ortools/linear_solver/samples/SimpleMipProgram.cs +++ b/ortools/linear_solver/samples/SimpleMipProgram.cs @@ -23,7 +23,7 @@ public class SimpleMipProgram { // [START solver] // Create the linear solver with the CBC backend. - Solver solver = Solver.CreateSolver("SimpleMipProgram", "CBC_MIXED_INTEGER_PROGRAMMING"); + Solver solver = Solver.CreateSolver("SimpleMipProgram", "cbc"); // [END solver] // [START variables] diff --git a/ortools/linear_solver/samples/SimpleMipProgram.java b/ortools/linear_solver/samples/SimpleMipProgram.java index 767a4a168d..96d6488981 100644 --- a/ortools/linear_solver/samples/SimpleMipProgram.java +++ b/ortools/linear_solver/samples/SimpleMipProgram.java @@ -30,8 +30,7 @@ public class SimpleMipProgram { public static void main(String[] args) throws Exception { // [START solver] // Create the linear solver with the CBC backend. - MPSolver solver = new MPSolver( - "SimpleMipProgram", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING); + MPSolver solver = MPSolver.createSolver("SimpleMipProgram", "cbc"); // [END solver] // [START variables] diff --git a/ortools/linear_solver/samples/assignment_mip.py b/ortools/linear_solver/samples/assignment_mip.py index 667b7a665c..a4c125bece 100644 --- a/ortools/linear_solver/samples/assignment_mip.py +++ b/ortools/linear_solver/samples/assignment_mip.py @@ -34,8 +34,8 @@ def main(): # Solver # [START solver] # Create the mip solver with the CBC backend. - solver = pywraplp.Solver('simple_mip_program', - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('simple_mip_program', 'cbc') + # [END solver] # Variables diff --git a/ortools/linear_solver/samples/bin_packing_mip.py b/ortools/linear_solver/samples/bin_packing_mip.py index abf3575f52..8c8e23d970 100644 --- a/ortools/linear_solver/samples/bin_packing_mip.py +++ b/ortools/linear_solver/samples/bin_packing_mip.py @@ -43,8 +43,8 @@ def main(): # [START solver] # Create the mip solver with the CBC backend. - solver = pywraplp.Solver('bin_packing_mip', - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('bin_packing_mip', 'cbc') + # [END solver] # [START program_part2] diff --git a/ortools/linear_solver/samples/integer_programming_example.py b/ortools/linear_solver/samples/integer_programming_example.py index 18354bf20f..29a3a6292c 100644 --- a/ortools/linear_solver/samples/integer_programming_example.py +++ b/ortools/linear_solver/samples/integer_programming_example.py @@ -22,8 +22,8 @@ def IntegerProgrammingExample(): """Integer programming sample.""" # [START solver] # Create the mip solver with the CBC backend. - solver = pywraplp.Solver('IntegerProgrammingExample', - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('IntegerProgrammingExample', 'cbc') + # [END solver] # [START variables] diff --git a/ortools/linear_solver/samples/linear_programming_example.py b/ortools/linear_solver/samples/linear_programming_example.py index d71f744621..06d68392c5 100644 --- a/ortools/linear_solver/samples/linear_programming_example.py +++ b/ortools/linear_solver/samples/linear_programming_example.py @@ -23,8 +23,7 @@ def LinearProgrammingExample(): """Linear programming sample.""" # Instantiate a Glop solver, naming it LinearExample. # [START solver] - solver = pywraplp.Solver('LinearProgrammingExample', - pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('LinearProgrammingExample', 'glop') # [END solver] # Create the two variables and let them take on any non-negative value. diff --git a/ortools/linear_solver/samples/mip_var_array.py b/ortools/linear_solver/samples/mip_var_array.py index e449088200..6c02d37c12 100644 --- a/ortools/linear_solver/samples/mip_var_array.py +++ b/ortools/linear_solver/samples/mip_var_array.py @@ -47,8 +47,7 @@ def main(): # [END program_part1] # [START solver] # Create the mip solver with the CBC backend. - solver = pywraplp.Solver('simple_mip_program', - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('mip_var_array', 'cbc') # [END solver] # [START program_part2] diff --git a/ortools/linear_solver/samples/multiple_knapsack_mip.py b/ortools/linear_solver/samples/multiple_knapsack_mip.py index b0d0b8b6d8..aa20275ea6 100644 --- a/ortools/linear_solver/samples/multiple_knapsack_mip.py +++ b/ortools/linear_solver/samples/multiple_knapsack_mip.py @@ -47,8 +47,7 @@ def main(): # [START solver] # Create the mip solver with the CBC backend. - solver = pywraplp.Solver('multiple_knapsack_mip', - pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('multiple_knapsack_mip', 'cbc') # [END solver] # [START program_part2] diff --git a/ortools/linear_solver/samples/simple_lp_program.py b/ortools/linear_solver/samples/simple_lp_program.py index 0f4b4561f1..9dc49f3b3e 100644 --- a/ortools/linear_solver/samples/simple_lp_program.py +++ b/ortools/linear_solver/samples/simple_lp_program.py @@ -21,8 +21,7 @@ from ortools.linear_solver import pywraplp def main(): # [START solver] # Create the linear solver with the GLOP backend. - solver = pywraplp.Solver('simple_lp_program', - pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) + solver = pywraplp.Solver.CreateSolver('simple_lp_program', 'glop') # [END solver] # [START variables]