@@ -218,26 +218,32 @@ void LinearIncrementalEvaluator::ComputeInitialActivities(
218
218
num_false_enforcement_.assign (num_constraints_, 0 );
219
219
220
220
// Update these numbers for all columns.
221
- for (int var = 0 ; var < columns_.size (); ++var) {
221
+ const int num_vars = columns_.size ();
222
+ for (int var = 0 ; var < num_vars; ++var) {
222
223
const SpanData& data = columns_[var];
223
224
const int64_t value = solution[var];
224
225
225
- int i = data.start ;
226
- for (int k = 0 ; k < data.num_pos_literal ; ++k, ++i) {
227
- const int c = ct_buffer_[i];
228
- if (value == 0 ) num_false_enforcement_[c]++;
226
+ if (value == 0 && data.num_pos_literal > 0 ) {
227
+ const int * ct_indices = &ct_buffer_[data.start ];
228
+ for (int k = 0 ; k < data.num_pos_literal ; ++k) {
229
+ num_false_enforcement_[ct_indices[k]]++;
230
+ }
229
231
}
230
- for (int k = 0 ; k < data.num_neg_literal ; ++k, ++i) {
231
- const int c = ct_buffer_[i];
232
- if (value == 1 ) num_false_enforcement_[c]++;
232
+
233
+ if (value == 1 && data.num_neg_literal > 0 ) {
234
+ const int * ct_indices = &ct_buffer_[data.start + data.num_pos_literal ];
235
+ for (int k = 0 ; k < data.num_neg_literal ; ++k) {
236
+ num_false_enforcement_[ct_indices[k]]++;
237
+ }
233
238
}
234
239
235
- if (value == 0 ) continue ;
236
- int j = data.linear_start ;
237
- for (int k = 0 ; k < data.num_linear_entries ; ++k, ++i, ++j) {
238
- const int c = ct_buffer_[i];
239
- const int64_t coeff = coeff_buffer_[j];
240
- activities_[c] += coeff * value;
240
+ if (value != 0 && data.num_linear_entries > 0 ) {
241
+ const int * ct_indices =
242
+ &ct_buffer_[data.start + data.num_pos_literal + data.num_neg_literal ];
243
+ const int64_t * coeffs = &coeff_buffer_[data.linear_start ];
244
+ for (int k = 0 ; k < data.num_linear_entries ; ++k) {
245
+ activities_[ct_indices[k]] += coeffs[k] * value;
246
+ }
241
247
}
242
248
}
243
249
@@ -249,9 +255,15 @@ void LinearIncrementalEvaluator::ComputeInitialActivities(
249
255
}
250
256
251
257
void LinearIncrementalEvaluator::ClearAffectedVariables () {
252
- in_last_affected_variables_.resize (columns_.size (), false );
253
- for (const int var : last_affected_variables_) {
254
- in_last_affected_variables_[var] = false ;
258
+ if (10 * last_affected_variables_.size () < columns_.size ()) {
259
+ // Sparse.
260
+ in_last_affected_variables_.resize (columns_.size (), false );
261
+ for (const int var : last_affected_variables_) {
262
+ in_last_affected_variables_[var] = false ;
263
+ }
264
+ } else {
265
+ // Dense.
266
+ in_last_affected_variables_.assign (columns_.size (), false );
255
267
}
256
268
last_affected_variables_.clear ();
257
269
DCHECK (std::all_of (in_last_affected_variables_.begin (),
@@ -315,19 +327,18 @@ void LinearIncrementalEvaluator::UpdateScoreOnWeightUpdate(
315
327
};
316
328
317
329
const int64_t old_distance = distances_[c];
330
+ const int64_t activity = activities_[c];
318
331
for (int k = 0 ; k < data.num_linear_entries ; ++k) {
319
332
const int var = row_vars[k];
320
333
const int64_t coeff = row_coeffs[k];
321
- const int64_t new_distance =
322
- violation (activities_[c] + coeff * jump_deltas[var]);
334
+ const int64_t diff =
335
+ violation (activity + coeff * jump_deltas[var]) - old_distance ;
323
336
if (!in_last_affected_variables_[var]) {
324
- var_to_score_change[var] =
325
- static_cast <double >(new_distance - old_distance);
337
+ var_to_score_change[var] = static_cast <double >(diff);
326
338
in_last_affected_variables_[var] = true ;
327
339
last_affected_variables_.push_back (var);
328
340
} else {
329
- var_to_score_change[var] +=
330
- static_cast <double >(new_distance - old_distance);
341
+ var_to_score_change[var] += static_cast <double >(diff);
331
342
}
332
343
}
333
344
}
@@ -1842,65 +1853,55 @@ bool LsEvaluator::ReduceObjectiveBounds(int64_t lb, int64_t ub) {
1842
1853
return false ;
1843
1854
}
1844
1855
1845
- void LsEvaluator::OverwriteCurrentSolution (absl::Span<const int64_t > solution) {
1846
- current_solution_.assign (solution.begin (), solution.end ());
1847
- }
1848
-
1849
- void LsEvaluator::ComputeAllViolations () {
1856
+ void LsEvaluator::ComputeAllViolations (absl::Span<const int64_t > solution) {
1850
1857
// Linear constraints.
1851
- linear_evaluator_.ComputeInitialActivities (current_solution_ );
1858
+ linear_evaluator_.ComputeInitialActivities (solution );
1852
1859
1853
1860
// Generic constraints.
1854
1861
for (const auto & ct : constraints_) {
1855
- ct->InitializeViolation (current_solution_ );
1862
+ ct->InitializeViolation (solution );
1856
1863
}
1857
1864
1858
1865
RecomputeViolatedList (/* linear_only=*/ false );
1859
1866
}
1860
1867
1861
- void LsEvaluator::UpdateAllNonLinearViolations () {
1868
+ void LsEvaluator::ComputeAllNonLinearViolations (
1869
+ absl::Span<const int64_t > solution) {
1862
1870
// Generic constraints.
1863
1871
for (const auto & ct : constraints_) {
1864
- ct->InitializeViolation (current_solution_ );
1872
+ ct->InitializeViolation (solution );
1865
1873
}
1866
1874
}
1867
1875
1868
- void LsEvaluator::UpdateNonLinearViolations (int var, int64_t new_value) {
1869
- const int64_t old_value = current_solution_[var];
1870
- if (old_value == new_value) return ;
1871
-
1872
- current_solution_[var] = new_value;
1876
+ void LsEvaluator::UpdateNonLinearViolations (
1877
+ int var, int64_t old_value, absl::Span<const int64_t > new_solution) {
1873
1878
for (const int general_ct_index : var_to_constraints_[var]) {
1874
1879
const int c = general_ct_index + linear_evaluator_.num_constraints ();
1875
1880
const int64_t v0 = constraints_[general_ct_index]->violation ();
1876
- constraints_[general_ct_index]->PerformMove (var, old_value,
1877
- current_solution_);
1881
+ constraints_[general_ct_index]->PerformMove (var, old_value, new_solution);
1878
1882
const int64_t violation_delta =
1879
1883
constraints_[general_ct_index]->violation () - v0;
1880
1884
if (violation_delta != 0 ) {
1881
1885
last_update_violation_changes_.push_back (c);
1882
1886
}
1883
1887
}
1884
- current_solution_[var] = old_value;
1885
1888
}
1886
1889
1887
- void LsEvaluator::UpdateLinearScores (int var, int64_t value,
1890
+ void LsEvaluator::UpdateLinearScores (int var, int64_t old_value,
1891
+ int64_t new_value,
1888
1892
absl::Span<const double > weights,
1889
1893
absl::Span<const int64_t > jump_deltas,
1890
1894
absl::Span<double > jump_scores) {
1891
1895
DCHECK (RefIsPositive (var));
1892
- const int64_t old_value = current_solution_[var];
1893
- if (old_value == value) return ;
1896
+ if (old_value == new_value) return ;
1894
1897
last_update_violation_changes_.clear ();
1895
1898
linear_evaluator_.ClearAffectedVariables ();
1896
- linear_evaluator_.UpdateVariableAndScores (var, value - old_value, weights,
1899
+ linear_evaluator_.UpdateVariableAndScores (var, new_value - old_value, weights,
1897
1900
jump_deltas, jump_scores,
1898
1901
&last_update_violation_changes_);
1899
1902
}
1900
1903
1901
- void LsEvaluator::UpdateVariableValue (int var, int64_t new_value) {
1902
- current_solution_[var] = new_value;
1903
-
1904
+ void LsEvaluator::UpdateViolatedList () {
1904
1905
// Maintain the list of violated constraints.
1905
1906
dtime_ += 1e-8 * last_update_violation_changes_.size ();
1906
1907
for (const int c : last_update_violation_changes_) {
@@ -1977,44 +1978,42 @@ bool LsEvaluator::IsViolated(int c) const {
1977
1978
1978
1979
double LsEvaluator::WeightedViolation (absl::Span<const double > weights) const {
1979
1980
DCHECK_EQ (weights.size (), NumEvaluatorConstraints ());
1980
- double violations = linear_evaluator_.WeightedViolation (weights);
1981
+ double result = linear_evaluator_.WeightedViolation (weights);
1981
1982
1982
1983
const int num_linear_constraints = linear_evaluator_.num_constraints ();
1983
1984
for (int c = 0 ; c < constraints_.size (); ++c) {
1984
- violations += static_cast <double >(constraints_[c]->violation ()) *
1985
- weights[num_linear_constraints + c];
1985
+ result += static_cast <double >(constraints_[c]->violation ()) *
1986
+ weights[num_linear_constraints + c];
1986
1987
}
1987
- return violations ;
1988
+ return result ;
1988
1989
}
1989
1990
1990
- double LsEvaluator::WeightedNonLinearViolationDelta (
1991
- absl::Span<const double > weights, int var, int64_t delta) const {
1992
- const int64_t old_value = current_solution_[var];
1993
- double violation_delta = 0 ;
1994
- // We change the mutable solution here, are restore it after the evaluation.
1995
- current_solution_[var] += delta;
1991
+ double LsEvaluator::WeightedViolationDelta (
1992
+ bool linear_only, absl::Span<const double > weights, int var, int64_t delta,
1993
+ absl::Span<int64_t > mutable_solution) const {
1994
+ double result = linear_evaluator_.WeightedViolationDelta (weights, var, delta);
1995
+ if (linear_only) return result;
1996
+
1997
+ // We change the mutable solution here, and restore it after the evaluation.
1998
+ const int64_t old_value = mutable_solution[var];
1999
+ mutable_solution[var] += delta;
2000
+
1996
2001
const int num_linear_constraints = linear_evaluator_.num_constraints ();
1997
2002
for (const int ct_index : var_to_constraints_[var]) {
1998
2003
// We assume linear time delta computation in number of variables.
1999
2004
// TODO(user): refine on a per constraint basis.
2000
2005
dtime_ += 1e-8 * static_cast <double >(constraint_to_vars_[ct_index].size ());
2001
2006
2002
2007
DCHECK_LT (ct_index, constraints_.size ());
2003
- const int64_t delta = constraints_[ct_index]->ViolationDelta (
2004
- var, old_value, current_solution_ );
2005
- violation_delta +=
2006
- static_cast < double >(delta) * weights[ct_index + num_linear_constraints];
2008
+ const int64_t ct_delta = constraints_[ct_index]->ViolationDelta (
2009
+ var, old_value, mutable_solution );
2010
+ result += static_cast < double >(ct_delta) *
2011
+ weights[ct_index + num_linear_constraints];
2007
2012
}
2008
- // Restore.
2009
- current_solution_[var] -= delta;
2010
- return violation_delta;
2011
- }
2012
2013
2013
- double LsEvaluator::WeightedViolationDelta (absl::Span<const double > weights,
2014
- int var, int64_t delta) const {
2015
- DCHECK_LT (var, current_solution_.size ());
2016
- return linear_evaluator_.WeightedViolationDelta (weights, var, delta) +
2017
- WeightedNonLinearViolationDelta (weights, var, delta);
2014
+ // Restore.
2015
+ mutable_solution[var] = old_value;
2016
+ return result;
2018
2017
}
2019
2018
2020
2019
bool LsEvaluator::VariableOnlyInLinearConstraintWithConvexViolationChange (
0 commit comments