public void AddOrMergeCacheEntry(CasExpr expr, Dictionary <string, SnapCacheEntry> cache, string key) { if (!cache.ContainsKey(key)) { SnapCacheEntry entry = new SnapCacheEntry(expr, cache, key); cache[key] = entry; CacheEntries.Add(entry); } else { var currentExpr = cache[key].Expr; var diffExpr = CAS.Sub(expr, currentExpr); var vars = new List <CasVar>(CAS.UsedVariables(diffExpr)); vars.Sort((CasVar var1, CasVar var2) => Variables[var2].Value.CompareTo(Variables[var1].Value)); foreach (var v in vars) { var solution = CAS.MakeZero(diffExpr, v); if (solution != null) { ReplaceVariable(v, solution); return; } } if (diffExpr.Poly1.Terms.Count != 0) { throw new Exception("Contradictory expression"); } } }
public float Eval(CasExpr expr, Dictionary <CasVar, float> values) { float res1 = expr.Poly1.Eval(values); float res2 = expr.Poly2.Eval(values); return(res1 / res2); }
public CasExpr Substitute(CasExpr expr, CasVar forV, CasExpr inExpr) { CasExpr expr1 = inExpr.Poly1.Substitute(expr, forV); CasExpr expr2 = inExpr.Poly2.Substitute(expr, forV); return(Div(expr1, expr2)); }
public HashSet <CasVar> UsedVariables(CasExpr expr) { HashSet <CasVar> res = new HashSet <CasVar>(); expr.Poly1.GetUsedVariables(res); expr.Poly2.GetUsedVariables(res); return(res); }
public void EqualizeLongerDims(Dictionary <int, SlideObject> slideObjects, int shapeId1, int shapeId2) { UpdateSnapCache(slideObjects); FindExprsForSlideObjs(slideObjects); CasExpr expr1 = slideObjects[shapeId1].LongerDimExpr(); CasExpr expr2 = slideObjects[shapeId2].LongerDimExpr(); EqualizeExpressions(expr1, expr2, expr1, slideObjects); }
public CasExpr Mul(CasExpr expr1, CasExpr expr2) { if (expr1.Poly1.PolyEquals(expr2.Poly2)) { return(new CasExpr(expr2.Poly1, expr1.Poly2).Simplify()); } if (expr1.Poly2.PolyEquals(expr2.Poly1)) { return(new CasExpr(expr1.Poly1, expr2.Poly2).Simplify()); } return(new CasExpr(CasPolynomial.PolyProd(expr1.Poly1, expr2.Poly1), CasPolynomial.PolyProd(expr1.Poly2, expr2.Poly2)).Simplify()); }
public CasExpr Substitute(CasExpr expr, CasVar forV) { if (!Variables.ContainsKey(forV)) { return(this.ToExpr()); } var exprPow = expr.RaisedToPower(Variables[forV]); var newTerm = CopyWithCoefficient(Coefficient); newTerm.Variables.Remove(forV); return(CasSystem.Instance.Mul(newTerm.ToExpr(), exprPow)); }
public CasExpr RaisedToPower(int exp) { if (exp == 0) { return(ConstantExpr(1)); } CasExpr res = this; for (int i = 1; i < exp; i++) { res = CasSystem.Instance.Mul(res, this); } return(res); }
public CasExpr Add(CasExpr expr1, CasExpr expr2) { if (expr1.Poly2.PolyEquals(expr2.Poly2)) { return(new CasExpr(CasPolynomial.PolySum(expr1.Poly1, expr2.Poly1), expr2.Poly2).Simplify()); } else { var p1 = CasPolynomial.PolyProd(expr1.Poly1, expr2.Poly2); var p2 = CasPolynomial.PolyProd(expr1.Poly2, expr2.Poly1); var num = CasPolynomial.PolySum(p1, p2); var denom = CasPolynomial.PolyProd(expr1.Poly2, expr2.Poly2); return(new CasExpr(num, denom).Simplify()); } }
public void ReplaceVariable(CasVar variable, CasExpr expr) { foreach (var entry in CacheEntries) { entry.Expr = CAS.Substitute(expr, variable, entry.Expr); } if (ObjectsToKeepUpdated != null) { foreach (var obj in ObjectsToKeepUpdated.Values) { obj.HeightExpr = CAS.Substitute(expr, variable, obj.HeightExpr); obj.WidthExpr = CAS.Substitute(expr, variable, obj.WidthExpr); obj.XExpr = CAS.Substitute(expr, variable, obj.XExpr); obj.YExpr = CAS.Substitute(expr, variable, obj.YExpr); } } }
public void UpdateForDim(float p1, float c, float p2, float length, Dictionary <string, SnapCacheEntry> cachedPos) { CasExpr p1Expr = MakeExprForFloat(p1, cachedPos); AddOrMergeCacheEntry(p1Expr, cachedPos, FloatToKey(p1)); p1Expr = cachedPos[FloatToKey(p1)].Expr; CasExpr lengthExpr = MakeExprForFloat(length, CachedLengths); AddOrMergeCacheEntry(lengthExpr, CachedLengths, FloatToKey(length)); lengthExpr = CachedLengths[FloatToKey(length)].Expr; var p2Expr = CAS.Add(p1Expr, lengthExpr); AddOrMergeCacheEntry(p2Expr, cachedPos, FloatToKey(p2)); var cExpr = CAS.Add(p1Expr, CAS.Div(lengthExpr, CAS.ConstExpr(2))); AddOrMergeCacheEntry(cExpr, cachedPos, FloatToKey(c)); }
public CasExpr Substitute(CasExpr expr, CasVar forV) { if (!ContainsVar(forV)) { return(new CasExpr(this, CasPolynomial.ConstantPoly(1))); } List <CasExpr> exprs = new List <CasExpr>(); foreach (var t in Terms) { exprs.Add(t.Substitute(expr, forV)); } var sum = CasExpr.ConstantExpr(0); foreach (var e in exprs) { sum = CasSystem.Instance.Add(sum, e); } return(sum); }
// Result is null if solver fails public CasExpr MakeZero(CasExpr expr, CasVar v) { List <CasTerm> zeroTerms = new List <CasTerm>(); List <CasTerm> oneTerms = new List <CasTerm>(); foreach (var t in expr.Poly1.Terms) { if (!t.Variables.ContainsKey(v)) { zeroTerms.Add(t); } else if (t.Variables[v] == 1) { oneTerms.Add(t); } else { return(null); } } if (oneTerms.Count == 0) { return(null); } CasPolynomial poly1 = new CasPolynomial(); CasPolynomial poly2 = new CasPolynomial(); foreach (var t in zeroTerms) { poly1.Terms.Add(t.CopyWithCoefficient(-1 * t.Coefficient)); } foreach (var t in oneTerms) { poly2.Terms.Add(t.CopyWithCoefficient(t.Coefficient)); } foreach (var t in poly2.Terms) { t.Variables.Remove(v); } return(new CasExpr(poly1, poly2)); }
public void EqualizeExpressions(CasExpr expr1, CasExpr expr2, CasExpr invariant, Dictionary <int, SlideObject> slideObjects) { var diffExpr = CAS.Sub(expr1, expr2); var vars = new List <CasVar>(CAS.UsedVariables(diffExpr)); CasVar bestVar = null; CasExpr bestSolution = null; float minChange = 0; Dictionary <CasVar, float> values = GetVariableValues(); float initialVal = CAS.Eval(invariant, values); foreach (var v in vars) { var solution = CAS.MakeZero(diffExpr, v); if (solution != null) { float change = Math.Abs(CAS.Eval(CAS.Substitute(solution, v, invariant), values) - initialVal); if (bestVar == null || change < minChange) { bestVar = v; minChange = change; bestSolution = solution; } } } if (bestSolution != null) { ObjectsToKeepUpdated = slideObjects; ReplaceVariable(bestVar, bestSolution); ObjectsToKeepUpdated = null; } // FindExprsForSlideObjs(slideObjects); SlideScanner.Instance.ApplyDimsToShapes(slideObjects, values); CacheEntries = new HashSet <SnapCacheEntry>(); CachedXs = RebuildCache(CachedXs, values); CachedYs = RebuildCache(CachedYs, values); CachedLengths = RebuildCache(CachedLengths, values); }
public CasExpr Sub(CasExpr expr1, CasExpr expr2) { return(Add(expr1, Mul(expr2, ConstExpr(-1)))); }
public CasExpr ConstExpr(int c) { return(CasExpr.ConstantExpr(c)); }
public CasExpr Div(CasExpr expr1, CasExpr expr2) { return(Mul(expr1, new CasExpr(expr2.Poly2, expr2.Poly1))); }
public SnapCacheEntry(CasExpr expr, Dictionary <string, SnapCacheEntry> cache, string key) { Expr = expr; Cache = cache; Key = key; }
// Result is null if solver fails public Tuple <CasExpr, CasVar> Solve(CasExpr expr, CasVar forV) { if (expr.Poly1.ContainsVar(forV) && expr.Poly2.ContainsVar(forV)) { return(null); } if (!expr.Poly1.ContainsVar(forV) && !expr.Poly2.ContainsVar(forV)) { return(null); } if (expr.Poly1.ContainsVar(forV) && !expr.Poly2.ContainsVar(forV)) { List <CasTerm> zeroTerms = new List <CasTerm>(); List <CasTerm> oneTerms = new List <CasTerm>(); foreach (var t in expr.Poly1.Terms) { if (!t.Variables.ContainsKey(forV)) { zeroTerms.Add(t); } else if (t.Variables[forV] == 1) { oneTerms.Add(t); } else { return(null); } } if (oneTerms.Count == 0) { return(null); } CasPolynomial polyZeros = new CasPolynomial(); CasPolynomial polyOnes = new CasPolynomial(); foreach (var t in zeroTerms) { polyZeros.Terms.Add(t.CopyWithCoefficient(-1 * t.Coefficient)); } foreach (var t in oneTerms) { polyOnes.Terms.Add(t.CopyWithCoefficient(t.Coefficient)); t.Variables.Remove(forV); } var newVar = NewVar(); var newTerm = new CasTerm(1); newTerm.Variables[newVar] = 1; polyZeros.Terms.Add(newTerm); var resExpr = new CasExpr(CasPolynomial.PolyProd(polyZeros, expr.Poly2), polyOnes); return(new Tuple <CasExpr, CasVar>(resExpr, newVar)); } else { List <CasTerm> zeroTerms = new List <CasTerm>(); List <CasTerm> oneTerms = new List <CasTerm>(); foreach (var t in expr.Poly2.Terms) { if (!t.Variables.ContainsKey(forV)) { zeroTerms.Add(t); } else if (t.Variables[forV] == 1) { oneTerms.Add(t); } else { return(null); } } if (oneTerms.Count == 0) { return(null); } CasPolynomial polyZeros = new CasPolynomial(); CasPolynomial polyOnes = new CasPolynomial(); var newVar = NewVar(); foreach (var t in zeroTerms) { polyZeros.Terms.Add(t.CopyWithCoefficient(-1 * t.Coefficient)); t.Variables[newVar] = 1; } foreach (var t in oneTerms) { polyOnes.Terms.Add(t.CopyWithCoefficient(t.Coefficient)); t.Variables.Remove(forV); t.Variables[newVar] = 1; } var resExpr = new CasExpr(CasPolynomial.PolySum(polyZeros, expr.Poly2), polyOnes); return(new Tuple <CasExpr, CasVar>(resExpr, newVar)); } }