google / or-tools

Google's Operations Research tools:
https://developers.google.com/optimization/
Apache License 2.0
11k stars 2.11k forks source link

BOP solver: Using number_of_solvers results in abnormal status #1504

Closed syxolk closed 5 years ago

syxolk commented 5 years ago

Hi, I am current trying to use the multi-threading feature of the BOP solver with the pywraplp frontend. I'm using Python 3.7.4 with OR-Tools 7.3.7083.

The following code results in an ABNORMAL result status:

from ortools.linear_solver import pywraplp

def main():
    solver = pywraplp.Solver('test', pywraplp.Solver.BOP_INTEGER_PROGRAMMING)
    solver.EnableOutput()
    solver.SetSolverSpecificParametersAsString("number_of_solvers: 2 synchronization_type: SYNCHRONIZE_ALL")

    x = solver.IntVar(0, 10, "")
    y = solver.IntVar(0, 10, "")
    solver.Add(y == 2*x)
    solver.Maximize(y)

    result_status = solver.Solve()
    print(f"{pywraplp.Solver.OPTIMAL} == {result_status}")
    if result_status == pywraplp.Solver.OPTIMAL:
        print(f"x = {x.SolutionValue()}")
        print(f"y = {y.SolutionValue()}")

main()

Output:

0 == 4

However, when I comment out the solver.SetSolverSpecificParametersAsString line or use number_of_solvers: 1 instead it works as expected:

WARNING: Logging before InitGoogleLogging() is written to STDERR
I0815 11:40:39.133632 20305 bop_portfolio.cc:147]       30 .. inf Portfolio - SATRandomFirstSolution. Time limit: inf -- inf
I0815 11:40:39.133743 20305 bop_portfolio.cc:79] Stats. #new_solutions/#calls by optimizer:
                      SATRandomFirstSolution :   0/1    (  0.00%)  Total gain:      0  Total Dtime: 0.000 score: 0.000001
0 == 0
x = 5.0
y = 10.0
lperron commented 5 years ago

Are you sure this is a supported parameter? I guess not, and the solver tells you it could not parse this string.

lperron commented 5 years ago

And really, you should not use BOP for that, BOP is for Boolean problems. The support for integer variables is slow and experimental.

In fact, you should use the CP-SAT solver directly:

from ortools.sat.python import cp_model

def main():
    model = cp_model.CpModel()

    x = model.NewIntVar(0, 10, "")
    y = model.NewIntVar(0, 10, "")
    model.Add(y == 2*x)
    model.Maximize(y)

    solver = cp_model.CpSolver()

    result_status = solver.Solve(model)
    print(f"status = {solver.StatusName(result_status)}")
    if result_status == cp_model.OPTIMAL:
        print(f"x = {solver.Value(x)}")
        print(f"y = {solver.Value(y)}")

main()

which outputs

status = OPTIMAL
x = 5
y = 10
lperron commented 5 years ago

to add Parallelism, just add the line before the Solve() method

solver.parameters.num_search_workers = 8
syxolk commented 5 years ago

Thanks for the suggestion with CP-SAT but I'm currently comparing different MIP solvers, so I want to use BOP.

Are you sure this is a supported parameter?

Yes, I've discovered it here: https://github.com/google/or-tools/blob/v7.3/ortools/bop/bop_parameters.proto#L184

  // The number of solvers used to run Bop. Note that one thread will be created
  // per solver. The type of communication between solvers is specified by the
  // synchronization_type parameter.
  optional int32 number_of_solvers = 24 [default = 1];

I guess not, and the solver tells you it could not parse this string.

It actually does not give me any error message.

When I do something obviously wrong like:

solver.SetSolverSpecificParametersAsString("foobar: 1")

I get an error message:

[libprotobuf ERROR /home/hans/projects/or-tools/dependencies/sources/protobuf-3.9.0/src/google/protobuf/text_format.cc:324]
Error parsing text-format operations_research.bop.BopParameters:
1:7: Message type "operations_research.bop.BopParameters" has no field named "foobar".

But this works just fine without error message:

solver.SetSolverSpecificParametersAsString("number_of_solvers: 2 synchronization_type: SYNCHRONIZE_ALL")
syxolk commented 5 years ago

So, is this an official feature of BOP or not?