/// <summary> /// Try to choose a subject (a variable to become basic) from /// among the current variables in expr. /// </summary> /// <remarks> /// We are trying to add the constraint expr=0 to the tableaux. /// If expr constains any unrestricted variables, then we must choose /// an unrestricted variable as the subject. Also if the subject is /// new to the solver, we won't have to do any substitutions, so we /// prefer new variables to ones that are currently noted as parametric. /// If expr contains only restricted variables, if there is a restricted /// variable with a negative coefficient that is new to the solver we can /// make that the subject. Otherwise we can't find a subject, so return nil. /// (In this last case we have to add an artificial variable and use that /// variable as the subject -- this is done outside this method though.) /// </remarks> protected ClAbstractVariable ChooseSubject(ClLinearExpression expr) /* ExClRequiredFailure */ { if (Trace) FnEnterPrint("ChooseSubject: " + expr); ClAbstractVariable subject = null; // the current best subject, if any bool foundUnrestricted = false; bool foundNewRestricted = false; Hashtable terms = expr.Terms; foreach (ClAbstractVariable v in terms.Keys) { double c = ((ClDouble) terms[v]).Value; if (foundUnrestricted) { if (!v.IsRestricted) { if (!ColumnsHasKey(v)) return v; } } else { // we haven't found an restricted variable yet if (v.IsRestricted) { if (!foundNewRestricted && !v.IsDummy && c < 0.0) { Set col = (Set) _columns[v]; if ( col == null || (col.Count == 1 && ColumnsHasKey(_objective)) ) { subject = v; foundNewRestricted = true; } } } else { subject = v; foundUnrestricted = true; } } } if (subject != null) return subject; double coeff = 0.0; foreach (ClAbstractVariable v in terms.Keys) { double c = ((ClDouble) terms[v]).Value; if (!v.IsDummy) return null; // nope, no luck if (!ColumnsHasKey(v)) { subject = v; coeff = c; } } if (!Cl.Approx(expr.Constant, 0.0)) { throw new ExClRequiredFailure(); } if (coeff > 0.0) { expr.MultiplyMe(-1); } return subject; }
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> /// Try to choose a subject (a variable to become basic) from /// among the current variables in expr. /// </summary> /// <remarks> /// We are trying to add the constraint expr=0 to the tableaux. /// If expr constains any unrestricted variables, then we must choose /// an unrestricted variable as the subject. Also if the subject is /// new to the solver, we won't have to do any substitutions, so we /// prefer new variables to ones that are currently noted as parametric. /// If expr contains only restricted variables, if there is a restricted /// variable with a negative coefficient that is new to the solver we can /// make that the subject. Otherwise we can't find a subject, so return nil. /// (In this last case we have to add an artificial variable and use that /// variable as the subject -- this is done outside this method though.) /// </remarks> private ClAbstractVariable ChooseSubject(ClLinearExpression expr) /* ExClRequiredFailure */ { ClAbstractVariable subject = null; // the current best subject, if any bool foundUnrestricted = false; bool foundNewRestricted = false; var terms = expr.Terms; foreach (ClAbstractVariable v in terms.Keys) { double c = (terms[v]).Value; if (foundUnrestricted) { if (!v.IsRestricted) { if (!ColumnsHasKey(v)) { return(v); } } } else { // we haven't found an restricted variable yet if (v.IsRestricted) { if (!foundNewRestricted && !v.IsDummy && c < 0.0) { HashSet <ClAbstractVariable> col; if (!Columns.TryGetValue(v, out col) || (col.Count == 1 && ColumnsHasKey(_objective))) { subject = v; foundNewRestricted = true; } } } else { subject = v; foundUnrestricted = true; } } } if (subject != null) { return(subject); } double coeff = 0.0; foreach (ClAbstractVariable v in terms.Keys) { double c = (terms[v]).Value; if (!v.IsDummy) { return(null); // nope, no luck } if (!ColumnsHasKey(v)) { subject = v; coeff = c; } } if (!Approx(expr.Constant, 0.0)) { throw new CassowaryRequiredFailureException(); } if (coeff > 0.0) { expr.MultiplyMe(-1); } return(subject); }