diff --git a/ortools/glop/entering_variable.h b/ortools/glop/entering_variable.h index a6df2b4ba0..b8604dae1c 100644 --- a/ortools/glop/entering_variable.h +++ b/ortools/glop/entering_variable.h @@ -74,12 +74,14 @@ class EnteringVariable { // Sets the parameters. void SetParameters(const GlopParameters& parameters); + void SetRandom(absl::BitGenRef random) { random_ = random; } + // Stats related functions. std::string StatString() const { return stats_.StatString(); } // Deterministic time used by some of the functions of this class. // - // TODO(user): Be exhausitive and more precise. + // TODO(user): Be exhaustive and more precise. double DeterministicTime() const { return DeterministicTimeForFpOperations(num_operations_); } diff --git a/ortools/glop/parameters.proto b/ortools/glop/parameters.proto index 54ebdf5619..8b2e180e40 100644 --- a/ortools/glop/parameters.proto +++ b/ortools/glop/parameters.proto @@ -24,7 +24,7 @@ package operations_research.glop; option java_package = "com.google.ortools.glop"; option java_multiple_files = true; option csharp_namespace = "Google.OrTools.Glop"; -// next id = 72 +// next id = 73 message GlopParameters { // Supported algorithms for scaling: // EQUILIBRATION - progressive scaling by row and column norms until the @@ -404,6 +404,12 @@ message GlopParameters { // advanced farther than the other. optional int32 random_seed = 43 [default = 1]; + // Whether to use absl::BitGen instead of MTRandom. + // MOE:begin_strip + // Note that in unit tests if this field is not explicitly set it will be + // default to true. MOE:end_strip + optional bool use_absl_random = 72 [default = false]; + // Number of threads in the OMP parallel sections. If left to 1, the code will // not create any OMP threads and will remain single-threaded. optional int32 num_omp_threads = 44 [default = 1]; diff --git a/ortools/glop/pricing.h b/ortools/glop/pricing.h index ad633d9a7e..63a3e21772 100644 --- a/ortools/glop/pricing.h +++ b/ortools/glop/pricing.h @@ -76,6 +76,8 @@ class DynamicMaximum { // Removes the given index from the set of candidates. void Remove(Index position); + void SetRandom(absl::BitGenRef random) { random_ = random; } + // Adds an element to the set of candidate and sets its value. If the element // is already present, this updates its value. The value must be finite. void AddOrUpdate(Index position, Fractional value); diff --git a/ortools/glop/reduced_costs.h b/ortools/glop/reduced_costs.h index aeba9a4d5a..4894c33a1a 100644 --- a/ortools/glop/reduced_costs.h +++ b/ortools/glop/reduced_costs.h @@ -67,6 +67,8 @@ class ReducedCosts { // next call to GetReducedCosts(). bool NeedsBasisRefactorization() const; + void SetRandom(absl::BitGenRef random) { random_ = random; } + // Checks the precision of the entering variable choice now that the direction // is computed. Returns its precise version. This will also trigger a // reduced cost recomputation if it was deemed too imprecise. @@ -307,6 +309,8 @@ class PrimalPrices { // the basis during a primal simplex iterations. ColIndex GetBestEnteringColumn(); + void SetRandom(absl::BitGenRef random) { prices_.SetRandom(random); } + // Similar to the other UpdateBeforeBasisPivot() functions. // // Important: Both the primal norms and reduced costs must have been updated diff --git a/ortools/glop/revised_simplex.cc b/ortools/glop/revised_simplex.cc index 550463c61a..92b9f9c0a0 100644 --- a/ortools/glop/revised_simplex.cc +++ b/ortools/glop/revised_simplex.cc @@ -97,7 +97,9 @@ constexpr const uint64_t kDeterministicSeed = 42; namespace { -bool UseAbslRandom() { return false; } +bool UseAbslRandom(const GlopParameters& parameters) { + return parameters.use_absl_random(); +} } // namespace @@ -108,8 +110,7 @@ RevisedSimplex::RevisedSimplex() variable_name_(), direction_(), error_(), - random_(UseAbslRandom() ? absl::BitGenRef(absl_random_) - : absl::BitGenRef(deterministic_random_)), + random_(absl::BitGenRef(deterministic_random_)), basis_factorization_(&compact_matrix_, &basis_), variables_info_(compact_matrix_), primal_edge_norms_(compact_matrix_, variables_info_, @@ -876,7 +877,7 @@ void RevisedSimplex::UpdateBasis(ColIndex entering_col, RowIndex basis_row, DCHECK(variables_info_.GetIsBasicBitRow().IsSet(leaving_col)); // Make leaving_col leave the basis and update relevant data. - // Note thate the leaving variable value is not necessarily at its exact + // Note that the leaving variable value is not necessarily at its exact // bound, which is like a bound shift. variables_info_.UpdateToNonBasicStatus(leaving_col, leaving_variable_status); DCHECK(leaving_variable_status == VariableStatus::AT_UPPER_BOUND || @@ -3678,10 +3679,21 @@ Fractional RevisedSimplex::ComputeInitialProblemObjectiveValue() const { return objective_scaling_factor_ * (sum + objective_offset_); } +void RevisedSimplex::SetRandom(absl::BitGenRef random) { + random_ = random; + dual_prices_.SetRandom(random_); + entering_variable_.SetRandom(random_); + reduced_costs_.SetRandom(random_); + primal_prices_.SetRandom(random_); +} + void RevisedSimplex::SetParameters(const GlopParameters& parameters) { SCOPED_TIME_STAT(&function_stats_); deterministic_random_.seed(parameters.random_seed()); absl_random_ = absl::BitGen(absl::SeedSeq({parameters.random_seed()})); + SetRandom((UseAbslRandom(parameters) + ? absl::BitGenRef(absl_random_) + : absl::BitGenRef(deterministic_random_))); initial_parameters_ = parameters; parameters_ = parameters; PropagateParameters(); @@ -3911,7 +3923,7 @@ void RevisedSimplex::ComputeBasicVariablesForState( void RevisedSimplex::DisplayRevisedSimplexDebugInfo() { if (VLOG_IS_ON(3)) { - // This function has a complexity in O(num_non_zeros_in_matrix). + variable_name_.resize(num_cols_, ""); DisplayInfoOnVariables(); std::string output = "z = " + StringifyWithFlags(ComputeObjectiveValue()); @@ -3944,10 +3956,11 @@ void RevisedSimplex::DisplayRevisedSimplexDebugInfo() { } } -void RevisedSimplex::DisplayProblem() const { +void RevisedSimplex::DisplayProblem() { // This function has a complexity in O(num_rows * num_cols * // num_non_zeros_in_row). if (VLOG_IS_ON(3)) { + variable_name_.resize(num_cols_, ""); DisplayInfoOnVariables(); std::string output = "min: "; bool has_objective = false; diff --git a/ortools/glop/revised_simplex.h b/ortools/glop/revised_simplex.h index 04f588e3e5..6ca87de09b 100644 --- a/ortools/glop/revised_simplex.h +++ b/ortools/glop/revised_simplex.h @@ -248,6 +248,11 @@ class RevisedSimplex { void SetLogger(SolverLogger* logger) { logger_ = logger; } + // Note: SetParameters() calls SetRandom() on its implementation, so if you + // want to set the parameters and then set the random generator, you should + // call SetRandom() after SetParameters(). + void SetRandom(absl::BitGenRef random); + // Advanced usage. For fast incremental call to the solver, it is better not // to use LinearProgram at all. This api allows to directly modify the // internal data of glop and then call solve. @@ -376,7 +381,7 @@ class RevisedSimplex { void DisplayRevisedSimplexDebugInfo(); // Displays the Linear Programming problem as it was input. - void DisplayProblem() const; + void DisplayProblem(); // Returns the current objective value. This is just the sum of the current // variable values times their current cost.