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); }
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; }
/// <summary> /// Remove a constraint from the tableau. /// Also remove any error variable associated with it. /// </summary> public ClSimplexSolver RemoveConstraint(ClConstraint cn) /* throws ExClRequiredFailure, ExClInternalError */ { _cNeedsSolving = true; ResetStayConstants(); ClLinearExpression zRow = RowExpression(_objective); HashSet <ClAbstractVariable> eVars; if (_errorVars.TryGetValue(cn, out eVars)) { foreach (ClAbstractVariable clv in eVars) { ClLinearExpression expr = RowExpression(clv); if (expr == null) { zRow.AddVariable(clv, -cn.Weight * cn.Strength.SymbolicWeight.AsDouble(), _objective, this); } else // the error variable was in the basis { zRow.AddExpression(expr, -cn.Weight * cn.Strength.SymbolicWeight.AsDouble(), _objective, this); } } } ClAbstractVariable marker; if (!_markerVars.TryGetValue(cn, out marker)) { throw new CassowaryConstraintNotFoundException(); } _markerVars.Remove(cn); if (RowExpression(marker) == null) { // not in the basis, so need to do some more work var col = Columns[marker]; ClAbstractVariable exitVar = null; double minRatio = 0.0; foreach (ClAbstractVariable v in col) { if (v.IsRestricted) { ClLinearExpression expr = RowExpression(v); double coeff = expr.CoefficientFor(marker); if (coeff < 0.0) { double r = -expr.Constant / coeff; if (exitVar == null || r < minRatio) { minRatio = r; exitVar = v; } } } } if (exitVar == null) { foreach (ClAbstractVariable v in col) { if (v.IsRestricted) { ClLinearExpression expr = RowExpression(v); double coeff = expr.CoefficientFor(marker); double r = expr.Constant / coeff; if (exitVar == null || r < minRatio) { minRatio = r; exitVar = v; } } } } if (exitVar == null) { // exitVar is still null if (col.Count == 0) { RemoveColumn(marker); } else { // put first element in exitVar var colEnum = col.GetEnumerator(); colEnum.MoveNext(); exitVar = colEnum.Current; } } if (exitVar != null) { Pivot(marker, exitVar); } } if (RowExpression(marker) != null) { RemoveRow(marker); } if (eVars != null) { foreach (ClAbstractVariable v in eVars.Where(a => a != marker)) { RemoveColumn(v); } } if (cn.IsStayConstraint) { if (eVars != null) { for (int i = 0; i < _stayPlusErrorVars.Count; i++) { eVars.Remove(_stayPlusErrorVars[i]); eVars.Remove(_stayMinusErrorVars[i]); } } } else if (cn.IsEditConstraint) { Assert(eVars != null, "eVars != null"); ClEditConstraint cnEdit = (ClEditConstraint)cn; ClVariable clv = cnEdit.Variable; ClEditInfo cei = _editVarMap[clv]; ClSlackVariable clvEditMinus = cei.ClvEditMinus; RemoveColumn(clvEditMinus); _editVarMap.Remove(clv); } // FIXME: do the remove at top if (eVars != null) { //_errorVars.Remove(eVars); _errorVars.Remove(cn); } if (_cOptimizeAutomatically) { Optimize(_objective); SetExternalVariables(); } return(this); }