From 069b2df9b9a54bee5161b68d15794affcee8917f Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 7 Apr 2016 17:18:24 +0200
Subject: [PATCH] naive nonlinear tree pattern matching

---
 .../src/arbology/exact/ExactPatternMatch.cpp  | 57 +++++++++++++++++--
 .../src/arbology/exact/ExactPatternMatch.h    |  4 ++
 .../src/arbology/exact/ExactSubtreeMatch.cpp  |  4 +-
 alib2data/src/tree/TreeFeatures.h             |  2 +
 4 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/alib2algo/src/arbology/exact/ExactPatternMatch.cpp b/alib2algo/src/arbology/exact/ExactPatternMatch.cpp
index 2d49e42933..5b5b0a7d40 100644
--- a/alib2algo/src/arbology/exact/ExactPatternMatch.cpp
+++ b/alib2algo/src/arbology/exact/ExactPatternMatch.cpp
@@ -9,6 +9,7 @@
 #include <exception/AlibException.h>
 #include <tree/ranked/RankedTree.h>
 #include <tree/ranked/RankedPattern.h>
+#include <tree/ranked/RankedNonlinearPattern.h>
 #include <tree/ranked/PrefixRankedTree.h>
 #include <tree/ranked/PrefixRankedPattern.h>
 #include <tree/ranked/PrefixRankedBarTree.h>
@@ -16,6 +17,7 @@
 #include <tree/unranked/UnrankedTree.h>
 #include <tree/unranked/UnrankedPattern.h>
 #include "SubtreeJumpTable.h"
+#include "ExactSubtreeRepeatsNaive.h"
 
 #include <deque>
 #include <foreach>
