aboutsummaryrefslogtreecommitdiff
path: root/forest/src/iter/plan.org
diff options
context:
space:
mode:
Diffstat (limited to 'forest/src/iter/plan.org')
-rw-r--r--forest/src/iter/plan.org187
1 files changed, 187 insertions, 0 deletions
diff --git a/forest/src/iter/plan.org b/forest/src/iter/plan.org
new file mode 100644
index 0000000..4ef7db1
--- /dev/null
+++ b/forest/src/iter/plan.org
@@ -0,0 +1,187 @@
+#+TITLE: Plan for querying
+#+AUTHOR: बुबोधयिषुः
+#+DATE: <2024-01-11 Jeu 11:40>
+
+* Basic plan
+
+Basically speaking, we are trying to solve a subgraph isomorphism
+problem, but for parse forests only. Moreover, each pattern node
+specifies some condition that the target node should satisfy, like the
+rule number, the grammar node number et cetera. This simply acts like
+the filtering algorithms employed by the general subgraph isomorphism
+algorithms.
+
+There is however one difference from the original problem:
+
+#+begin_quote
+Edges might be matched by paths.
+#+end_quote
+
+This means that some edges in the pattern graph could be matched by
+paths in the (directed) target graph. Moreover, some edges require to
+be siblings of some previously matched edges. This poses some
+traditionally missing contraints.
+
+But anyways, we can consult the backtracing algorithms that were
+written for the general problem to have an idea how to solve our
+specific variant of the problem.
+
+** Filtering
+
+Our pattern nodes already specify some conditions for the target nodes
+to match. So it is worth condidering whether or not we employ some
+more powerful filtering techniques, like the iterative strenghthening
+of the subgraph-isomorphism-compatible-labels algorithm. This can be
+simply adapted to our situation since we have a natural candidate for
+the labels: the pattern nodes have the matching conditions as labels,
+whereas the target nodes have labels that are either grammar nodes or
+rule numbers. We can define a partial order on this set of labels by
+requiring that a matching condition is less than or equal to a target
+label if and only if that target label satisfies the matching
+condition.
+
+Then we simply apply the iterative strenghthening procedure, by
+forming, from the label \(L\), the new label \(L\times N(L)\), where
+\(N(L)\) is the function that sends each node \(n\) to the /multiset/
+\(\{L(m) \mid \text{Adj}(m, n)\}\), where \(\text{Adj}\) means that
+the two nodes are adjacent. And we say that a multiset \(m_1\) is less
+than or equal to another multiset \(m_2\) if and only if the bipartite
+graph formed from these two multisets have a matching covering every
+vertex corresponding to elements in \(m_1\). Note that this bipartite
+graph has as nodes \(N_x^i\) for every \(x\in m_1\), where \(i = 0, \ldots,
+m_1(x)\) and \(m_1(x)\) is the multiplicity of \(x\) in \(m_1\). Also
+two nodes \(N_x^i\) and \(N_y^j\), where \(x\in m_1\) and \(y\in m_2\) are
+adjacent if and only if \(x\leq y\). We can prove that if \(L\) is
+subgraph-isomorphism-compatible, then this new label \(L\times N(L)\) is
+also subgraph-isomorphism-compatible.
+
+As a consequence, we can iteratively construct new labels to filter
+out wrong candidate pairs of pattern nodes and target nodes, until
+this procedure does not yield stronger labels, which are guaranteed to
+happen in polynomial time.
+
+** General sketch
+
+Since our starting label is already domain-specific, it might be
+anticipated that this procedure can enhance the performance of the
+algorithm a lot. This is the general sketch of the algorithm.
+
+* Two difficulties
+
+** When a branch is exhausted, how should we switch to another branch?
+
+To solve this issue, we need a data type with the following methods:
+
+- Follow nodes in the depth-first order
+- Enumerate and switch to a specific "world line" in the forest: that
+ is, a forest is a pack of trees, and we match against each tree
+ separately; when a tree cannot be matched, we switch to the next
+ tree.
+
+All of this should be implemented efficiently, that is, within a
+constant and "small" amount of operations.
+
+For now, the plan is to preprocess the forest to store the information
+about each packed node in advance, and then the world line is defined
+by which child of those packed nodes to use. Thus to switch world
+line, we just change an array of numbers, which is pretty efficient I
+suppose.
+
+** When a query cannot be matched, how should we fallback to a parent query?
+
+To solve this issue, we need a data type with the following methods:
+
+- Follow nodes in the depth-first order
+- Jump to the parent and restore the querying context that was stored
+ earlier.
+
+ We can consult the codes for general subgraph isomorphism problems
+ to implement this, since the general structure is the same.
+
+* Steps [1/4]
+
+** TO-THINK Preprocess the target graph
+
+The target needs to be preprocessed so that we know about the world
+lines in advance, and we can generate some supplemental graphs as well
+to facilitate the search.
+
+This may not be required anymore.
+
+** SOLVED Backtrack based on domains
+We need to keep track of the domains. Can we find better ways to do
+this?
+
+Maybe we can keep track of only the differences of the set of domains,
+where each domain is a bitset. For the functionality of bit-sets,
+[[https://docs.rs/bitset-core/latest/bitset_core/index.html][this crate]] is quite useful.
+
+Since this is an external crate, we may treat this feature as an
+optionally enabled feature, and by default we use ordinary arrays of
+booleans. The main advantage, in my opinion, provided by the external
+crate is its SIMD-awareness, so the default implementation should not
+lose exponential performance.
+
+A more serious problem is how to handle the packed nodes, or
+equivalently how to treat different trees packed inside a forest.
+Previously I was thinking of searching each packed tree separately,
+but this is not respecting the shared structures of these trees, so
+that we must waste a lot of efforts to search the same portions
+multiple times.
+
+A better approach could be to ignore all children of packed nodes, and
+treat the grand-chidlren of the packed nodes as their own children.
+This way we do not need to waste efforts, and we need no special
+treatment of different world-lines when searching.
+
+Here is a more formal description of the approach.
+
+- For each pattern vertex, associate a vector of target vertices,
+ initialized as a vector of vertices with the same boolean true
+ label of length the number of nodes of the target graph.
+- Repeat the following steps.
+- Find a pattern vertex with the smallest domain, tiebreaking by
+ randomly choosing one with the higher degree, excluding vertices
+ whose domains are either empty or singleton.
+ + If there is a vertex with empty domain, the pattern graph is not a
+ subgraph of the target graph.
+ + If every vertex has a singleton domain, return the found mapping.
+- Find a "suitable" target vertex with highest degree within the
+ domain of the chosen vertex.
+ + If none exists, then we go back to the previous association of
+ some target vertex to some pattern vertex, and exclude that target
+ vertex from the domain of that pattern vertex, and then repeat the
+ process again.
+ * If no previous association exists, this means we happen to
+ choose one pattern vertex that cannot be mapped to the target
+ graph at the first step, so we can simply stop the algorithm and
+ decide that the pattern graph is not a subgraph of the target
+ graph.
+- Record the mapping from the above pattern to the above target in the
+ list of associations, and filter other domains.
+ + We can filter by the degree.
+ + We can filter by the sequence of degrees of neighbors.
+
+** TODO Rapid restarts and no-good recording
+This is a highly important optional improvement.
+
+** TODO Connect with the rest of the package
+
+
+Now we want to connect the subgraph isomorphism solver with the rest
+of the package. This requires a mechanism to convert from user-input
+to a pattern graph, and then run the subgraph (isomorphism) solver to
+find a mapping from the pattern graph to the parse-graph.
+
+In addition, there are some other constraints that might be imposed by
+the user, such as to require that certain edges be siblings, or that
+certain edges be non-repeating (either for nodes or for edges) paths
+instead of plain edges.
+
+All these can be implemented at the filtering step as additional
+requirements other than the neighbourhood-preserving constraint.
+
+Also the user may expect the neighbour relation to be directed. I am
+not sure if this causes any trouble, but I need to deal with this
+correctly to avoid potential disasters.
+