示例#1
0
 /// <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));
   }
 }
示例#2
0
    /// <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;
    }
示例#3
0
 /// <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);
 }
示例#4
0
    /// <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;
    }
示例#5
0
    /// <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;
    }
示例#6
0
 /// <summary>
 /// Changes the current constraint A*X &lt;= B into (A + m*aa)*X &lt;= B + m*bb,
 /// where "cc" is the constraint aa*X &lt;= 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;
 }
示例#7
0
 public void SetCoefficient(IVariable/*!*/ dimension, Rational coefficient) {
   Contract.Requires(dimension != null);
   coefficients[dimension] = coefficient;
 }
示例#8
0
 /// <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();
 }