// // Generate ALL maximal problems from the given start node (note, each incoming basic edge results in a maximal problem). // This gives soundness of generating problems from given nodes (current def of interesting problems), but lacks // completeness by not generating all of the subproblems along the way // // // From this node, generate all problems backward. // Do so by generating simple problems first (in a depth-first manner) // private List<Problem<Hypergraph.EdgeAnnotation>> GenerateAllMaximalProblemsFrom(ProblemHashMap<Hypergraph.EdgeAnnotation> memoizedProblems, HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, int node) { if (node == 118) { //Debug.WriteLine("NO-OP"); } // If we have already generated problems, no need to regenerate if (memoizedProblems.HasNodeBeenGenerated(node)) return memoizedProblems.Get(node); // For all edges, create base problems and add them all to the database List<PebblerHyperEdge<Hypergraph.EdgeAnnotation>> edges = edgeDatabase.GetBasedOnGoal(node); // If there are no edges, this is a 'root' node (has no predecessors) if (edges == null || !edges.Any()) { // We've successfully generated all the problems for this node: zero problems memoizedProblems.SetGenerated(node); return new List<Problem<Hypergraph.EdgeAnnotation>>(); } // // Create all the base problems consisting of only one edge and add to the database List<Problem<Hypergraph.EdgeAnnotation>> baseProblems = new List<Problem<Hypergraph.EdgeAnnotation>>(); foreach (PebblerHyperEdge<Hypergraph.EdgeAnnotation> edge in edges) { baseProblems.Add(new Problem<Hypergraph.EdgeAnnotation>(edge)); } // memoizedProblems.PutUnchecked(baseProblems); // For all of the base problems, generate backward foreach (Problem<Hypergraph.EdgeAnnotation> baseProblem in baseProblems) { GenerateMaximalProblemFromSingleEdge(memoizedProblems, edgeDatabase, baseProblem); } // We've successfully generated all the problems for this node memoizedProblems.SetGenerated(node); // Return all the generated problems return memoizedProblems.Get(node); }
// // Generates all forward directional problems using the template-based clauses from the pre-computation // private List<Problem<Hypergraph.EdgeAnnotation>> GenerateForwardProblems(List<GroundedClause> goalClauses, Pebbler.HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, int numGivens) { // System.Diagnostics.Debug.WriteLine("Forward"); List<int> clauseIndices = AcquireGoalIndices(goalClauses); // The resultant structure of problems; graph size dictates associated array size in hashMap; number of givens is a limiting factor the size of problems ProblemHashMap<Hypergraph.EdgeAnnotation> problems = new ProblemHashMap<Hypergraph.EdgeAnnotation>(edgeDatabase, graph.vertices.Count, numGivens); // Generate all the problems based on the node indices foreach (int goalNode in clauseIndices) { if (Utilities.PROBLEM_GEN_DEBUG) { System.Diagnostics.Debug.WriteLine("Template node; will generate problems (" + goalNode + "): " + graph.vertices[goalNode].data.ToString()); } pathGenerator.GenerateProblemsUsingBackwardPathToLeaves(problems, edgeDatabase, goalNode); } return FilterForMinimalAndRedundantProblems(problems.GetAll()); }
// // Given a start node, construct a path using reachability analysis to construct a path from start template node back to leaves. // Forward problems are generated by following forward edges in reverse // // A multimap of all pebbled edges (from pebbling) public void GenerateProblemsUsingBackwardPathToLeaves(ProblemHashMap<Hypergraph.EdgeAnnotation> memoizedProblems, HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, int goalNode) { // Although this returns the set of problems, we can still acquire them through the ProblemHashMap GenerateAllMaximalProblemsFrom(memoizedProblems, edgeDatabase, goalNode); }
// // For all given nodes in this problem, generate the single maximal problem // // This is done is a convluted way to speed up execution since we need to combine in the size of the powerset of cardinality of givens // private void GenerateMaximalProblemFromSingleEdge(ProblemHashMap<Hypergraph.EdgeAnnotation> memoizedProblems, HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, Problem<Hypergraph.EdgeAnnotation> baseProblem) { // Create all simple problems by pursuing only a single path backward in the givens: append // all problems from a given to the base problem // // | // v // given __ // | | // v | baseProblem // goal __| // // Acquire all of the problems for the singleton sets of the powerset for all of the givens of this problem List<Problem<Hypergraph.EdgeAnnotation>>[] singletonMapToNewProblems = new List<Problem<Hypergraph.EdgeAnnotation>>[baseProblem.givens.Count]; List<Problem<Hypergraph.EdgeAnnotation>>[] singletonMapToOriginalProblems = new List<Problem<Hypergraph.EdgeAnnotation>>[baseProblem.givens.Count]; bool generatedNewProblems = false; for (int g = 0; g < baseProblem.givens.Count; g++) { // Acquire the original problems and save them singletonMapToOriginalProblems[g] = GenerateAllMaximalProblemsFrom(memoizedProblems, edgeDatabase, baseProblem.givens[g]); if (singletonMapToOriginalProblems[g] == null) singletonMapToOriginalProblems[g] = new List<Problem<Hypergraph.EdgeAnnotation>>(); // Using the original problems, append them to the base problem singletonMapToNewProblems[g] = new List<Problem<Hypergraph.EdgeAnnotation>>(); // Append all of these given problems to the base problem foreach (Problem<Hypergraph.EdgeAnnotation> problem in singletonMapToOriginalProblems[g]) { Problem<Hypergraph.EdgeAnnotation> baseProblemCopy = new Problem<Hypergraph.EdgeAnnotation>(baseProblem); baseProblemCopy.Append(graph, edgeDatabase, problem); //memoizedProblems.Put(baseProblemCopy); singletonMapToNewProblems[g].Add(baseProblemCopy); generatedNewProblems = true; } } if (baseProblem.goal == 98) { //Debug.WriteLine("98NO-OP"); } // If we did not perform any appending, we have reached a maximal situation // Add the maximal problem to the database if (!generatedNewProblems) { // Determine suppression now to mitigate number of problems added baseProblem.DetermineSuppressedGivens(graph); memoizedProblems.Put(baseProblem); return; } // // Stitch together all of the possible combinations of maximal problems // // | | | // | | | // v v v // g_1 g_2 ... g_n __ // | | baseProblem // v | // target __| // // // We are looking for the maximal set of problems; therefore, we don't need all combinations. // What we do require is the combining of all generated problems with the base problem. // // Find all the sets of populated new problems List<int> populatedIndices = new List<int>(); for (int index = 0; index < singletonMapToNewProblems.Length; index++) { if (singletonMapToNewProblems[index].Any()) populatedIndices.Add(index); } List<Problem<Hypergraph.EdgeAnnotation>> maximalProblems = new List<Problem<Hypergraph.EdgeAnnotation>>(singletonMapToNewProblems[populatedIndices[0]]); populatedIndices.RemoveAt(0); foreach (int index in populatedIndices) { //int count = 0; List<Problem<Hypergraph.EdgeAnnotation>> tmpMaximalProbs = new List<Problem<Hypergraph.EdgeAnnotation>>(); foreach (Problem<Hypergraph.EdgeAnnotation> singleton in singletonMapToOriginalProblems[index]) { foreach (Problem<Hypergraph.EdgeAnnotation> problem in maximalProblems) { //if (baseProblem.goal == 98) //{ // Debug.WriteLine(count++); //} Problem<Hypergraph.EdgeAnnotation> problemCopy = new Problem<Hypergraph.EdgeAnnotation>(problem); // It is possible for a problem to have been created which deduced further information with an additional edge; // that is, a given node was pushed into the path of the problem. Hence, no need to append in this situation if (problem.givens.Contains(singleton.goal)) { problemCopy.Append(graph, edgeDatabase, singleton); } tmpMaximalProbs.Add(problemCopy); } } maximalProblems = tmpMaximalProbs; } // Add all the maximal problems to the database foreach (Problem<Hypergraph.EdgeAnnotation> problem in maximalProblems) { // Determine suppression now to mitigate number of problems added problem.DetermineSuppressedGivens(graph); memoizedProblems.Put(problem); } }
// // For all given nodes in this problem, generate all problems // // This is done is a convluted way to speed up execution since we need to combine in the size of the powerset of cardinality of givens // private void GenerateAllProblemsFromSingleEdge(ProblemHashMap<Hypergraph.EdgeAnnotation> memoizedProblems, HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, Problem<Hypergraph.EdgeAnnotation> baseProblem) { // Create all simple problems by pursuing only a single path backward in the givens: append // all problems from a given to the base problem // // | // v // given __ // | | // v | baseProblem // goal __| // // Acquire all of the problems for the singleton sets of the powerset for all of the givens of this problem List<Problem<Hypergraph.EdgeAnnotation>>[] singletonMapToNewProblems = new List<Problem<Hypergraph.EdgeAnnotation>>[baseProblem.givens.Count]; List<Problem<Hypergraph.EdgeAnnotation>>[] singletonMapToOriginalProblems = new List<Problem<Hypergraph.EdgeAnnotation>>[baseProblem.givens.Count]; for (int g = 0; g < baseProblem.givens.Count; g++) { // Acquire the original problems and save them singletonMapToOriginalProblems[g] = GenerateAllProblemsFrom(memoizedProblems, edgeDatabase, baseProblem.givens[g]); if (singletonMapToOriginalProblems[g] == null) singletonMapToOriginalProblems[g] = new List<Problem<Hypergraph.EdgeAnnotation>>(); // Using the original problems, append them to the base problem singletonMapToNewProblems[g] = new List<Problem<Hypergraph.EdgeAnnotation>>(); // Append all of these given problems to the base problem foreach (Problem<Hypergraph.EdgeAnnotation> problem in singletonMapToOriginalProblems[g]) { Problem<Hypergraph.EdgeAnnotation> baseProblemCopy = new Problem<Hypergraph.EdgeAnnotation>(baseProblem); baseProblemCopy.Append(graph, edgeDatabase, problem); memoizedProblems.Put(baseProblemCopy); singletonMapToNewProblems[g].Add(baseProblemCopy); } } // If there was only 1 given, we need to perform a powerset combining if (baseProblem.givens.Count == 1) return; // // Stitch together all of the possible combinations of problems that will result; // note this is a POWERSET construction of all possible problems; hence, note exponential explosion in number of problems // // | | // | | // v v // g_1 g_2 ... g_n __ // | | baseProblem // v | // target __| // // | | // | | // v v // g_1 g_2 ... g_n __ // | | baseProblem // v | // target __| // // | | | // | | | // v v v // g_1 g_2 ... g_n __ // | | baseProblem // v | // target __| // // Acquire an encoded list of subsets: the powerset for the number of givens in this problem List<string> powerset = Utilities.ConstructPowerSetStringsWithNoEmpty(baseProblem.givens.Count, baseProblem.givens.Count); // <-- We avoid generating singleton sets // Maps a subset string representation (from the powerset) to the list of problems that it results in. Dictionary<string, List<Problem<Hypergraph.EdgeAnnotation>>> powersetMapToProblems = new Dictionary<string, List<Problem<Hypergraph.EdgeAnnotation>>>(powerset.Count); // // For every combination of possible problems (a subset of the powerset), we combine problems // // Note, the Utilities generated the powerset in the specific sorted ordering of lower cardinality sets first (also values in subset are increasing) // So a typical subset string is given by 012 or 023 foreach (string subset in powerset) { // Break the subset string into its constituent elements: <Arbitrary subset, singleton> KeyValuePair<string, int> splitSubset = Utilities.SplitStringIntoKnownToProcess(subset); // Subset Problems; given the subset {012}: {01} List<Problem<Hypergraph.EdgeAnnotation>> subsetProblems; if (!powersetMapToProblems.TryGetValue(splitSubset.Key, out subsetProblems)) { // Use the singleton list; ASCII conversion of char to int subsetProblems = singletonMapToNewProblems[Convert.ToInt32(splitSubset.Key)]; } // Singleton tails; given the subset {012}: {2} List<Problem<Hypergraph.EdgeAnnotation>> singletonProblems = singletonMapToOriginalProblems[splitSubset.Value]; // Combine the precomputed powerset subset (.Key) guiding the appending of the singleton (.Value) problems List<Problem<Hypergraph.EdgeAnnotation>> combinedSubsetProblems = new List<Problem<Hypergraph.EdgeAnnotation>>(); foreach (Problem<Hypergraph.EdgeAnnotation> subsetProblem in subsetProblems) { foreach (Problem<Hypergraph.EdgeAnnotation> singletonProb in singletonProblems) { // It is possible for a problem to have been created which deduced further information with an additional edge; // that is, a given node was pushed into the path of the problem. Hence, no need to append in this situation if (subsetProblem.givens.Contains(singletonProb.goal)) { // Combine the two problems and record Problem<Hypergraph.EdgeAnnotation> subsetProblemCopy = new Problem<Hypergraph.EdgeAnnotation>(subsetProblem); subsetProblemCopy.Append(graph, edgeDatabase, singletonProb); memoizedProblems.Put(subsetProblemCopy); combinedSubsetProblems.Add(subsetProblemCopy); } } } // We have calculated the problems for this subset, keep track of them powersetMapToProblems.Add(subset, combinedSubsetProblems); } }
private List<Problem<Hypergraph.EdgeAnnotation>> GenerateBackwardProblems(List<GroundedClause> goalClauses, Pebbler.HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase) { System.Diagnostics.Debug.WriteLine("Backward"); List<int> clauseIndices = AcquireGoalIndices(goalClauses); // The resultant structure of problems; graph size dictates associated array size in hashMap; number of givens is a limiting factor the size of problems // Problem generation limits the number of givens in BACKWARD problems to 4 (or the constant in the HashMap structure) ProblemHashMap<Hypergraph.EdgeAnnotation> problems = new ProblemHashMap<Hypergraph.EdgeAnnotation>(edgeDatabase, graph.vertices.Count); // Generate all the problems based on the node indices foreach (int goalNode in clauseIndices) { if (Utilities.PROBLEM_GEN_DEBUG) { System.Diagnostics.Debug.WriteLine("Template node; will generate problems (" + goalNode + "): " + graph.vertices[goalNode].data.ToString()); } pathGenerator.GenerateProblemsUsingBackwardPathToLeaves(problems, edgeDatabase, goalNode); } // Filter backward problems so that only problems with goal being the original figure givens persist. return FilterBackwardProblems(clauseIndices, FilterForMinimalAndRedundantProblems(problems.GetAll())); }