diff --git a/ortools/glop/BUILD b/ortools/glop/BUILD index e3d4a042ab..e07f91109d 100644 --- a/ortools/glop/BUILD +++ b/ortools/glop/BUILD @@ -15,11 +15,11 @@ cc_library( hdrs = ["pricing.h"], deps = [ "//ortools/base", - "@com_google_absl//absl/random", - "@com_google_absl//absl/random:bit_gen_ref", "//ortools/lp_data:base", "//ortools/util:bitset", "//ortools/util:stats", + "@com_google_absl//absl/random", + "@com_google_absl//absl/random:bit_gen_ref", ], ) @@ -262,6 +262,7 @@ cc_library( "//ortools/lp_data:scattered_vector", "//ortools/util:random_engine", "//ortools/util:stats", + "@com_google_absl//absl/random:bit_gen_ref", ], ) @@ -308,6 +309,7 @@ cc_library( "//ortools/util:bitset", "//ortools/util:random_engine", "//ortools/util:stats", + "@com_google_absl//absl/random:bit_gen_ref", ], ) diff --git a/ortools/glop/entering_variable.cc b/ortools/glop/entering_variable.cc index 5f0c8a8cbf..e97a17a3e6 100644 --- a/ortools/glop/entering_variable.cc +++ b/ortools/glop/entering_variable.cc @@ -23,7 +23,7 @@ namespace operations_research { namespace glop { EnteringVariable::EnteringVariable(const VariablesInfo& variables_info, - random_engine_t* random, + absl::BitGenRef random, ReducedCosts* reduced_costs, PrimalEdgeNorms* primal_edge_norms) : variables_info_(variables_info), @@ -256,7 +256,7 @@ Status EnteringVariable::DualChooseEnteringColumn( equivalent_entering_choices_.push_back(*entering_col); *entering_col = equivalent_entering_choices_[std::uniform_int_distribution( - 0, equivalent_entering_choices_.size() - 1)(*random_)]; + 0, equivalent_entering_choices_.size() - 1)(random_)]; IF_STATS_ENABLED( stats_.num_perfect_ties.Add(equivalent_entering_choices_.size())); } @@ -502,7 +502,7 @@ void EnteringVariable::NormalizedChooseEnteringColumn(ColIndex* entering_col) { equivalent_entering_choices_.push_back(*entering_col); *entering_col = equivalent_entering_choices_[std::uniform_int_distribution( - 0, equivalent_entering_choices_.size() - 1)(*random_)]; + 0, equivalent_entering_choices_.size() - 1)(random_)]; IF_STATS_ENABLED( stats_.num_perfect_ties.Add(equivalent_entering_choices_.size())); } diff --git a/ortools/glop/entering_variable.h b/ortools/glop/entering_variable.h index e0fe663217..3ae4f0ccc2 100644 --- a/ortools/glop/entering_variable.h +++ b/ortools/glop/entering_variable.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_GLOP_ENTERING_VARIABLE_H_ #define OR_TOOLS_GLOP_ENTERING_VARIABLE_H_ +#include "absl/random/bit_gen_ref.h" #include "ortools/glop/basis_representation.h" #include "ortools/glop/parameters.pb.h" #include "ortools/glop/primal_edge_norms.h" @@ -24,7 +25,6 @@ #include "ortools/lp_data/lp_data.h" #include "ortools/lp_data/lp_types.h" #include "ortools/util/bitset.h" -#include "ortools/util/random_engine.h" #include "ortools/util/stats.h" #if !SWIG @@ -53,7 +53,7 @@ namespace glop { class EnteringVariable { public: // Takes references to the linear program data we need. - EnteringVariable(const VariablesInfo& variables_info, random_engine_t* random, + EnteringVariable(const VariablesInfo& variables_info, absl::BitGenRef random, ReducedCosts* reduced_costs, PrimalEdgeNorms* primal_edge_norms); @@ -118,7 +118,7 @@ class EnteringVariable { // Problem data that should be updated from outside. const VariablesInfo& variables_info_; - random_engine_t* random_; + absl::BitGenRef random_; ReducedCosts* reduced_costs_; PrimalEdgeNorms* primal_edge_norms_; diff --git a/ortools/glop/reduced_costs.cc b/ortools/glop/reduced_costs.cc index be782ace2f..4a6312647b 100644 --- a/ortools/glop/reduced_costs.cc +++ b/ortools/glop/reduced_costs.cc @@ -29,7 +29,7 @@ ReducedCosts::ReducedCosts(const CompactSparseMatrix& matrix, const RowToColMapping& basis, const VariablesInfo& variables_info, const BasisFactorization& basis_factorization, - random_engine_t* random) + absl::BitGenRef random) : matrix_(matrix), objective_(objective), basis_(basis), @@ -272,7 +272,7 @@ void ReducedCosts::PerturbCosts() { for (ColIndex col(0); col < structural_size; ++col) { const Fractional objective = objective_[col]; const Fractional magnitude = - (1.0 + std::uniform_real_distribution()(*random_)) * + (1.0 + std::uniform_real_distribution()(random_)) * (parameters_.relative_cost_perturbation() * std::abs(objective) + parameters_.relative_max_cost_perturbation() * max_cost_magnitude); DCHECK_GE(magnitude, 0.0); diff --git a/ortools/glop/reduced_costs.h b/ortools/glop/reduced_costs.h index 5e6f7f33a4..6a721e47ab 100644 --- a/ortools/glop/reduced_costs.h +++ b/ortools/glop/reduced_costs.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_GLOP_REDUCED_COSTS_H_ #define OR_TOOLS_GLOP_REDUCED_COSTS_H_ +#include "absl/random/bit_gen_ref.h" #include "ortools/glop/basis_representation.h" #include "ortools/glop/parameters.pb.h" #include "ortools/glop/primal_edge_norms.h" @@ -23,7 +24,6 @@ #include "ortools/lp_data/lp_data.h" #include "ortools/lp_data/lp_types.h" #include "ortools/lp_data/scattered_vector.h" -#include "ortools/util/random_engine.h" #include "ortools/util/stats.h" namespace operations_research { @@ -52,7 +52,7 @@ class ReducedCosts { const RowToColMapping& basis, const VariablesInfo& variables_info, const BasisFactorization& basis_factorization, - random_engine_t* random); + absl::BitGenRef random); // If this is true, then the caller must re-factorize the basis before the // next call to GetReducedCosts(). @@ -255,7 +255,7 @@ class ReducedCosts { const RowToColMapping& basis_; const VariablesInfo& variables_info_; const BasisFactorization& basis_factorization_; - random_engine_t* random_; + absl::BitGenRef random_; // Internal data. GlopParameters parameters_; diff --git a/ortools/glop/revised_simplex.cc b/ortools/glop/revised_simplex.cc index 4270f850b0..30faa6fabe 100644 --- a/ortools/glop/revised_simplex.cc +++ b/ortools/glop/revised_simplex.cc @@ -86,6 +86,8 @@ RevisedSimplex::RevisedSimplex() variable_name_(), direction_(), error_(), + deterministic_random_(kDeterministicSeed), + random_(deterministic_random_), basis_factorization_(&compact_matrix_, &basis_), variables_info_(compact_matrix_), dual_edge_norms_(basis_factorization_), @@ -97,8 +99,8 @@ RevisedSimplex::RevisedSimplex() update_row_(compact_matrix_, transposed_matrix_, variables_info_, basis_, basis_factorization_), reduced_costs_(compact_matrix_, objective_, basis_, variables_info_, - basis_factorization_, &random_), - entering_variable_(variables_info_, &random_, &reduced_costs_, + basis_factorization_, random_), + entering_variable_(variables_info_, random_, &reduced_costs_, &primal_edge_norms_), num_iterations_(0), num_feasibility_iterations_(0), @@ -112,8 +114,7 @@ RevisedSimplex::RevisedSimplex() function_stats_("SimplexFunctionStats"), parameters_(), test_lu_(), - feasibility_phase_(true), - random_(kDeterministicSeed) { + feasibility_phase_(true) { SetParameters(parameters_); } @@ -3075,7 +3076,8 @@ Fractional RevisedSimplex::ComputeInitialProblemObjectiveValue() const { void RevisedSimplex::SetParameters(const GlopParameters& parameters) { SCOPED_TIME_STAT(&function_stats_); - random_.seed(parameters.random_seed()); + deterministic_random_.seed(parameters.random_seed()); + initial_parameters_ = parameters; parameters_ = parameters; PropagateParameters(); diff --git a/ortools/glop/revised_simplex.h b/ortools/glop/revised_simplex.h index 691f82cc23..3d85d76eb2 100644 --- a/ortools/glop/revised_simplex.h +++ b/ortools/glop/revised_simplex.h @@ -95,6 +95,7 @@ #include #include +#include "absl/random/bit_gen_ref.h" #include "ortools/base/integral_types.h" #include "ortools/base/macros.h" #include "ortools/glop/basis_representation.h" @@ -636,6 +637,15 @@ class RevisedSimplex { // Used to compute the error 'b - A.x' or 'a - B.d'. DenseColumn error_; + // A random number generator. In test we use absl_random_ to have a + // non-deterministic behavior and avoid client depending on a golden optimal + // solution which prevent us from easily changing the solver. + random_engine_t deterministic_random_; +#ifndef NDEBUG + absl::BitGen absl_random_; +#endif + absl::BitGenRef random_; + // Representation of matrix B using eta matrices and LU decomposition. BasisFactorization basis_factorization_; @@ -760,9 +770,6 @@ class RevisedSimplex { // anyway. std::vector equivalent_leaving_choices_; - // A random number generator. - random_engine_t random_; - // This is used by Polish(). DenseRow integrality_scale_;