/// <summary> /// Remove the basic variable v from the tableau row v=expr /// Then update column cross indices. /// </summary> protected ClLinearExpression RemoveRow(ClAbstractVariable var) /*throws ExCLInternalError*/ { var expr = _rows[var]; if (expr == null) { throw new CassowaryInternalException("linear expression is null"); } // For each variable in this expression, update // the column mapping and remove the variable from the list // of rows it is known to be in. foreach (var varset in expr.Terms.Keys.Select(clv => _columns[clv]).Where(varset => varset != null)) { varset.Remove(var); } InfeasibleRows.Remove(var); if (var.IsExternal) { ExternalRows.Remove((ClVariable)var); } _rows.Remove(var); return(expr); }
/// <summary> /// Re-solve the current collection of constraints, given the new /// values for the edit variables that have already been /// suggested (see <see cref="IEditContext.SuggestValue"/> method). /// </summary> IEditContext IEditContext.Resolve() { DualOptimize(); SetExternalVariables(); InfeasibleRows.Clear(); ResetStayConstants(); return(this); }
/// <summary> /// Marks the start of an edit session. /// </summary> /// <remarks> /// BeginEdit should be called before sending Resolve() /// messages, after adding the appropriate edit variables. /// </remarks> public IEditContext BeginEdit(params ClVariable[] editVar) { foreach (ClVariable variable in editVar) { AddEditVar(variable, ClStrength.Strong); } Assert(_editVarMap.Count > 0, "_editVarMap.Count > 0"); // may later want to do more in here InfeasibleRows.Clear(); ResetStayConstants(); _stkCedcns.Push(_editVarMap.Count); return(this); }
/// <summary> /// Re-optimize using the dual simplex algorithm. /// </summary> /// <remarks> /// We have set new values for the constants in the edit constraints. /// </remarks> protected void DualOptimize() /* throws ExClInternalError */ { ClLinearExpression zRow = RowExpression(_objective); while (InfeasibleRows.Count > 0) { ClAbstractVariable exitVar = InfeasibleRows.First(); InfeasibleRows.Remove(exitVar); ClAbstractVariable entryVar = null; ClLinearExpression expr = RowExpression(exitVar); if (expr != null) { if (expr.Constant < 0.0) { double ratio = Double.MaxValue; var terms = expr.Terms; foreach (ClAbstractVariable v in terms.Keys) { double c = (terms[v]).Value; if (c > 0.0 && v.IsPivotable) { double zc = zRow.CoefficientFor(v); double r = zc / c; if (r < ratio) { entryVar = v; ratio = r; } } } // ReSharper disable CompareOfFloatsByEqualityOperator if (ratio == Double.MaxValue) // ReSharper restore CompareOfFloatsByEqualityOperator { throw new CassowaryInternalException("ratio == nil (Double.MaxValue) in DualOptimize"); } Pivot(entryVar, exitVar); } } } }
/// <summary> /// Fix the constants in the equations representing the edit constraints. /// </summary> /// <remarks> /// Each of the non-required edits will be represented by an equation /// of the form: /// v = c + eplus - eminus /// where v is the variable with the edit, c is the previous edit value, /// and eplus and eminus are slack variables that hold the error in /// satisfying the edit constraint. We are about to change something, /// and we want to fix the constants in the equations representing /// the edit constraints. If one of eplus and eminus is basic, the other /// must occur only in the expression for that basic error variable. /// (They can't both be basic.) Fix the constant in this expression. /// Otherwise they are both non-basic. Find all of the expressions /// in which they occur, and fix the constants in those. See the /// UIST paper for details. /// (This comment was for ResetEditConstants(), but that is now /// gone since it was part of the screwey vector-based interface /// to resolveing. --02/16/99 gjb) /// </remarks> protected void DeltaEditConstant(double delta, ClAbstractVariable plusErrorVar, ClAbstractVariable minusErrorVar) { ClLinearExpression exprPlus = RowExpression(plusErrorVar); if (exprPlus != null) { exprPlus.IncrementConstant(delta); if (exprPlus.Constant < 0.0) { InfeasibleRows.Add(plusErrorVar); } return; } ClLinearExpression exprMinus = RowExpression(minusErrorVar); if (exprMinus != null) { exprMinus.IncrementConstant(-delta); if (exprMinus.Constant < 0.0) { InfeasibleRows.Add(minusErrorVar); } return; } var columnVars = Columns[minusErrorVar]; foreach (ClAbstractVariable basicVar in columnVars) { ClLinearExpression expr = RowExpression(basicVar); //Assert(expr != null, "expr != null"); double c = expr.CoefficientFor(minusErrorVar); expr.IncrementConstant(c * delta); if (basicVar.IsRestricted && expr.Constant < 0.0) { InfeasibleRows.Add(basicVar); } } }
/// <summary> /// Replace all occurrences of oldVar with expr, and update column cross indices /// oldVar should now be a basic variable. /// </summary> protected void SubstituteOut(ClAbstractVariable oldVar, ClLinearExpression expr) { var varset = _columns[oldVar]; foreach (var v in varset) { var row = _rows[v]; row.SubstituteOut(oldVar, expr, v, this); if (v.IsRestricted && row.Constant < 0.0) { InfeasibleRows.Add(v); } } if (oldVar.IsExternal) { ExternalRows.Add((ClVariable)oldVar); ExternalParametricVars.Remove((ClVariable)oldVar); } _columns.Remove(oldVar); }