public Pebbler(Hypergraph.Hypergraph<GeometryTutorLib.ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> graph, PebblerHypergraph<ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> pGraph) { this.graph = graph; this.pebblerGraph = pGraph; forwardPebbledEdges = new HyperEdgeMultiMap<Hypergraph.EdgeAnnotation>(pGraph.vertices.Length); backwardPebbledEdges = new HyperEdgeMultiMap<Hypergraph.EdgeAnnotation>(pGraph.vertices.Length); forwardPebbledEdges.SetOriginalHypergraph(graph); backwardPebbledEdges.SetOriginalHypergraph(graph); }
// // The combination of new information may lead to other given information being deducible // // // foreach given in the problem // find all edges with target given // foreach edge with target with given // if (all of the source nodes in edge are in the given OR path) then // if this is a minimal edge (fewer sources better) then // save edge // if (found edge) then // AddEdge to problem // move target given to path // private void PerformDeducibilityCheck(HyperEdgeMultiMap <A> edgeDatabase) { // All the givens and path nodes for this problem; this includes the new edgeSources List <int> problemGivensAndPath = new List <int>(this.givens); problemGivensAndPath.AddRange(this.path); // foreach given in the problem List <int> tempGivens = new List <int>(this.givens); // Make a copy because we may be modifying it below foreach (int given in tempGivens) { PebblerHyperEdge <A> savedEdge = null; // find all edges with target given List <PebblerHyperEdge <A> > forwardEdges = edgeDatabase.GetBasedOnGoal(given); if (forwardEdges != null) { // foreach edge with target with given foreach (PebblerHyperEdge <A> edge in forwardEdges) { // if (all of the source nodes in edge are in the given OR path) then if (Utilities.Subset <int>(problemGivensAndPath, edge.sourceNodes)) { // if this is a minimal edge (fewer sources better) then if (savedEdge == null) { savedEdge = edge; } else if (edge.sourceNodes.Count < savedEdge.sourceNodes.Count) { savedEdge = edge; } } } if (savedEdge != null) { // if (Utilities.PROBLEM_GEN_DEBUG) System.Diagnostics.Debug.WriteLine("CTA: Found another edge which can deduce givens." + savedEdge); // Add the found edge to the problem this.AddEdge(savedEdge); // move target given to path: (1) remove from givens; (2) add to path this.givens.Remove(savedEdge.targetNode); Utilities.AddUnique <int>(this.path, savedEdge.targetNode); } } } }
// // 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); }
// // COMPELTE POWERSET implementation // // Time consuming, but complete. // // // From this node, generate all problems backward. // Do so by generating simple problems first (in a depth-first manner) // private List <Problem <Hypergraph.EdgeAnnotation> > GenerateAllProblemsFrom(ProblemHashMap <Hypergraph.EdgeAnnotation> memoizedProblems, HyperEdgeMultiMap <Hypergraph.EdgeAnnotation> edgeDatabase, int node) { // 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> > forwardEdges = edgeDatabase.GetBasedOnGoal(node); // If there are no edges, this is a 'root' node (has no predecessors) if (forwardEdges == null || !forwardEdges.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 forwardEdges) { 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) { GenerateAllProblemsFromSingleEdge(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)); }
// // Given a node, pebble the reachable parts of the graph (in the forward direction) // We pebble in a breadth first manner // private void ForwardTraversal(HyperEdgeMultiMap<Hypergraph.EdgeAnnotation> edgeDatabase, List<int> nodesToPebble) { List<int> worklist = new List<int>(nodesToPebble); // // Pebble until the list is empty // while (worklist.Any()) { // Acquire the next value to consider int currentNodeIndex = worklist[0]; worklist.RemoveAt(0); // Pebble the current node as a forward node and percolate forward pebblerGraph.vertices[currentNodeIndex].pebbled = true; // For all hyperedges leaving this node, mark a pebble along the arc foreach (PebblerHyperEdge<Hypergraph.EdgeAnnotation> currentEdge in pebblerGraph.vertices[currentNodeIndex].edges) { if (!Utilities.RESTRICTING_AXS_DEFINITIONS_THEOREMS || (Utilities.RESTRICTING_AXS_DEFINITIONS_THEOREMS && currentEdge.annotation.IsActive())) { if (!currentEdge.IsFullyPebbled()) { // Indicate the node has been pebbled by adding to the list of pebbled vertices; should not have to be a unique addition Utilities.AddUnique<int>(currentEdge.sourcePebbles, currentNodeIndex); // With this new node, check if the edge is full pebbled; if so, percolate if (currentEdge.IsFullyPebbled()) { // Has the target of this edge been pebbled previously? Pebbled -> Pebbled means we have a backward edge if (!IsNodePebbled(currentEdge.targetNode)) { // Success, we have an edge // Construct a static set of pebbled hyperedges for problem construction edgeDatabase.Put(currentEdge); // Add this node to the worklist to percolate further if (!worklist.Contains(currentEdge.targetNode)) { worklist.Add(currentEdge.targetNode); worklist.Sort(); } } } } } } } }
// // 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); } }
// // 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); }
// // 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); } }
// // Create a new problem based on thisProblem and thatProblem in accordance with the above comments (repeated here) // // This problem { This Givens } { This Path } -> This Goal // The new problem is of the form: { That Givens } { That Path } -> Goal // Combined: { New Givens U This Givens \minus This Goal} {This Path U This Goal } -> Goal // public void Append(Hypergraph.Hypergraph <ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> graph, HyperEdgeMultiMap <A> forwardEdges, Problem <A> thatProblem) { if (thatProblem.goal == -1) { throw new ArgumentException("Attempt to append with an empty problem " + this + " " + thatProblem); } // // If this is an empty problem, populate it like a copy constructor and return // if (this.goal == -1) { givens = new List <int>(thatProblem.givens); goal = thatProblem.goal; path = new List <int>(thatProblem.path); edges = new List <PebblerHyperEdge <A> >(thatProblem.edges); suppressedGivens = new List <int>(thatProblem.suppressedGivens); thatProblem.edges.ForEach(edge => this.AddEdge(edge)); return; } // // Standard appending of an existent problem to another existent problem // if (!this.givens.Contains(thatProblem.goal)) { throw new ArgumentException("Attempt to append problems that do not connect goal->given" + this + " " + thatProblem); } // Degenerate by removing the new problem goal from THIS source node. this.givens.Remove(thatProblem.goal); // Add the 'new problem' goal node to the path of the new Problem (uniquely) Utilities.AddUnique <int>(this.path, thatProblem.goal); // Add the path nodes to THIS path Utilities.AddUniqueList <int>(this.path, thatProblem.path); // Add all the new sources to the degenerated old sources; do so uniquely Utilities.AddUniqueList <int>(this.givens, thatProblem.givens); Utilities.AddUniqueList <int>(this.suppressedGivens, thatProblem.suppressedGivens); // Add all of the edges of that problem to this problem; this also adds to the problem graph thatProblem.edges.ForEach(edge => this.AddEdge(edge)); if (this.ContainsCycle()) { throw new Exception("Problem contains a cycle" + this.graph.GetStronglyConnectedComponentDump()); // Remove an edge from this problem? } // Now, if there exists a node in the path AND in the givens, remove it from the givens. foreach (int p in this.path) { if (this.givens.Remove(p)) { // if (Utilities.PROBLEM_GEN_DEBUG) System.Diagnostics.Debug.WriteLine("A node existed in the path AND givens (" + p + "); removing from givens"); } } PerformDeducibilityCheck(forwardEdges); }
public Pebbler(PebblerHypergraph<ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> hypergraph) { pebblerGraph = hypergraph; forwardPebbledEdges = new HyperEdgeMultiMap<Hypergraph.EdgeAnnotation>(hypergraph.vertices.Length); backwardPebbledEdges = new HyperEdgeMultiMap<Hypergraph.EdgeAnnotation>(hypergraph.vertices.Length); }