/// <summary> /// Returns a rational whose numerator and denominator, resepctively, are the Gcd /// of the numerators and denominators of r and s. If one of r and s is 0, the absolute /// value of the other is returned. If both are 0, 1 is returned. /// </summary> public static Rational Gcd(Rational r, Rational s) { Contract.Ensures(Contract.Result<Rational>().IsPositive); if (r.IsZero) { if (s.IsZero) { return ONE; } else { return s.Abs(); } } else if (s.IsZero) { return r.Abs(); } else { return new Rational(r.Numerator.Gcd(s.Numerator), r.Denominator.Gcd(s.Denominator)); } }
/// <summary> /// If the last operation applied to the tableau was: /// undo = Pivot(i,j); /// then UnPivot(i, j, undo) undoes the pivot operation. /// Note: This operation is not supported for any call to Pivot before constructionDone /// is set to true. /// </summary> /// <param name="r"></param> /// <param name="c"></param> /// <param name="undo"></param> void UnPivot(int r, int c, Rational[]/*!*/ undo) { Contract.Requires(undo != null); Contract.Assert(0 <= r && r < rows); Contract.Assert(0 <= c && c < columns - 1); Contract.Assert(m[r, c].HasValue(1)); Contract.Assert(undo.Length == rows + 1); // add a multiple of the pivot row to all other rows for (int i = 0; i < rows; i++) { if (i != r) { Rational q = undo[i]; if (q.IsNonZero) { for (int j = 0; j < columns; j++) { m[i, j] += q * m[r, j]; } } } } // scale the pivot row Rational p = undo[r]; for (int j = 0; j < columns; j++) { m[r, j] *= p; } // update basis information int prevCol = undo[rows].AsInteger; Contract.Assert(prevCol != -1); basisColumns[r] = prevCol; inBasis[c] = -1; inBasis[prevCol] = r; }
/// <summary> /// This method is to be thought of as being part of the FrameElement object's construction process. /// Assumes "dimension" is not already in FrameElement. /// </summary> /// <param name="dimension"></param> /// <param name="value"></param> public void AddCoordinate(IVariable/*!*/ dimension, Rational value) { Contract.Requires(dimension != null); terms.Add(dimension, value); }
/// <summary> /// Applies the Pivot Operation on row "r" and column "c". /// /// This method can be called when !constructionDone, that is, at a time when not all basis /// columns have been set up (indicated by -1 in basisColumns). This method helps set up /// those basis columns. /// /// The return value is an undo record that can be used with UnPivot. /// </summary> /// <param name="r"></param> /// <param name="c"></param> public Rational[]/*!*/ Pivot(int r, int c) { Contract.Ensures(Contract.Result<Rational[]>() != null); Contract.Assert(0 <= r && r < rows); Contract.Assert(0 <= c && c < columns - 1); Contract.Assert(m[r, c].IsNonZero); Contract.Assert(inBasis[c] == -1); // follows from invariant and m[r,c] != 0 Contract.Assert(basisColumns[r] != rhsColumn); // follows from invariant and m[r,c] != 0 Rational[] undo = new Rational[rows + 1]; for (int i = 0; i < rows; i++) { undo[i] = m[i, c]; } // scale the pivot row Rational q = m[r, c]; if (q != Rational.ONE) { for (int j = 0; j < columns; j++) { m[r, j] /= q; } } // subtract a multiple of the pivot row from all other rows for (int i = 0; i < rows; i++) { if (i != r) { q = m[i, c]; if (q.IsNonZero) { for (int j = 0; j < columns; j++) { m[i, j] -= q * m[r, j]; } } } } // update basis information int prevCol = basisColumns[r]; undo[rows] = Rational.FromInt(prevCol); basisColumns[r] = c; if (prevCol != -1) { inBasis[prevCol] = -1; } inBasis[c] = r; return undo; }
/// <summary> /// Try to reduce the magnitude of the coefficients used. /// Has a side effect on the coefficients, but leaves the meaning of the linear constraint /// unchanged. /// </summary> public void Normalize() { // compute the gcd of the numerators and the gcd of the denominators Rational gcd = rhs; foreach (Rational r in coefficients.Values) { gcd = Rational.Gcd(gcd, r); } // Change all coefficients, to divide their numerators with gcdNum and to // divide their denominators with gcdDen. Hashtable /*IVariable->Rational*/ newCoefficients = new Hashtable /*IVariable->Rational*/ (coefficients.Count); foreach (DictionaryEntry /*IVarianble->Rational*/ e in coefficients) { Rational r = (Rational)(cce.NonNull(e.Value)); if (r.IsNonZero) { newCoefficients.Add(e.Key, Rational.FromBignums(r.Numerator / gcd.Numerator, r.Denominator / gcd.Denominator)); } else { newCoefficients.Add(e.Key, r); } } coefficients = newCoefficients; rhs = rhs.IsNonZero ? Rational.FromBignums(rhs.Numerator / gcd.Numerator, rhs.Denominator / gcd.Denominator) : rhs; }
/// <summary> /// Changes the current constraint A*X <= B into (A + m*aa)*X <= B + m*bb, /// where "cc" is the constraint aa*X <= bb. /// </summary> /// <param name="m"></param> /// <param name="cc"></param> /// <returns></returns> public void AddMultiple(Rational m, LinearConstraint/*!*/ cc) { Contract.Requires(cc != null); foreach (DictionaryEntry /*IVariable->Rational*/ entry in cc.coefficients) { IVariable dim = (IVariable)entry.Key; Rational d = m * (Rational)(cce.NonNull(entry.Value)); if (d.IsNonZero) { object prev = coefficients[dim]; if (prev == null) { coefficients[dim] = d; } else { coefficients[dim] = (Rational)prev + d; } } } rhs += m * cc.rhs; }
public void SetCoefficient(IVariable/*!*/ dimension, Rational coefficient) { Contract.Requires(dimension != null); coefficients[dimension] = coefficient; }
/// <summary> /// Returns an expression that denotes sum + r*x. /// If sum==null, drops the "sum +". /// If x==null, drops the "*x". /// if x!=null and r==1, drops the "r*". /// </summary> /// <param name="factory"></param> /// <param name="sum"></param> /// <param name="r"></param> /// <param name="x"></param> static IExpr/*!*/ AddTerm(ILinearExprFactory/*!*/ factory, /*MayBeNull*/ IExpr sum, Rational r, /*MayBeNull*/ IVariable x) { Contract.Requires(factory != null); Contract.Ensures(Contract.Result<IExpr>() != null); IExpr/*!*/ product = factory.Term(r, x); Contract.Assert(product != null); if (sum == null) { return product; } else { return factory.Add(sum, product); } }
IExpr ILinearExprFactory.Term(Rational r, IVariable var) { Contract.Ensures(Contract.Result<IExpr>() != null); throw new System.NotImplementedException(); }