/// <summary> /// DFS: Depth First Search /// </summary> /// <param name="term"></param> /// <param name="rootTerm">Trace generation purpose</param> /// <returns></returns> public Term DepthFirstSearch(Term rootTerm) { var lst = Args as List <object>; Debug.Assert(lst != null); Term localTerm = this; int index = 0; while (index < lst.Count) { var tempTerm = lst[index] as Term; if (tempTerm != null) { object gTerm = tempTerm.AlgebraLaws(rootTerm); if (!gTerm.Equals(tempTerm)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[index] = gTerm; lst = cloneLst; localTerm = cloneTerm; } } index++; } return(localTerm); }
/// <summary> /// x+0 = x, x-0 = x, x*0=0 /// </summary> /// <param name="obj"></param> /// <param name="rootTerm"></param> /// <returns></returns> public static object ApplyZero(this object obj, Term rootTerm) { var term = obj as Term; if (term == null) { return(obj); } Term localTerm = term.DepthFirstSearch(rootTerm); #region Apply Zero Law var list = localTerm.Args as List <object>; if (ContainZero(list)) { if (localTerm.Op.Method.Name.Equals("Multiply")) { string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Identity); string rule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Identity); String appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Identity, localTerm, null); rootTerm.GenerateTrace(localTerm, 0, kc, rule, appliedRule); return(0); } if (localTerm.Op.Method.Name.Equals("Add")) { string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Identity); var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); RemoveZero(ref cloneLst); //generate trace rule string rule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Identity); string appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Identity, localTerm, null); rootTerm.GenerateTrace(localTerm, cloneTerm, kc, rule, appliedRule); localTerm = cloneTerm; } } #endregion return(localTerm); }
/// <summary> //with calculation functionality, it does not /// take care of term rewriting. /// /// Terms should follow the below rules: /// tp: "2+2", "2+3-1", "2+2*2" /// </summary> /// <returns> can be term or value</returns> /// public static object Arithmetic(this object obj, Term rootTerm) { var term = obj as Term; if (term == null) { return(obj); } Term localTerm = term.DepthFirstSearch(rootTerm); var list = localTerm.Args as List <object>; //List<object> objs = localTerm.FindArithValues(); if (list == null || list.Count < 2) { return(localTerm); } bool madeChanges; do { list = localTerm.Args as List <object>; if (list == null) { throw new Exception("Cannot be null"); } int itemCount = list.Count; madeChanges = false; itemCount--; for (var i = 0; i < itemCount; i++) { list = localTerm.Args as List <object>; Debug.Assert(list != null); itemCount = list.Count; object obj1; if (i + 1 >= list.Count) { break; } if (SatisfyCalcCondition(term.Op, list[i], list[i + 1], out obj1)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[i] = obj1; cloneLst.RemoveAt(i + 1); string metaScaffold = ArithRule.CalcRule(term.Op.Method.Name); string scaffold = ArithRule.CalcRule(term.Op.Method.Name, list[i], list[i + 1], obj1); string kc = ArithRule.FindKC(term.Op.Method.Name); rootTerm.GenerateTrace(localTerm, cloneTerm, kc, metaScaffold, scaffold); localTerm = cloneTerm; madeChanges = true; } } } while (madeChanges); var lstArgs = localTerm.Args as List <object>; if (lstArgs.Count == 1) { return(lstArgs[0]); } return(localTerm); }
/// <summary> /// x+(y+z) == (x+y)+zm, x(yz) == (xy)z /// </summary> /// <param name="term"></param> /// <param name="gTerm"></param> /// <returns></returns> public static object ApplyAssociative(this object obj, Term rootTerm) { //(a+1)+1 -> a+(1+1) //a*3*3 -> a*(3*3) var term = obj as Term; if (term == null) { return(obj); } Term localTerm = term.DepthFirstSearch(rootTerm); var list = localTerm.Args as List <object>; if (list == null) { throw new Exception("Cannot be null"); } if (list.Count < 2) { return(localTerm); } object obj1, obj2; if (SatisfyAssociativeCondition(term, list[0], list[1], out obj1, out obj2)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[0] = obj1; cloneLst[1] = obj2; //generate trace rule string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Associative); string rule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Associative); String appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Associative, list[0], list[1]); rootTerm.GenerateTrace(localTerm, cloneTerm, kc, rule, appliedRule); localTerm = cloneTerm; } Term gTerm; if (SatisfyAssociativeCondition2(localTerm, out gTerm)) { //generate trace rule string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Associative); string rule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Associative); String appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Associative, list[0], list[1]); rootTerm.GenerateTrace(localTerm, gTerm, kc, rule, appliedRule); localTerm = gTerm; } return(localTerm); }
/// <summary> /// Commutative Law /// Algorithm: Bubble Sort /// </summary> /// <param name="term"></param> /// <param name="obj"></param> /// <param name="rootTerm"></param> public static object ApplyCommutative(this object obj, Term rootTerm) { var term = obj as Term; if (term == null) { return(obj); } //3+x -> x+3 //x*3 -> 3*x //x+a -> x+a //x*a -> x*a //3*a*3 -> a*3*3 //(x+1)*a -> a*(x+1) //1+(1+a) -> (a+1)+1 Term localTerm = term.DepthFirstSearch(rootTerm); #region Apply Commutative Law: Bubble Sort bool madeChanges; do { var list = localTerm.Args as List <object>; if (list == null) { throw new Exception("Cannot be null"); } int itemCount = list.Count; madeChanges = false; itemCount--; for (var i = 0; i < itemCount; i++) { list = localTerm.Args as List <object>; Debug.Assert(list != null); if (SatisfyCommutativeCondition(localTerm, list[i], list[i + 1])) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); object tempObj = cloneLst[i]; cloneLst[i] = cloneLst[i + 1]; cloneLst[i + 1] = tempObj; madeChanges = true; //generate trace rule string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Commutative); string rule = AlgebraRule.Rule(AlgebraRule.AlgebraRuleType.Commutative); string appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Commutative, list[i], list[i + 1]); rootTerm.GenerateTrace(localTerm, cloneTerm, kc, rule, appliedRule); localTerm = cloneTerm; } } } while (madeChanges); #endregion return(localTerm); }
public static object ApplyDistributive(this object obj, Term rootTerm) { //1*y+1*y -> (1+1)*y //1*y+2*y -> (1+2)*y //y+y+y -> (1+1+1)*y //a*y+y+x -> (a+1)*y+x //1*y^2+2*y^2 -> (1+2)*y^2 //x^2+x^2+x^2 -> (1+1+1)*x^2 //2*x^2+x^2+y -> (2+1)x^2+y //3*(x+1) -> 3x+3 //a*(x+1) -> ax+a //x*(a+1) -> xa + x //(a+1)*(x+1) -> TODO var term = obj as Term; if (term == null) { return(obj); } Term localTerm = term.DepthFirstSearch(rootTerm); var list = localTerm.Args as List <object>; if (list == null) { throw new Exception("Cannot be null"); } if (list.Count < 2) { return(localTerm); } bool madeChanges; do { list = localTerm.Args as List <object>; if (list == null) { throw new Exception("Cannot be null"); } int itemCount = list.Count; madeChanges = false; itemCount--; for (var i = 0; i < itemCount; i++) { list = localTerm.Args as List <object>; Debug.Assert(list != null); itemCount = list.Count; object obj1; if (i + 1 >= list.Count) { break; } if (SatisfyDistributiveCondition(term, list[i], list[i + 1], out obj1)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[i] = obj1; cloneLst.RemoveAt(i + 1); string kc = AlgebraRule.RuleConcept(AlgebraRule.AlgebraRuleType.Distributive); //generate trace rule string rule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Distributive); string appliedRule = AlgebraRule.Rule( AlgebraRule.AlgebraRuleType.Distributive, list[i], list[i + 1]); if (cloneLst.Count == 1) { cloneTerm = cloneLst[0] as Term; } rootTerm.GenerateTrace(localTerm, cloneTerm, kc, rule, appliedRule); localTerm = cloneTerm; madeChanges = true; } } } while (madeChanges); return(localTerm); }
/// <summary> /// true positive: y*1 -> y, y/1 -> y /// </summary> /// <param name="obj"></param> /// <param name="rootTerm"></param> /// <returns></returns> public static object ApplyIdentity(this object obj, Term rootTerm) { //x ->1*x //x+3 ->1*x+3 //x+x ->1*x+1*x //y+2*y ->1*y+2*y //x*y ->1*x*y var variable = obj as Var; if (variable != null) { return(new Term(Expression.Multiply, new List <object>() { 1, variable })); } var term = obj as Term; if (term == null) { return(obj); } Term localTerm = term.DepthFirstSearch(rootTerm); #region Apply Identity Law var list = localTerm.Args as List <object>; Debug.Assert(list != null); var lst = localTerm.Args as List <object>; Debug.Assert(lst != null); object gobj; for (int i = 0; i < lst.Count; i++) { if (SatisfyIdentityCondition1(localTerm, lst[i], out gobj)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[i] = gobj; //generate trace rule /* * string rule = AlgebraRule.Rule( * AlgebraRule.AlgebraRuleType.Identity, * list[i], null); * * rootTerm.GenerateTrace(localTerm, cloneTerm, rule); */ localTerm = cloneTerm; } } if (lst.Count >= 2) { if (SatisfyIdentityCondition2(localTerm, lst[0], lst[1], out gobj)) { var cloneTerm = localTerm.Clone(); var cloneLst = cloneTerm.Args as List <object>; Debug.Assert(cloneLst != null); cloneLst[0] = gobj; cloneLst.Remove(lst[1]); //generate trace rule /* * string rule = AlgebraRule.Rule( * AlgebraRule.AlgebraRuleType.Identity, * list[0], null); * * rootTerm.GenerateTrace(localTerm, cloneTerm, rule); */ localTerm = cloneTerm; } } #endregion return(localTerm); }
public void Test_Clone() { int a = 1; var b = new Var('b'); int c = 1; var lst = new List<object>() { a, b, c }; var term = new Term(Expression.Add, lst); var term1 = term.Clone(); var args = term.Args as List<object>; Assert.NotNull(args); args[0] = 2; var args1 = term1.Args as List<object>; Assert.NotNull(args1); Assert.True(args1[0].Equals(1)); }