Update bop folder + add test
This commit is contained in:
committed by
Mizux Seiha
parent
cb2fae32ed
commit
c807a53c0f
@@ -14,6 +14,7 @@
|
||||
load("@protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
|
||||
load("@protobuf//bazel:proto_library.bzl", "proto_library")
|
||||
load("@rules_cc//cc:cc_library.bzl", "cc_library")
|
||||
load("@rules_cc//cc:cc_test.bzl", "cc_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
@@ -24,16 +25,15 @@ proto_library(
|
||||
|
||||
cc_proto_library(
|
||||
name = "bop_parameters_cc_proto",
|
||||
deps = ["bop_parameters_proto"],
|
||||
deps = [":bop_parameters_proto"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "bop_types",
|
||||
hdrs = ["bop_types.h"],
|
||||
deps = [
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/util:strong_integers",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -45,21 +45,19 @@ cc_library(
|
||||
":bop_parameters_cc_proto",
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"@abseil-cpp//absl/synchronization",
|
||||
"//ortools/glop:lp_solver",
|
||||
# "//ortools/glop",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:clause",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/base:threadpool",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/base:core_headers",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/synchronization",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -70,9 +68,17 @@ cc_library(
|
||||
deps = [
|
||||
":bop_base",
|
||||
":bop_solution",
|
||||
"//ortools/base",
|
||||
":bop_types",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"//ortools/sat:restart",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/util:bitset",
|
||||
"//ortools/util:strong_integers",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -82,11 +88,27 @@ cc_library(
|
||||
hdrs = ["bop_solution.h"],
|
||||
deps = [
|
||||
":bop_types",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "bop_solution_test",
|
||||
size = "small",
|
||||
srcs = ["bop_solution_test.cc"],
|
||||
deps = [
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
"//ortools/base:gmock_main",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/util:strong_integers",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@protobuf",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -101,24 +123,29 @@ cc_library(
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
"//ortools/algorithms:sparse_permutation",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/glop:lp_solver",
|
||||
#"//ortools/glop",
|
||||
"//ortools/lp_data:lp_print_utils",
|
||||
"//ortools/glop:parameters_cc_proto",
|
||||
"//ortools/lp_data",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:clause",
|
||||
"//ortools/sat:lp_utils",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_parameters_cc_proto",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/sat:symmetry",
|
||||
"//ortools/sat:util",
|
||||
"//ortools/util:bitset",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/random",
|
||||
"@protobuf",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/random:bit_gen_ref",
|
||||
"@abseil-cpp//absl/random:distributions",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -132,23 +159,26 @@ cc_library(
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/glop:lp_solver",
|
||||
#"//ortools/glop",
|
||||
"//ortools/lp_data:lp_print_utils",
|
||||
"//ortools/lp_data",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:lp_utils",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_parameters_cc_proto",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/util:bitset",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/random",
|
||||
"@abseil-cpp//absl/cleanup",
|
||||
"@protobuf",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/random:bit_gen_ref",
|
||||
"@abseil-cpp//absl/random:distributions",
|
||||
"@abseil-cpp//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -158,19 +188,22 @@ cc_library(
|
||||
hdrs = ["complete_optimizer.h"],
|
||||
deps = [
|
||||
":bop_base",
|
||||
":bop_parameters_cc_proto",
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:encoding",
|
||||
"//ortools/sat:optimization",
|
||||
"//ortools/sat:model",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_parameters_cc_proto",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -180,18 +213,26 @@ cc_library(
|
||||
hdrs = ["bop_ls.h"],
|
||||
deps = [
|
||||
":bop_base",
|
||||
":bop_parameters_cc_proto",
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
"//ortools/base",
|
||||
"//ortools/base:hash",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:logging",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:sat_base",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/container:flat_hash_map",
|
||||
"@abseil-cpp//absl/container:flat_hash_set",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/meta:type_traits",
|
||||
"@abseil-cpp//absl/random",
|
||||
"@abseil-cpp//absl/status:statusor",
|
||||
"@abseil-cpp//absl/random:bit_gen_ref",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/strings:str_format",
|
||||
"@abseil-cpp//absl/types:span",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -209,22 +250,24 @@ cc_library(
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
":complete_optimizer",
|
||||
"//ortools/base",
|
||||
"//ortools/base:hash",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"@abseil-cpp//absl/log:vlog_is_on",
|
||||
"@abseil-cpp//absl/status:statusor",
|
||||
"//ortools/algorithms:sparse_permutation",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/glop:lp_solver",
|
||||
#"//ortools/glop",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/sat:symmetry",
|
||||
"//ortools/util:random_engine",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/log:vlog_is_on",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -234,31 +277,22 @@ cc_library(
|
||||
hdrs = ["bop_solver.h"],
|
||||
deps = [
|
||||
":bop_base",
|
||||
":bop_fs",
|
||||
":bop_lns",
|
||||
":bop_ls",
|
||||
":bop_parameters_cc_proto",
|
||||
":bop_portfolio",
|
||||
":bop_solution",
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
":complete_optimizer",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/glop:lp_solver",
|
||||
#"//ortools/glop",
|
||||
"//ortools/lp_data:lp_print_utils",
|
||||
"//ortools/base:threadpool",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/sat:lp_utils",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/base:threadpool",
|
||||
"//ortools/util:bitset",
|
||||
"//ortools/util:time_limit",
|
||||
"@protobuf",
|
||||
"//ortools/sat:pb_constraint",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:time_limit",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/status",
|
||||
"@abseil-cpp//absl/strings:str_format",
|
||||
"@protobuf",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -267,29 +301,28 @@ cc_library(
|
||||
srcs = ["integral_solver.cc"],
|
||||
hdrs = ["integral_solver.h"],
|
||||
deps = [
|
||||
":bop_base",
|
||||
":bop_fs",
|
||||
":bop_lns",
|
||||
":bop_ls",
|
||||
":bop_parameters_cc_proto",
|
||||
":bop_solution",
|
||||
":bop_solver",
|
||||
":bop_types",
|
||||
":bop_util",
|
||||
"//ortools/base",
|
||||
"//ortools/base:intops",
|
||||
"//ortools/base:stl_util",
|
||||
"//ortools/base:strong_vector",
|
||||
"//ortools/glop:lp_solver",
|
||||
"//ortools/base:threadpool",
|
||||
"//ortools/lp_data",
|
||||
"//ortools/lp_data:base",
|
||||
"//ortools/lp_data:lp_decomposer",
|
||||
"//ortools/lp_data:lp_utils",
|
||||
"//ortools/lp_data:sparse",
|
||||
"//ortools/lp_data:sparse_column",
|
||||
"//ortools/lp_data:sparse_vector",
|
||||
"//ortools/sat:boolean_problem",
|
||||
"//ortools/sat:lp_utils",
|
||||
"//ortools/sat:sat_solver",
|
||||
"//ortools/sat:boolean_problem_cc_proto",
|
||||
"//ortools/util:bitset",
|
||||
"//ortools/util:stats",
|
||||
"//ortools/util:fp_utils",
|
||||
"//ortools/util:strong_integers",
|
||||
"//ortools/util:time_limit",
|
||||
"@protobuf",
|
||||
"@abseil-cpp//absl/base:core_headers",
|
||||
"@abseil-cpp//absl/log",
|
||||
"@abseil-cpp//absl/log:check",
|
||||
"@abseil-cpp//absl/strings:str_format",
|
||||
],
|
||||
)
|
||||
|
||||
174
ortools/bop/bop_solution_test.cc
Normal file
174
ortools/bop/bop_solution_test.cc
Normal file
@@ -0,0 +1,174 @@
|
||||
// Copyright 2010-2025 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
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ortools/bop/bop_solution.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "ortools/bop/bop_types.h"
|
||||
#include "ortools/sat/boolean_problem.pb.h"
|
||||
#include "ortools/util/strong_integers.h"
|
||||
|
||||
namespace operations_research {
|
||||
namespace bop {
|
||||
namespace {
|
||||
|
||||
using ::operations_research::sat::LinearBooleanProblem;
|
||||
|
||||
// Tests Bop solutions using a problem with no constraints.
|
||||
// The solution is always feasible, but the cost can vary.
|
||||
TEST(BopSolution, NoConstraints) {
|
||||
const std::string kProblem =
|
||||
"name: \"Test\" "
|
||||
"num_variables: 3 "
|
||||
"var_names: \"x\" "
|
||||
"var_names: \"y\" "
|
||||
"var_names: \"z\" "
|
||||
"objective { " // 4 * (x + 2 * y - z + 3)
|
||||
" literals: 1 coefficients: 1 " // x
|
||||
" literals: 2 coefficients: 2 " // 2 * y
|
||||
" literals: 3 coefficients: -1 " // - z
|
||||
" offset: 3 scaling_factor: 4 "
|
||||
"} ";
|
||||
|
||||
LinearBooleanProblem problem;
|
||||
CHECK(google::protobuf::TextFormat::ParseFromString(kProblem, &problem));
|
||||
|
||||
// Empty solution: all variables are set depending on the coefficient sign.
|
||||
BopSolution solution_001(problem, "NoConstraints");
|
||||
EXPECT_TRUE(solution_001.IsFeasible());
|
||||
EXPECT_EQ(-1, solution_001.GetCost());
|
||||
EXPECT_EQ(4 * (-1 + 3), solution_001.GetScaledCost());
|
||||
|
||||
// Check accessors.
|
||||
EXPECT_EQ(3, solution_001.Size());
|
||||
EXPECT_EQ("NoConstraints", solution_001.name());
|
||||
VariableIndex var(0);
|
||||
const std::vector<bool> kValues = {false, false, true};
|
||||
for (const bool value : solution_001) {
|
||||
EXPECT_EQ(value, solution_001.Value(var));
|
||||
EXPECT_EQ(kValues[var.value()], solution_001.Value(var));
|
||||
++var;
|
||||
}
|
||||
|
||||
// All-true solution.
|
||||
BopSolution solution_111 = solution_001;
|
||||
for (VariableIndex var(0); var < solution_111.Size(); ++var) {
|
||||
solution_111.SetValue(var, true);
|
||||
}
|
||||
|
||||
// Solution_000 should not have changed.
|
||||
EXPECT_TRUE(solution_001.IsFeasible());
|
||||
EXPECT_EQ(-1, solution_001.GetCost());
|
||||
EXPECT_EQ(4 * (-1 + 3), solution_001.GetScaledCost());
|
||||
EXPECT_EQ(solution_001.Size(), solution_111.Size());
|
||||
for (VariableIndex var(0); var < solution_111.Size(); ++var) {
|
||||
EXPECT_EQ(kValues[var.value()], solution_001.Value(var));
|
||||
EXPECT_TRUE(solution_111.Value(var));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(solution_111.IsFeasible());
|
||||
EXPECT_EQ(2, solution_111.GetCost());
|
||||
EXPECT_EQ((2 + 3) * 4, solution_111.GetScaledCost());
|
||||
|
||||
// All false.
|
||||
BopSolution solution_000 = solution_001;
|
||||
solution_000.SetValue(VariableIndex(2), false);
|
||||
|
||||
EXPECT_TRUE(solution_000.IsFeasible());
|
||||
EXPECT_EQ(0, solution_000.GetCost());
|
||||
EXPECT_EQ(3 * 4, solution_000.GetScaledCost());
|
||||
}
|
||||
|
||||
// Tests using a Two-constraints problem. Constraints can be broken
|
||||
// independently. Note that any feasible solution has a cost of 1 (because of
|
||||
// the
|
||||
// first constraint).
|
||||
TEST(BopSolution, TwoConstraints) {
|
||||
const std::string kProblem =
|
||||
"name: \"Test\" "
|
||||
"num_variables: 3 "
|
||||
"var_names: \"x\" "
|
||||
"var_names: \"y\" "
|
||||
"var_names: \"z\" "
|
||||
"constraints { " // x + y == 1
|
||||
" literals: 1 coefficients: 1 "
|
||||
" literals: 2 coefficients: 1 "
|
||||
" lower_bound: 1 "
|
||||
" upper_bound: 1 "
|
||||
" name: \"Ct_1\" "
|
||||
"} "
|
||||
"constraints { " // y + z <= 1
|
||||
" literals: 2 coefficients: 1 "
|
||||
" literals: 3 coefficients: 1 "
|
||||
" upper_bound: 1 "
|
||||
" name: \"Ct_2\" "
|
||||
"} "
|
||||
"objective { " // x + y
|
||||
" literals: 1 coefficients: 1 "
|
||||
" literals: 2 coefficients: 1 "
|
||||
"} ";
|
||||
|
||||
LinearBooleanProblem problem;
|
||||
CHECK(google::protobuf::TextFormat::ParseFromString(kProblem, &problem));
|
||||
|
||||
// Empty solution: all variables are set to false.
|
||||
BopSolution solution_000(problem, "TwoConstraints");
|
||||
EXPECT_FALSE(solution_000.IsFeasible());
|
||||
EXPECT_EQ(0, solution_000.GetCost());
|
||||
EXPECT_EQ(0, solution_000.GetScaledCost());
|
||||
|
||||
// All-true solution.
|
||||
BopSolution solution_111 = solution_000;
|
||||
for (VariableIndex var(0); var < solution_111.Size(); ++var) {
|
||||
solution_111.SetValue(var, true);
|
||||
}
|
||||
EXPECT_FALSE(solution_111.IsFeasible());
|
||||
EXPECT_EQ(2, solution_111.GetCost());
|
||||
EXPECT_EQ(2, solution_111.GetScaledCost());
|
||||
|
||||
// Feasible solution with x true.
|
||||
BopSolution solution_100 = solution_000;
|
||||
solution_100.SetValue(VariableIndex(0), true);
|
||||
EXPECT_TRUE(solution_100.IsFeasible());
|
||||
EXPECT_EQ(1, solution_100.GetCost());
|
||||
EXPECT_EQ(1, solution_100.GetScaledCost());
|
||||
|
||||
// Feasible solution with x and z true.
|
||||
BopSolution solution_101 = solution_100;
|
||||
solution_101.SetValue(VariableIndex(2), true);
|
||||
EXPECT_TRUE(solution_101.IsFeasible());
|
||||
EXPECT_EQ(1, solution_101.GetCost());
|
||||
EXPECT_EQ(1, solution_101.GetScaledCost());
|
||||
|
||||
// Infeasible solution with y and z true.
|
||||
BopSolution solution_two_true = solution_111;
|
||||
solution_two_true.SetValue(VariableIndex(0), false);
|
||||
EXPECT_FALSE(solution_two_true.IsFeasible());
|
||||
EXPECT_EQ(1, solution_two_true.GetCost());
|
||||
EXPECT_EQ(1, solution_two_true.GetScaledCost());
|
||||
|
||||
// Make solution_two_true feasible by swapping x and y values.
|
||||
solution_two_true.SetValue(VariableIndex(0), true);
|
||||
solution_two_true.SetValue(VariableIndex(1), false);
|
||||
EXPECT_TRUE(solution_two_true.IsFeasible());
|
||||
EXPECT_EQ(1, solution_two_true.GetCost());
|
||||
EXPECT_EQ(1, solution_two_true.GetScaledCost());
|
||||
}
|
||||
} // anonymous namespace
|
||||
} // namespace bop
|
||||
} // namespace operations_research
|
||||
Reference in New Issue
Block a user