// check if the grandson has the same list as its grandpa! private static bool sameAsGrandpa(Equation p, int ssd_idx) { // if p is in the first 2 layers, then he does not have grandpa if (p.get_depth() < 2) { return(false); } Equation grandpa = p.anncestors[1]; return(p.ssds[ssd_idx] == grandpa.ssds[ssd_idx]); }
// expand One Possible random equation List, define its ancestors, attribute, ssds and optr private static void expand(Equation father, out List <Equation> children) { children = new List <Equation>(); for (int i = 0; i < father.ssds.Count; i++) { SSD cur_ssd = father.ssds[i]; // expand curent ssd var cur_ssd_list = cur_ssd.expand(father.Attribute); for (int j = 0; j < cur_ssd_list.Count; j++) { Equation son = new Equation(); // ssds son.ssds = new List <SSD>(father.ssds); // change the i'th ssd to a new one. son.ssds[i] = cur_ssd_list[j]; // optr son.optr = new Dictionary <int, char>(father.optr); // attribute son.Attribute = inverse(father.Attribute); // ancestors son.anncestors = new List <Equation>(father.anncestors); son.anncestors.Insert(0, father); //* Cut branch Operation*/ // if same as grandpa: (means it goes back! ) then should be cut! if (sameAsGrandpa(son, i)) { continue; } // if the son's depth = 3, and son's ssds[i] == grandpa's ssds[i], then cut! if (father.get_depth() == 2 && son.ssds[i] == father.anncestors[0].ssds[i]) { continue; } children.Add(son); } } }
// Generate a puzzle, if found return true, else false public static bool GenerateSearch(ref Equation root, out Equation puzzle, int movMatch = 1) { root.Attribute = Action.Remove; puzzle = new Equation(); // Set up Open and Close Table List <Equation> Open = new List <Equation>(), Close = new List <Equation>(); // mark if the puzzle is found /* 深度优先搜索算法: */ //(1)把起始节点S 放到未扩展节点Open 表中。如果此节点为一目标节点,则得到一 //个解。 Open.Add(root); //(2)如果Open 为一空表,或ans_list数量超过一定范围,则失败退出。 while (Open.Count > 0) { //(3)把Open 中第一个节点n 从Open 表移到Closed 表。 Equation cur_equ = Open[0]; Open.RemoveAt(0); Close.Add(cur_equ); // Check if Open[0].depth < 2 * movMatch if (cur_equ.get_depth() > 2 * movMatch) { continue; } //(4)扩展节点n ,产生其全部(时间太长,如何改进)后裔,对后裔生成其祖先、属性,(检查是否与前序节点一样),并把它们放入Open 表的前端(末端的节点比前端 //的节点后移出)。如果没有后裔,则转向步骤(2)。 // 其中已经检查节点是否与祖父一样; List <Equation> children; randomExpand(cur_equ, out children); Open.InsertRange(0, children); //(5)如果后继节点中有任一个为目标节点,则求得一个解,判断其Attributes == Action.Remove && depth == 2*MovMatch, // 成功退出;否则,转向步骤(2)。 for (int i = 0; i < children.Count; i++) { Equation son = children[i]; // if "son" needs to be placed one match, algorithm continues! if (son.Attribute == Action.Place) { continue; } // if "son".depth != 2 * matches, then still not ending! if (son.get_depth() != 2 * movMatch) { continue; } // now check! if (isValidEqu(son)) { // Optional: check if the result are "strictly" valid if (matchDiff(ref root, ref son) != 2 * movMatch) { continue; } puzzle.ssds = new List <SSD>(son.ssds); puzzle.Attribute = Action.Remove; puzzle.optr = new Dictionary <int, char>(son.optr); return(true); } } } return(false); }
/* Search algorithm */ public static void Search(ref Equation root, out List <Equation> ans_list, int movMatch = 1, int max_ans_num = 10, double MAX_TIME = 3.0) { root.Attribute = Action.Remove; ans_list = new List <Equation>(); //start watch sw.Restart(); // Set up Open and Close Table List <Equation> Open = new List <Equation>(), Close = new List <Equation>(); /* 深度优先搜索算法: */ //(1)把起始节点S 放到未扩展节点Open 表中。如果此节点为一目标节点,则得到一 //个解。 Open.Add(root); if (isCorrect(root)) { ans_list.Add(root); } //(2)如果Open 为一空表,或ans_list数量超过一定范围,则失败退出。 while (Open.Count > 0 && ans_list.Count < max_ans_num) { // check timer if (sw.Elapsed.TotalSeconds > MAX_TIME) { sw.Stop(); return; } //(3)把Open 中第一个节点n 从Open 表移到Closed 表。 Equation cur_equ = Open[0]; Open.RemoveAt(0); Close.Add(cur_equ); // Check if Open[0].depth < 2 * movMatch if (cur_equ.get_depth() > 2 * movMatch) { continue; } //(4)扩展节点n ,产生其全部(时间太长,如何改进)后裔,对后裔生成其祖先、属性,(检查是否与前序节点一样),并把它们放入Open 表的前端(末端的节点比前端 //的节点后移出)。如果没有后裔,则转向步骤(2)。 // 其中已经检查节点是否与祖父一样; List <Equation> children; expand(cur_equ, out children); Open.InsertRange(0, children); //(5)如果后继节点中有任一个为目标节点,则求得一个解,判断其Attributes == Action.Remove && depth == 2*MovMatch, // 成功退出;否则,转向步骤(2)。 for (int i = 0; i < children.Count; i++) { Equation son = children[i]; // if "son" needs to be placed one match, algorithm continues! if (son.Attribute == Action.Place) { continue; } // if "son".depth != 2 * matches, then still not ending! if (son.get_depth() != 2 * movMatch) { continue; } // now check! if (isCorrect(son) && !exist(ref ans_list, ref son)) { ans_list.Add(son); } } } sw.Stop(); }