@@ -35,7 +37,7 @@ bool ExactPatternMatch::matchHelper ( const tree::UnrankedNode & subject, const
 
 	if ( subject.getChildren ( ).size ( ) != pattern.getChildren ( ).size ( ) ) return false;
 
-	for ( const std::tuple < const tree::UnrankedNode *, const tree::UnrankedNode * > & childs : std::make_pair_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
+	for ( const std::tuple < const tree::UnrankedNode *, const tree::UnrankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
 		if ( !matchHelper ( * std::get < 0 > ( childs ), * std::get < 1 > ( childs ), subtreeVariable ) ) return false;
 
 	return true;
@@ -47,12 +49,32 @@ bool ExactPatternMatch::matchHelper ( const tree::RankedNode & subject, const tr
 	if ( subject.getSymbol ( ) != pattern.getSymbol ( ) ) return false;
 
 	 // ranked symbols are the same; test for number of children is not needed
-	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_pair_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
+	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
 		if ( !matchHelper ( * std::get < 0 > ( childs ), * std::get < 1 > ( childs ), subtreeVariable ) ) return false;
 
 	return true;
 }
 
+bool ExactPatternMatch::matchHelper ( const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable, const std::set < alphabet::RankedSymbol > & nonlinearVariables, const tree::RankedNode & repeats, std::map < alphabet::RankedSymbol, alphabet::Symbol > & variablesSetting ) {
+	if ( pattern.getSymbol ( ) == subtreeVariable ) return true;
+
+	if ( nonlinearVariables.count ( pattern.getSymbol ( ) ) ) {
+		auto setting = variablesSetting.find ( pattern.getSymbol ( ) );
+
+		if ( ( setting != variablesSetting.end ( ) ) && ( repeats.getSymbol ( ).getSymbol ( ) != setting->second ) ) return false;
+
+		if ( setting == variablesSetting.end ( ) ) variablesSetting.insert ( std::make_pair ( pattern.getSymbol ( ), repeats.getSymbol ( ).getSymbol ( ) ) );
+	}
+
+	if ( subject.getSymbol ( ) != pattern.getSymbol ( ) ) return false;
+
+	 // ranked symbols are the same; test for number of children is not needed
+	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), pattern.getChildren ( ), repeats.getChildren ( ) ) )
+		if ( !matchHelper ( * std::get < 0 > ( childs ), * std::get < 1 > ( childs ), subtreeVariable, nonlinearVariables, * std::get < 2 > ( childs ), variablesSetting ) ) return false;
+
+	return true;
+}
+
 void ExactPatternMatch::matchInternal ( unsigned & index, std::set < unsigned > & occ, const tree::UnrankedNode & subject, const tree::UnrankedNode & pattern, const alphabet::Symbol & subtreeVariable ) {
 	if ( matchHelper ( subject, pattern, subtreeVariable ) ) occ.insert ( index );
 
@@ -71,6 +93,17 @@ void ExactPatternMatch::matchInternal ( unsigned & index, std::set < unsigned >
 		matchInternal ( index, occ, * child, pattern, subtreeVariable );
 }
 
+void ExactPatternMatch::matchInternal ( unsigned & index, std::set < unsigned > & occ, const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable, const std::set < alphabet::RankedSymbol > & nonlinearVariables, const tree::RankedNode & repeats ) {
+	std::map < alphabet::RankedSymbol, alphabet::Symbol > variablesSetting;
+
+	if ( matchHelper ( subject, pattern, subtreeVariable, nonlinearVariables, repeats, variablesSetting ) ) occ.insert ( index );
+
+	index++;
+
+	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), repeats.getChildren ( ) ) )
+		matchInternal ( index, occ, * std::get < 0 > ( childs ), pattern, subtreeVariable, nonlinearVariables, * std::get < 1 > ( childs ) );
+}
+
 std::set < unsigned > ExactPatternMatch::match ( const tree::UnrankedTree & subject, const tree::UnrankedPattern & pattern ) {
 	unsigned i = 0;
 	std::set < unsigned > occ;
@@ -79,7 +112,7 @@ std::set < unsigned > ExactPatternMatch::match ( const tree::UnrankedTree & subj
 	return occ;
 }
 
-auto ExactPatternMatchUnrankedTree = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::UnrankedTree, tree::UnrankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
+auto ExactPatternMatchUnrankedPattern = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::UnrankedTree, tree::UnrankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
 
 std::set < unsigned > ExactPatternMatch::match ( const tree::RankedTree & subject, const tree::RankedPattern & pattern ) {
 	unsigned i = 0;
@@ -89,7 +122,19 @@ std::set < unsigned > ExactPatternMatch::match ( const tree::RankedTree & subjec
 	return occ;
 }
 
-auto ExactPatternMatchRankedTree = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::RankedTree, tree::RankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
+auto ExactPatternMatchRankedPattern = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::RankedTree, tree::RankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
+
+std::set < unsigned > ExactPatternMatch::match ( const tree::RankedTree & subject, const tree::RankedNonlinearPattern & pattern ) {
+	unsigned i = 0;
+	std::set < unsigned > occ;
+
+	tree::RankedTree repeats = ExactSubtreeRepeatsNaive::repeats ( subject );
+
+	matchInternal ( i, occ, subject.getRoot ( ), pattern.getRoot ( ), pattern.getSubtreeWildcard ( ), pattern.getNonlinearVariables ( ), repeats.getRoot ( ) );
+	return occ;
+}
+
+auto ExactPatternMatchRankedNonlinearPattern = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::RankedTree, tree::RankedNonlinearPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
 
 std::set < unsigned > ExactPatternMatch::match ( const tree::PrefixRankedTree & subject, const tree::PrefixRankedPattern & pattern ) {
 	std::vector < int > subjectSubtreeJumpTable = SubtreeJumpTable::compute ( subject );
@@ -116,7 +161,7 @@ std::set < unsigned > ExactPatternMatch::match ( const tree::PrefixRankedTree &
 	return occ;
 }
 
-auto ExactPatternMatchPrefixRankedTree = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::PrefixRankedTree, tree::PrefixRankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
+auto ExactPatternMatchPrefixRankedPattern = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::PrefixRankedTree, tree::PrefixRankedPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
 
 std::set < unsigned > ExactPatternMatch::match ( const tree::PrefixRankedBarTree & subject, const tree::PrefixRankedBarPattern & pattern ) {
 	std::vector < int > subjectSubtreeJumpTable = SubtreeJumpTable::compute ( subject );
@@ -145,7 +190,7 @@ std::set < unsigned > ExactPatternMatch::match ( const tree::PrefixRankedBarTree
 	return occ;
 }
 
-auto ExactPatternMatchPrefixRankedBarTree = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::PrefixRankedBarTree, tree::PrefixRankedBarPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
+auto ExactPatternMatchPrefixRankedBarPattern = ExactPatternMatch::RegistratorWrapper < std::set < unsigned >, tree::PrefixRankedBarTree, tree::PrefixRankedBarPattern > ( ExactPatternMatch::getInstance ( ), ExactPatternMatch::match );
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/arbology/exact/ExactPatternMatch.h b/alib2algo/src/arbology/exact/ExactPatternMatch.h
index 4caec9421d..1bcc858438 100644
--- a/alib2algo/src/arbology/exact/ExactPatternMatch.h
+++ b/alib2algo/src/arbology/exact/ExactPatternMatch.h
@@ -14,6 +14,7 @@
 #include <tree/unranked/UnrankedNode.h>
 #include <set>
 #include <core/multipleDispatch.hpp>
+#include <alphabet/RankedSymbol.h>
 
 namespace arbology {
 
@@ -29,15 +30,18 @@ public:
 
 	static std::set < unsigned > match ( const tree::UnrankedTree & subject, const tree::UnrankedPattern & pattern );
 	static std::set < unsigned > match ( const tree::RankedTree & subject, const tree::RankedPattern & pattern );
+	static std::set < unsigned > match ( const tree::RankedTree & subject, const tree::RankedNonlinearPattern & pattern );
 	static std::set < unsigned > match ( const tree::PrefixRankedTree & subject, const tree::PrefixRankedPattern & pattern );
 	static std::set < unsigned > match ( const tree::PrefixRankedBarTree & subject, const tree::PrefixRankedBarPattern & pattern );
 
 private:
 	static bool matchHelper ( const tree::UnrankedNode & subject, const tree::UnrankedNode & pattern, const alphabet::Symbol & subtreeVariable );
 	static bool matchHelper ( const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable );
+	static bool matchHelper ( const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable, const std::set < alphabet::RankedSymbol > & nonlinearVariables, const tree::RankedNode & repeats, std::map < alphabet::RankedSymbol, alphabet::Symbol > & variablesSetting );
 
 	static void matchInternal ( unsigned & index, std::set < unsigned > & occ, const tree::UnrankedNode & subject, const tree::UnrankedNode & pattern, const alphabet::Symbol & subtreeVariable );
 	static void matchInternal ( unsigned & index, std::set < unsigned > & occ, const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable );
+	static void matchInternal ( unsigned & index, std::set < unsigned > & occ, const tree::RankedNode & subject, const tree::RankedNode & pattern, const alphabet::RankedSymbol & subtreeVariable, const std::set < alphabet::RankedSymbol > & nonlinearVariables, const tree::RankedNode & subjectRepeats );
 
 public:
 	static ExactPatternMatch & getInstance ( ) {
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
index fd29de4a55..25768ec1b2 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatch.cpp
@@ -28,7 +28,7 @@ bool ExactSubtreeMatch::matchHelper ( const tree::UnrankedNode & subject, const
 
 	if ( subject.getChildren ( ).size ( ) != pattern.getChildren ( ).size ( ) ) return false;
 
-	for ( const std::tuple < const tree::UnrankedNode *, const tree::UnrankedNode * > & childs : std::make_pair_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
+	for ( const std::tuple < const tree::UnrankedNode *, const tree::UnrankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
 		if ( !matchHelper ( * std::get < 0 > ( childs ), * std::get < 1 > ( childs ) ) ) return false;
 
 	return true;
@@ -38,7 +38,7 @@ bool ExactSubtreeMatch::matchHelper ( const tree::RankedNode & subject, const tr
 	if ( subject.getSymbol ( ) != pattern.getSymbol ( ) ) return false;
 
 	 // ranked symbols are the same; test for number of children is not needed
-	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_pair_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
+	for ( const std::tuple < const tree::RankedNode *, const tree::RankedNode * > & childs : std::make_tuple_foreach ( subject.getChildren ( ), pattern.getChildren ( ) ) )
 		if ( !matchHelper ( * std::get < 0 > ( childs ), * std::get < 1 > ( childs ) ) ) return false;
 
 	return true;
diff --git a/alib2data/src/tree/TreeFeatures.h b/alib2data/src/tree/TreeFeatures.h
index 60737ab718..4d8bd71280 100644
--- a/alib2data/src/tree/TreeFeatures.h
+++ b/alib2data/src/tree/TreeFeatures.h
@@ -28,12 +28,14 @@ class TreeBase;
 
 class RankedTree;
 class RankedPattern;
+class RankedNonlinearPattern;
 class PrefixRankedTree;
 class PrefixRankedBarTree;
 class PrefixRankedPattern;
 class PrefixRankedBarPattern;
 class UnrankedTree;
 class UnrankedPattern;
+class UnrankedNonlinearPattern;
 
 class RankedNode;
 class UnrankedNode;
-- 
GitLab