Skip to content

Solver keeps running after optimal solution found #4997

@baklazan

Description

@baklazan

What version of OR-Tools and what language are you using?
Version: v9.15
Language: C++

Which solver are you using (e.g. CP-SAT, Routing Solver, GLOP, BOP, Gurobi)
CP-SAT

What operating system (Linux, Windows, ...) and version?
Linux

What did you do?

  1. Create an operations_research::sat::Model instance
  2. Register a feasible solution observer
  3. Register an external boolean as limit
  4. Run operations_research::sat::SolveCpModel using the Model from step 1

Here's a minimum example:

#include <atomic>
#include <fstream>
#include <iostream>

#include "ortools/sat/cp_model.pb.h"
#include "ortools/sat/cp_model_solver.h"
#include "ortools/util/time_limit.h"

namespace sat = operations_research::sat;

int main(int argc, char** argv) {
  if (argc != 2) {
    std::cerr << argv[0] << " input-proto-message\n";
    return -1;
  }
  sat::CpModelProto cp_model;
  std::ifstream in(argv[1], std::ios::binary);
  if (!cp_model.ParseFromIstream(&in)) {
    std::cerr << "Failed to open or parse " << argv[1] << "\n";
    return -1;
  }

  sat::SatParameters params;
  params.set_num_workers(16);
  params.set_log_search_progress(true);

  std::atomic<bool> stop;
  sat::Model model;

  model.Add(NewSatParameters(params));
  model.Add(sat::NewFeasibleSolutionObserver(
      [](const sat::CpSolverResponse& response) {
        std::cerr << response.best_objective_bound() << ""
                  << response.objective_value() << "\n";
      }));
  model.GetOrCreate<operations_research::TimeLimit>()
      ->RegisterExternalBooleanAsLimit(&stop);

  sat::CpSolverResponse response = sat::SolveCpModel(cp_model, &model);
  std::cout << "Solver finished, status=" << response.status() << "\n";
}

I ran the above code on this input: model.zip.
It takes about 2 minutes to find an optimal solution.

What did you expect to see

After the solver finds an optimal solution, it terminates.

What did you see instead?

The solver keeps on running.
I first noticed this issue when I "manually" (using the stop variable) stopped the solver after 10 minutes and it reported an optimal solution with a tight lower bound.
I subsequently verified by adding a debug print to operations_research::SharedTimeLimit::Stop.

Anything else we should know about your project / environment

If I reverse the order of model.Add calls (register bool limit first, then the feasible solution observer), the solver terminates as expected.

I think the issue might be caused by NewFeasibleSolutionObserver creating an instance of SharedResponseManager, which forces creation of ModelSharedTimeLimit. When I later register the external boolean limit in TimeLimit, it doesn't correctly propagate to SharedTimeLimit.

Metadata

Metadata

Assignees

Labels

Help NeededModeling/Usage problemLang: C++Native implementation issueOS: LinuxGNU/Linux OS

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions