/// <summary> /// Add a term c*v to this expression. If the expression already /// contains a term involving v, add c to the existing coefficient. /// If the new coefficient is approximately 0, delete v. /// </summary> public /*sealed*/ ClLinearExpression AddVariable(ClAbstractVariable v, double c) { // body largely duplicated below if (Trace) { FnEnterPrint(string.Format("AddVariable: {0}, {1}", v, c)); } ClDouble coeff = (ClDouble)_terms[v]; if (coeff != null) { double new_coefficient = coeff.Value + c; if (Cl.Approx(new_coefficient, 0.0)) { _terms.Remove(v); } else { coeff.Value = new_coefficient; } } else { if (!Cl.Approx(c, 0.0)) { _terms.Add(v, new ClDouble(c)); } } return(this); }
public override string ToString() { String s = ""; IDictionaryEnumerator e = _terms.GetEnumerator(); if (!Approx(_constant.Value, 0.0) || _terms.Count == 0) { s += _constant.ToString(); } else { if (_terms.Count == 0) { return(s); } e.MoveNext(); // go to first element ClAbstractVariable clv = (ClAbstractVariable)e.Key; ClDouble coeff = _terms[clv]; s += string.Format("{0}*{1}", coeff, clv); } while (e.MoveNext()) { ClAbstractVariable clv = (ClAbstractVariable)e.Key; ClDouble coeff = _terms[clv]; s += string.Format(" + {0}*{1}", coeff, clv); } return(s); }
/// <summary> /// Add a term c*v to this expression. If the expression already /// contains a term involving v, add c to the existing coefficient. /// If the new coefficient is approximately 0, delete v. Notify the /// solver if v appears or disappears from this expression. /// </summary> public ClLinearExpression AddVariable(ClAbstractVariable v, double c, ClAbstractVariable subject, ClTableau solver) { ClDouble coeff = _terms[v]; if (coeff != null) { double newCoefficient = coeff.Value + c; if (Approx(newCoefficient, 0.0)) { solver.NoteRemovedVariable(v, subject); _terms.Remove(v); } else { coeff.Value = newCoefficient; } } else { if (!Approx(c, 0.0)) { _terms.Add(v, new ClDouble(c)); solver.NoteAddedVariable(v, subject); } } return(this); }
public ClLinearExpression(ClAbstractVariable clv, double value = 1, double constant = 0) { _constant = new ClDouble(constant); _terms = new Dictionary <ClAbstractVariable, ClDouble>(); if (clv != null) { _terms.Add(clv, new ClDouble(value)); } }
/// <summary> /// For use by the clone method. /// </summary> protected ClLinearExpression(ClDouble constant, Dictionary <ClAbstractVariable, ClDouble> terms) { _constant = constant.Clone(); _terms = new Dictionary <ClAbstractVariable, ClDouble>(); // need to unalias the ClDouble-s that we clone (do a deep clone) foreach (var clv in terms.Keys) { _terms.Add(clv, (terms[clv]).Clone()); } }
public ClLinearExpression MultiplyMe(double x) { _constant.Value = _constant.Value * x; foreach (ClAbstractVariable clv in _terms.Keys) { ClDouble cld = (ClDouble)_terms[clv]; cld.Value = cld.Value * x; } return(this); }
/// <summary> /// This linear expression currently represents the equation self=0. Destructively modify it so /// that subject=self represents an equivalent equation. /// /// Precondition: subject must be one of the variables in this expression. /// NOTES /// Suppose this expression is /// c + a*subject + a1*v1 + ... + an*vn /// representing /// c + a*subject + a1*v1 + ... + an*vn = 0 /// The modified expression will be /// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn /// representing /// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn /// /// Note that the term involving subject has been dropped. /// Returns the reciprocal, so changeSubject can use it, too /// </summary> public double NewSubject(ClAbstractVariable subject) { ClDouble coeff = _terms[subject]; _terms.Remove(subject); double reciprocal = 1.0 / coeff.Value; MultiplyMe(-reciprocal); return(reciprocal); }
public ClLinearExpression(ClAbstractVariable clv, double value, double constant) { if (Cl.GC) { Console.Error.WriteLine("new ClLinearExpression"); } _constant = new ClDouble(constant); _terms = new Hashtable(1); if (clv != null) _terms.Add(clv, new ClDouble(value)); }
/// <summary> /// This linear expression currently represents the equation /// oldSubject=self. Destructively modify it so that it represents /// the equation newSubject=self. /// /// Precondition: newSubject currently has a nonzero coefficient in /// this expression. /// /// NOTES /// Suppose this expression is c + a*newSubject + a1*v1 + ... + an*vn. /// /// Then the current equation is /// oldSubject = c + a*newSubject + a1*v1 + ... + an*vn. /// The new equation will be /// newSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn. /// Note that the term involving newSubject has been dropped. /// </summary> public /*sealed*/ void ChangeSubject(ClAbstractVariable old_subject, ClAbstractVariable new_subject) { ClDouble cld = (ClDouble)_terms[old_subject]; if (cld != null) { cld.Value = NewSubject(new_subject); } else { _terms.Add(old_subject, new ClDouble(NewSubject(new_subject))); } }
/// <summary> /// Return the coefficient corresponding to variable var, i.e., /// the 'ci' corresponding to the 'vi' that var is: /// v1*c1 + v2*c2 + .. + vn*cn + c /// </summary> public double CoefficientFor(ClAbstractVariable var) { ClDouble coeff = _terms[var]; if (coeff != null) { return(coeff.Value); } else { return(0.0); } }
/// <summary> /// Replace var with a symbolic expression expr that is equal to it. /// If a variable has been added to this expression that wasn't there /// before, or if a variable has been dropped from this expression /// because it now has a coefficient of 0, inform the solver. /// PRECONDITIONS: /// var occurs with a non-zero coefficient in this expression. /// </summary> public /*sealed*/ void SubstituteOut(ClAbstractVariable var, ClLinearExpression expr, ClAbstractVariable subject, ClTableau solver) { if (Trace) { FnEnterPrint(string.Format("CLE:SubstituteOut: {0}, {1}, {2}, ...", var, expr, subject)); } if (Trace) { TracePrint("this = " + this); } double multiplier = ((ClDouble)_terms[var]).Value; _terms.Remove(var); IncrementConstant(multiplier * expr.Constant); foreach (ClAbstractVariable clv in expr.Terms.Keys) { double coeff = ((ClDouble)expr.Terms[clv]).Value; ClDouble d_old_coeff = (ClDouble)_terms[clv]; if (d_old_coeff != null) { double old_coeff = d_old_coeff.Value; double newCoeff = old_coeff + multiplier * coeff; if (Cl.Approx(newCoeff, 0.0)) { solver.NoteRemovedVariable(clv, subject); _terms.Remove(clv); } else { d_old_coeff.Value = newCoeff; } } else { // did not have that variable already _terms.Add(clv, new ClDouble(multiplier * coeff)); solver.NoteAddedVariable(clv, subject); } } if (Trace) { TracePrint("Now this is " + this); } }
public ClLinearExpression(ClAbstractVariable clv, double value, double constant) { if (Cl.GC) { Console.Error.WriteLine("new ClLinearExpression"); } _constant = new ClDouble(constant); _terms = new Hashtable(1); if (clv != null) { _terms.Add(clv, new ClDouble(value)); } }
/// <summary> /// For use by the clone method. /// </summary> protected ClLinearExpression(ClDouble constant, Hashtable terms) { if (Cl.GC) { Console.Error.WriteLine("clone ClLinearExpression"); } _constant = (ClDouble)constant.Clone(); _terms = new Hashtable(); // need to unalias the ClDouble-s that we clone (do a deep clone) foreach (ClAbstractVariable clv in terms.Keys) { _terms.Add(clv, ((ClDouble)terms[clv]).Clone()); } }
public /*sealed*/ ClLinearExpression SetVariable(ClAbstractVariable v, double c) { // Assert(c != 0.0); ClDouble coeff = (ClDouble)_terms[v]; if (coeff != null) { coeff.Value = c; } else { _terms.Add(v, new ClDouble(c)); } return(this); }
/// <summary> /// For use by the clone method. /// </summary> protected ClLinearExpression(ClDouble constant, Hashtable terms) { if (Cl.GC) { Console.Error.WriteLine("clone ClLinearExpression"); } _constant = (ClDouble) constant.Clone(); _terms = new Hashtable(); // need to unalias the ClDouble-s that we clone (do a deep clone) foreach (ClAbstractVariable clv in terms.Keys) { _terms.Add(clv, ((ClDouble) terms[clv]).Clone()); } }
/// <summary> /// This linear expression currently represents the equation self=0. Destructively modify it so /// that subject=self represents an equivalent equation. /// /// Precondition: subject must be one of the variables in this expression. /// NOTES /// Suppose this expression is /// c + a*subject + a1*v1 + ... + an*vn /// representing /// c + a*subject + a1*v1 + ... + an*vn = 0 /// The modified expression will be /// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn /// representing /// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn /// /// Note that the term involving subject has been dropped. /// Returns the reciprocal, so changeSubject can use it, too /// </summary> public /*sealed*/ double NewSubject(ClAbstractVariable subject) { if (Trace) { FnEnterPrint(string.Format("newSubject: {0}", subject)); } ClDouble coeff = (ClDouble)_terms[subject]; _terms.Remove(subject); double reciprocal = 1.0 / coeff.Value; MultiplyMe(-reciprocal); return(reciprocal); }
/// <summary> /// Add a constraint to the solver. /// <param name="cn"> /// The constraint to be added. /// </param> /// </summary> public ClSimplexSolver AddConstraint(ClConstraint cn) { List <ClAbstractVariable> eplusEminus = new List <ClAbstractVariable>(2); ClDouble prevEConstant = new ClDouble(); ClLinearExpression expr = NewExpression(cn, /* output to: */ eplusEminus, prevEConstant); bool cAddedOkDirectly = TryAddingDirectly(expr); if (!cAddedOkDirectly) { // could not add directly AddWithArtificialVariable(expr); } _cNeedsSolving = true; if (cn.IsEditConstraint) { int i = _editVarMap.Count; ClEditConstraint cnEdit = (ClEditConstraint)cn; ClSlackVariable clvEplus = (ClSlackVariable)eplusEminus[0]; ClSlackVariable clvEminus = (ClSlackVariable)eplusEminus[1]; _editVarMap.Add(cnEdit.Variable, new ClEditInfo(cnEdit, clvEplus, clvEminus, prevEConstant.Value, i)); } if (_cOptimizeAutomatically) { Optimize(_objective); SetExternalVariables(); } return(this); }
/// <summary> /// Add a term c*v to this expression. If the expression already /// contains a term involving v, add c to the existing coefficient. /// If the new coefficient is approximately 0, delete v. Notify the /// solver if v appears or disappears from this expression. /// </summary> public /*sealed*/ ClLinearExpression AddVariable(ClAbstractVariable v, double c, ClAbstractVariable subject, ClTableau solver) { // body largely duplicated above if (Trace) { FnEnterPrint(string.Format("AddVariable: {0}, {1}, {2}, ...", v, c, subject)); } ClDouble coeff = (ClDouble)_terms[v]; if (coeff != null) { double new_coefficient = coeff.Value + c; if (Cl.Approx(new_coefficient, 0.0)) { solver.NoteRemovedVariable(v, subject); _terms.Remove(v); } else { coeff.Value = new_coefficient; } } else { if (!Cl.Approx(c, 0.0)) { _terms.Add(v, new ClDouble(c)); solver.NoteAddedVariable(v, subject); } } return(this); }
void Number(out ClDouble d) { Expect(13); double tmpVal = double.Parse(t.val, new CultureInfo("en-US").NumberFormat); d = new ClDouble(tmpVal); }
private ClLinearExpression NewExpression(ClConstraint cn, ICollection <ClAbstractVariable> eplusEminus, ClDouble prevEConstant) { ClLinearExpression cnExpr = cn.Expression; ClLinearExpression expr = new ClLinearExpression(cnExpr.Constant); ClSlackVariable eminus; var cnTerms = cnExpr.Terms; foreach (ClAbstractVariable v in cnTerms.Keys) { double c = (cnTerms[v]).Value; ClLinearExpression e = RowExpression(v); if (e == null) { expr.AddVariable(v, c); } else { expr.AddExpression(e, c); } } if (cn.IsInequality) { ++_slackCounter; ClSlackVariable slackVar = new ClSlackVariable(_slackCounter, "s"); expr.SetVariable(slackVar, -1); _markerVars.Add(cn, slackVar); if (!cn.Strength.IsRequired) { ++_slackCounter; eminus = new ClSlackVariable(_slackCounter, "em"); expr.SetVariable(eminus, 1.0); ClLinearExpression zRow = RowExpression(_objective); ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight); zRow.SetVariable(eminus, sw.AsDouble()); InsertErrorVar(cn, eminus); NoteAddedVariable(eminus, _objective); } } else { // cn is an equality if (cn.Strength.IsRequired) { ++_dummyCounter; ClDummyVariable dummyVar = new ClDummyVariable(_dummyCounter, "d"); expr.SetVariable(dummyVar, 1.0); _markerVars.Add(cn, dummyVar); } else { ++_slackCounter; ClSlackVariable eplus = new ClSlackVariable(_slackCounter, "ep"); eminus = new ClSlackVariable(_slackCounter, "em"); expr.SetVariable(eplus, -1.0); expr.SetVariable(eminus, 1.0); _markerVars.Add(cn, eplus); ClLinearExpression zRow = RowExpression(_objective); ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight); double swCoeff = sw.AsDouble(); zRow.SetVariable(eplus, swCoeff); NoteAddedVariable(eplus, _objective); zRow.SetVariable(eminus, swCoeff); NoteAddedVariable(eminus, _objective); InsertErrorVar(cn, eminus); InsertErrorVar(cn, eplus); if (cn.IsStayConstraint) { _stayPlusErrorVars.Add(eplus); _stayMinusErrorVars.Add(eminus); } else if (cn.IsEditConstraint) { eplusEminus.Add(eplus); eplusEminus.Add(eminus); prevEConstant.Value = cnExpr.Constant; } } } if (expr.Constant < 0) { expr.MultiplyMe(-1); } return(expr); }
/// <summary> /// Add a constraint to the solver. /// <param name="cn"> /// The constraint to be added. /// </param> /// </summary> public ClSimplexSolver AddConstraint(ClConstraint cn) /* throws ExClRequiredFailure, ExClInternalError */ { if (Trace) FnEnterPrint("AddConstraint: " + cn); ArrayList eplus_eminus = new ArrayList(2); ClDouble prevEConstant = new ClDouble(); ClLinearExpression expr = NewExpression(cn, /* output to: */ eplus_eminus, prevEConstant); bool cAddedOkDirectly = false; try { cAddedOkDirectly = TryAddingDirectly(expr); if (!cAddedOkDirectly) { // could not add directly AddWithArtificialVariable(expr); } } catch (ExClRequiredFailure rf) { throw rf; } _cNeedsSolving = true; if (cn.IsEditConstraint) { int i = _editVarMap.Count; ClEditConstraint cnEdit = (ClEditConstraint) cn; ClSlackVariable clvEplus = (ClSlackVariable) eplus_eminus[0]; ClSlackVariable clvEminus = (ClSlackVariable) eplus_eminus[1]; _editVarMap.Add(cnEdit.Variable, new ClEditInfo(cnEdit, clvEplus, clvEminus, prevEConstant.Value, i)); } if (_cOptimizeAutomatically) { Optimize(_objective); SetExternalVariables(); } return this; }
protected ClLinearExpression NewExpression(ClConstraint cn, ArrayList eplus_eminus, ClDouble prevEConstant) { if (Trace) { FnEnterPrint("NewExpression: " + cn); TracePrint("cn.IsInequality == " + cn.IsInequality); TracePrint("cn.IsRequired == " + cn.IsRequired); } ClLinearExpression cnExpr = cn.Expression; ClLinearExpression expr = new ClLinearExpression(cnExpr.Constant); ClSlackVariable slackVar = new ClSlackVariable(); ClDummyVariable dummyVar = new ClDummyVariable(); ClSlackVariable eminus = new ClSlackVariable(); ClSlackVariable eplus = new ClSlackVariable(); Hashtable cnTerms = cnExpr.Terms; foreach(ClAbstractVariable v in cnTerms.Keys) { double c = ((ClDouble) cnTerms[v]).Value; ClLinearExpression e = RowExpression(v); if (e == null) expr.AddVariable(v, c); else expr.AddExpression(e, c); } if (cn.IsInequality) { ++_slackCounter; slackVar = new ClSlackVariable (_slackCounter, "s"); expr.SetVariable(slackVar, -1); _markerVars.Add(cn, slackVar); if (!cn.IsRequired) { ++_slackCounter; eminus = new ClSlackVariable(_slackCounter, "em"); expr.SetVariable(eminus, 1.0); ClLinearExpression zRow = RowExpression(_objective); ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight); zRow.SetVariable(eminus, sw.AsDouble()); InsertErrorVar(cn, eminus); NoteAddedVariable(eminus, _objective); } } else { // cn is an equality if (cn.IsRequired) { ++_dummyCounter; dummyVar = new ClDummyVariable(_dummyCounter, "d"); expr.SetVariable(dummyVar, 1.0); _markerVars.Add(cn, dummyVar); if (Trace) TracePrint("Adding dummyVar == d" + _dummyCounter); } else { ++_slackCounter; eplus = new ClSlackVariable(_slackCounter, "ep"); eminus = new ClSlackVariable(_slackCounter, "em"); expr.SetVariable(eplus, -1.0); expr.SetVariable(eminus, 1.0); _markerVars.Add(cn, eplus); ClLinearExpression zRow = RowExpression(_objective); ClSymbolicWeight sw = cn.Strength.SymbolicWeight.Times(cn.Weight); double swCoeff = sw.AsDouble(); if (swCoeff == 0) { if (Trace) { TracePrint("sw == " + sw); TracePrint("cn == " + cn); TracePrint("adding " + eplus + " and " + eminus + " with swCoeff == " + swCoeff); } } zRow.SetVariable(eplus, swCoeff); NoteAddedVariable(eplus, _objective); zRow.SetVariable(eminus, swCoeff); NoteAddedVariable(eminus, _objective); InsertErrorVar(cn, eminus); InsertErrorVar(cn, eplus); if (cn.IsStayConstraint) { _stayPlusErrorVars.Add(eplus); _stayMinusErrorVars.Add(eminus); } else if (cn.IsEditConstraint) { eplus_eminus.Add(eplus); eplus_eminus.Add(eminus); prevEConstant.Value = cnExpr.Constant; } } } if (expr.Constant < 0) expr.MultiplyMe(-1); if (Trace) FnExitPrint("returning " + expr); return expr; }