public static int Compare(CardVar v1, CardVar v2) { if (v1 == v2) { return(0); } var cmp = Microsoft.Formula.Common.Terms.Symbol.Compare(v1.Symbol, v2.Symbol); if (cmp != 0) { return(cmp); } if (v1.IsLFPCard && v2.IsLFPCard) { return(0); } else if (!v1.IsLFPCard) { return(-1); } else { return(1); } }
private Cardinality Eval(CardExpr expr, CardVar cvar, Cardinality val, bool evalOnLower) { switch (expr.Kind) { case CardExpr.ExprKind.Cnst: return(((CardCnst)expr).Value); case CardExpr.ExprKind.Var: if (expr == cvar) { return(val); } else if (evalOnLower) { return(GetRange((CardVar)expr).Lower); } else { return(GetRange((CardVar)expr).Upper); } case CardExpr.ExprKind.Prod: return(Eval(expr[0], cvar, val, evalOnLower) * Eval(expr[1], cvar, val, evalOnLower)); case CardExpr.ExprKind.Unn: return(Eval(expr[0], cvar, val, evalOnLower) + Eval(expr[1], cvar, val, evalOnLower)); default: throw new NotImplementedException(); } }
public CardConstraint(OpKind op, CardVar lhs, CardExpr rhs) { Contract.Requires(lhs != null && rhs != null); Op = op; Lhs = lhs; Rhs = rhs; GetRHSVars(rhs); }
private LinkedList <CardConstraint> GetUseList(CardVar cvar) { LinkedList <CardConstraint> cons; if (!useLists.TryFindValue(cvar, out cons)) { cons = new LinkedList <CardConstraint>(); useLists.Add(cvar, cons); } return(cons); }
private void UpdateRange(CardVar cvar, CardRange newRange) { Contract.Requires(newRange.Lower != Cardinality.Infinity); MutableTuple <CardRange> range; if (solverState.Peek().TryFindValue(cvar, out range)) { range.Item1 = newRange; } else { solverState.Peek().Add(cvar, new MutableTuple <CardRange>(newRange)); } }
private CardRange GetRange(CardVar cvar) { MutableTuple <CardRange> range; foreach (var valuations in solverState) { if (valuations.TryFindValue(cvar, out range)) { return(range.Item1); } } return(CardRange.All); }
private void EnqueueConstraints(CardVar cvar, Stack <CardConstraint> stack) { LinkedList <CardConstraint> cons; if (useLists.TryFindValue(cvar, out cons)) { foreach (var c in cons) { if (!c.IsQueued) { c.IsQueued = true; stack.Push(c); } } } }
private bool Propagate(CardVar cvar) { Cardinality cd; CardRange lhs, rhs; CardRange intr, intrp; CardConstraint con; var stack = new Stack <CardConstraint>(); EnqueueConstraints(cvar, stack); while (stack.Count > 0) { con = stack.Pop(); lhs = GetRange(con.Lhs); rhs = Eval(con.Rhs); con.IsQueued = false; switch (con.Op) { case CardConstraint.OpKind.LEq: if ((cd = Cardinality.Min(lhs.Upper, rhs.Upper)) != lhs.Upper) { if (cd < lhs.Lower) { return(false); } UpdateRange(con.Lhs, lhs = new CardRange(lhs.Lower, cd)); EnqueueConstraints(con.Lhs, stack); } if (rhs.Lower < lhs.Lower) { foreach (var rhsvar in con.RhsVars) { rhs = GetRange(rhsvar); if (Eval(con.Rhs, rhsvar, rhs.Lower, false) >= lhs.Lower) { continue; } intr = new CardRange(rhs.Lower, Cardinality.Min(lhs.Lower, rhs.Upper)); while (intr.Lower + 1 < intr.Upper) { intrp = intr.Bisect(true); if (Eval(con.Rhs, rhsvar, intrp.Lower, false) >= lhs.Lower) { intr = new CardRange(intr.Lower, intrp.Lower); } else { intr = new CardRange(intrp.Lower, intr.Upper); } } if (Eval(con.Rhs, rhsvar, intr.Lower, false) >= lhs.Lower) { if (intr.Lower > rhs.Lower) { UpdateRange(rhsvar, new CardRange(intr.Lower, rhs.Upper)); EnqueueConstraints(rhsvar, stack); continue; } } else if (Eval(con.Rhs, rhsvar, intr.Upper, false) >= lhs.Lower) { if (intr.Upper > rhs.Lower) { UpdateRange(rhsvar, new CardRange(intr.Upper, rhs.Upper)); EnqueueConstraints(rhsvar, stack); continue; } } else { return(false); } } } break; case CardConstraint.OpKind.GEq: if ((cd = Cardinality.Max(lhs.Lower, rhs.Lower)) != lhs.Lower) { if (cd > lhs.Upper) { return(false); } UpdateRange(con.Lhs, lhs = new CardRange(cd, lhs.Upper)); EnqueueConstraints(con.Lhs, stack); } if (rhs.Upper > lhs.Upper) { foreach (var rhsvar in con.RhsVars) { rhs = GetRange(rhsvar); if (Eval(con.Rhs, rhsvar, rhs.Upper, true) <= lhs.Upper) { continue; } intr = new CardRange(rhs.Lower, Cardinality.Min(rhs.Upper, lhs.Upper)); while (intr.Lower + 1 < intr.Upper) { intrp = intr.Bisect(false); if (Eval(con.Rhs, rhsvar, intrp.Upper, true) <= lhs.Upper) { intr = new CardRange(intrp.Upper, intr.Upper); } else { intr = new CardRange(intr.Lower, intrp.Upper); } } if (Eval(con.Rhs, rhsvar, intr.Upper, true) <= lhs.Upper) { if (intr.Upper < rhs.Upper) { UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Upper)); EnqueueConstraints(rhsvar, stack); continue; } } else if (Eval(con.Rhs, rhsvar, intr.Lower, true) <= lhs.Upper) { if (intr.Lower < rhs.Upper) { UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Lower)); EnqueueConstraints(rhsvar, stack); continue; } } else { return(false); } } } break; default: throw new NotImplementedException(); } } return(true); }