protected override bool Update(NumericVariable v) { return(v.RestrictRange(-(v == _variable1 ? _variable2 : _variable1).Value)); }
//public SumIs0Constraint Plus(DoubleHolder d) { // return new SumIs0Constraint(_plus.Concat(new[] { d })); //} protected override bool Update(NumericVariable v) { bool changed = false; // The following propagation uses these ideas: // For each variable v, take the sum S of all OTHER Lo values. A high value that is higher // than -S will never cancel S to zero, let alone sums that are greater than S. Hence, // v.Hi can be restricted to <= -S. // Likewise, v.Lo can be restricted to >= -S where S is the sum of all other Hi values. // O(n^2) algorithm - a O(n) algorithm is possible ... later double loSum = 0; // OnceExcluded is necessary for a constraint like X + X + Y = 0: When we already know // that X = [100..100] and Y = [-200..-200], this should succeed. However, when during // Upgrade(X) we skip both X's (via w != v), the sum will not be 100-200 == 100, but // -200; and hence // X will then be restricted to [200..+inf], which, together with the previously known // value X = 100 will erroneously imply that there is no solution for X. // By the way, when in X + X + Y = 0, we have X = [-inf...+inf] and Y = [-200..-200] at // the beginning, we will NOT conclude that X = [100..100] - that would be equation // solving, which we do not support at this level. bool onceExcluded = false; foreach (var w in _inputVariables) { if (onceExcluded || w != v) { double wLo = w.Value.Lo; if (double.IsNegativeInfinity(wLo)) { // Nothing can be said about the sum of lows - cancel this computation; goto SKIP_LO; } loSum += wLo; } else { onceExcluded = true; } } changed |= v.RestrictRange(double.NegativeInfinity, -loSum); SKIP_LO: double hiSum = 0; onceExcluded = false; foreach (var w in _inputVariables) { if (onceExcluded || w != v) { double wHi = w.Value.Hi; if (double.IsPositiveInfinity(wHi)) { // Nothing can be said about the sum of his - cancel this computation; goto SKIP_HI; } hiSum += wHi; } else { onceExcluded = true; } } changed |= v.RestrictRange(-hiSum, double.PositiveInfinity); SKIP_HI: return(changed); }
protected override bool Update(NumericVariable v) { return(v.RestrictRange(_range)); }