From cbdf1502f07ff52c1d082dc82c09784fc3120dc0 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 16 Apr 2019 09:03:24 +0200
Subject: [PATCH] add basic rte optimize functionality

---
 alib2algo/src/rte/simplify/RTEOptimize.cpp    |  23 +
 alib2algo/src/rte/simplify/RTEOptimize.h      | 101 +++
 .../rte/simplify/RTEOptimizeFormalPart.hpp    | 620 ++++++++++++++++++
 3 files changed, 744 insertions(+)
 create mode 100644 alib2algo/src/rte/simplify/RTEOptimize.cpp
 create mode 100644 alib2algo/src/rte/simplify/RTEOptimize.h
 create mode 100644 alib2algo/src/rte/simplify/RTEOptimizeFormalPart.hpp

diff --git a/alib2algo/src/rte/simplify/RTEOptimize.cpp b/alib2algo/src/rte/simplify/RTEOptimize.cpp
new file mode 100644
index 0000000000..4fcd6de81b
--- /dev/null
+++ b/alib2algo/src/rte/simplify/RTEOptimize.cpp
@@ -0,0 +1,23 @@
+/*
+ * RTEOptimize.cpp
+ *
+ *  Created on: 1. 4. 2019
+ *	  Author: Jan Travnicek
+ */
+
+#include "RTEOptimize.h"
+#include <registration/AlgoRegistration.hpp>
+
+namespace rte {
+
+namespace simplify {
+
+auto RTEOptimizeFormalRTE = registration::AbstractRegister < RTEOptimize, FormalRTE < >, const FormalRTE < > & > ( RTEOptimize::optimize, "rte" ).setDocumentation (
+"Implements a rte simplification algorithm that is transforming the regular expression to be smaller.\n\
+\n\
+@param rte the simplified rte\n\
+@return the simlified rte" );
+
+} /* namespace rte */
+
+} /* namespace simplify */
diff --git a/alib2algo/src/rte/simplify/RTEOptimize.h b/alib2algo/src/rte/simplify/RTEOptimize.h
new file mode 100644
index 0000000000..0b411f88b8
--- /dev/null
+++ b/alib2algo/src/rte/simplify/RTEOptimize.h
@@ -0,0 +1,101 @@
+/*
+ * RTEOptimize.h
+ *
+ *  Created on: 1. 4. 2019
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef _RTE_OPTIMIZE_H__
+#define _RTE_OPTIMIZE_H__
+
+#include <alib/algorithm>
+#include <alib/iterator>
+
+#include <rte/formal/FormalRTE.h>
+#include <rte/formal/FormalRTEElements.h>
+
+#include <exception/CommonException.h>
+
+namespace rte {
+
+namespace simplify {
+
+class RTEOptimize {
+public:
+
+	template < class SymbolType, class RankType >
+	static rte::FormalRTE < SymbolType, RankType > optimize( const rte::FormalRTE < SymbolType, RankType > & rte );
+	template < class SymbolType, class RankType >
+	static rte::FormalRTEStructure < SymbolType, RankType > optimize( const rte::FormalRTEStructure < SymbolType, RankType > & rte );
+	template < class SymbolType, class RankType >
+	static void optimize( rte::FormalRTEElement < SymbolType, RankType > & rte );
+private:
+	template < class SymbolType, class RankType >
+	static ext::smart_ptr < rte::FormalRTEElement < SymbolType, RankType > > optimizeInner( const rte::FormalRTEElement < SymbolType, RankType > & node );
+
+	template < class SymbolType, class RankType >
+	static bool S( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A1( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A2( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A3( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A4( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A5( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A6( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A7( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A8( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool A9( rte::FormalRTEElement < SymbolType, RankType > * & node );
+/*	template < class SymbolType, class RankType >
+	static bool A10( rte::FormalRTEElement < SymbolType, RankType > * & node );*/
+	template < class SymbolType, class RankType >
+	static bool A11( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V1( rte::FormalRTEElement < SymbolType, RankType > * & node );
+/*	template < class SymbolType, class RankType >
+	static bool V2( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V3( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V4( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V5( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V6( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V8( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V9( rte::FormalRTEElement < SymbolType, RankType > * & node );
+	template < class SymbolType, class RankType >
+	static bool V10( rte::FormalRTEElement < SymbolType, RankType > * & node );*/
+
+	template < class SymbolType, class RankType >
+	static bool X1( rte::FormalRTEElement < SymbolType, RankType > * & node );
+};
+
+template < class SymbolType, class RankType >
+FormalRTE < SymbolType, RankType > RTEOptimize::optimize( const FormalRTE < SymbolType, RankType > & rte ) {
+	return rte::FormalRTE < SymbolType, RankType > ( RTEOptimize::optimize ( rte.getRTE ( ) ) );
+}
+
+template < class SymbolType, class RankType >
+FormalRTEStructure < SymbolType, RankType > RTEOptimize::optimize( const FormalRTEStructure < SymbolType, RankType > & rte ) {
+	ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > optimized = optimizeInner( rte.getStructure ( ) );
+
+	return rte::FormalRTEStructure < SymbolType, RankType > ( * optimized );
+}
+
+} /* namespace simplify */
+
+} /* namespace rte */
+
+#include "RTEOptimizeFormalPart.hpp"
+
+#endif /* _RTE_OPTIMIZE_H__ */
diff --git a/alib2algo/src/rte/simplify/RTEOptimizeFormalPart.hpp b/alib2algo/src/rte/simplify/RTEOptimizeFormalPart.hpp
new file mode 100644
index 0000000000..d2a8304727
--- /dev/null
+++ b/alib2algo/src/rte/simplify/RTEOptimizeFormalPart.hpp
@@ -0,0 +1,620 @@
+/*
+ * RTEOptimize.cpp
+ *
+ *  Created on: 1. 4. 2019
+ *	  Author: Jan Travnicek
+ */
+
+namespace rte {
+
+namespace simplify {
+
+template < class SymbolType, class RankType >
+void RTEOptimize::optimize( FormalRTEElement < SymbolType, RankType > & element ) {
+	ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > optimized = optimizeInner ( element );
+
+	FormalRTEAlternation < SymbolType, RankType > * alternation = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( & element );
+	if( alternation ) {
+		FormalRTEAlternation < SymbolType, RankType > * alternationOptimized = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > * > ( optimized.get ( ) );
+		if( alternationOptimized ) {
+			* alternation = std::move( * alternationOptimized );
+		} else {
+			* alternation = FormalRTEAlternation < SymbolType, RankType > { * optimized, FormalRTEEmpty < SymbolType, RankType > { } };
+		}
+		return;
+	}
+
+	FormalRTESubstitution < SymbolType, RankType > * concatenation = dynamic_cast<FormalRTESubstitution < SymbolType, RankType > *>( & element );
+	if( concatenation ) {
+		FormalRTESubstitution < SymbolType, RankType > * concatenationOptimized = dynamic_cast<FormalRTESubstitution < SymbolType, RankType > * > ( optimized.get ( ) );
+		if( concatenationOptimized ) {
+			* concatenation = std::move( * concatenationOptimized );
+		} else {
+			* concatenation = FormalRTESubstitution < SymbolType, RankType > { * optimized, FormalRTESymbolSubst < SymbolType, RankType > { } };
+		}
+		return;
+	}
+
+	FormalRTEIteration < SymbolType, RankType > * iteration = dynamic_cast<FormalRTEIteration < SymbolType, RankType > *>( & element );
+	if( iteration ) {
+		FormalRTEIteration < SymbolType, RankType > * iterationOptimized = dynamic_cast<FormalRTEIteration < SymbolType, RankType > *>( optimized.get ( ) );
+		if( iterationOptimized ) {
+			* iteration = std::move( * iterationOptimized );
+		} else {
+			* iteration = FormalRTEIteration < SymbolType, RankType > { optimized };
+		}
+		return;
+	}
+
+	// Nothing to optimize original element was FormalRTESymbol, FormalRTESymbolSubst, or FormalRTEEmpty
+	return;
+}
+
+template < class SymbolType, class RankType >
+ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > RTEOptimize::optimizeInner( const FormalRTEElement < SymbolType, RankType > & node ) {
+	FormalRTEElement < SymbolType, RankType > * elem = node.clone();
+
+	// optimize while you can
+	while(    A1( elem ) || A2( elem ) || A3( elem ) || A4( elem ) /*|| A10( elem ) || V2( elem ) || V5( elem ) || V6( elem ) || X1( elem )*/
+	       || A5( elem ) || A6( elem ) || A7( elem ) || A8( elem ) || A9( elem ) /*|| V8( elem ) //|| V9( elem )*/
+	       || A11( elem ) || V1( elem ) /*|| V3( elem ) || V4( elem ) || V10( elem )*/ || S(elem) );
+
+	return ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > ( elem );
+}
+
+template < class SymbolType, class RankType >
+bool RTEOptimize::S( FormalRTEElement < SymbolType, RankType > * & node ) {
+	bool optimized = false;
+	FormalRTEAlternation < SymbolType, RankType > * alternation = dynamic_cast<FormalRTEAlternation < SymbolType, RankType >*>( node );
+	if( alternation ) {
+		ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > tmp = optimizeInner ( alternation->getLeftElement ( ) );
+		if(* tmp != alternation->getLeftElement ( ) ) {
+			optimized = true;
+			alternation->setLeftElement ( * tmp );
+		}
+
+		tmp = optimizeInner ( alternation->getRightElement ( ) );
+		if(* tmp != alternation->getRightElement ( ) ) {
+			optimized = true;
+			alternation->setRightElement ( * tmp );
+		}
+
+		return optimized;
+	}
+
+	FormalRTESubstitution < SymbolType, RankType > * concatenation = dynamic_cast<FormalRTESubstitution < SymbolType, RankType >*>( node );
+	if( concatenation ) {
+		ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > tmp = optimizeInner ( concatenation->getLeftElement() );
+		if(* tmp != concatenation->getLeftElement ( ) ) {
+			optimized = true;
+			concatenation->setLeftElement ( * tmp );
+		}
+
+		tmp = optimizeInner ( concatenation->getRightElement ( ));
+		if(* tmp != concatenation->getRightElement ( )) {
+			optimized = true;
+			concatenation->setRightElement ( * tmp );
+		}
+
+		return optimized;
+	}
+
+	FormalRTEIteration < SymbolType, RankType > * iteration = dynamic_cast<FormalRTEIteration < SymbolType, RankType >*>( node );
+	if( iteration ) {
+		ext::smart_ptr < FormalRTEElement < SymbolType, RankType > > tmp = optimizeInner ( iteration->getElement() );
+
+		if(* tmp != iteration->getElement ( ) ) {
+			optimized = true;
+			iteration->setElement ( * tmp );
+		}
+		return optimized;
+	}
+
+	return optimized;
+}
+
+
+/**
+  * optimization A1: ( x + y ) + z = x + ( y + z )
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A1( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	if( dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( & node->getLeft ( ) ) ) {
+		FormalRTEAlternation < SymbolType, RankType > leftAlt ( std::move ( static_cast < FormalRTEAlternation < SymbolType, RankType > & > ( node->getLeft ( ) ) ) );
+
+		node->setLeft ( std::move ( leftAlt.getLeft ( ) ) );
+		leftAlt.setLeft ( std::move ( leftAlt.getRight ( ) ) );
+		leftAlt.setRight ( std::move ( node->getRight ( ) ) );
+		node->setRight ( std::move ( leftAlt ) );
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A2: x + y = y + x (sort)
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A2 ( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	if ( dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( & node->getRight ( ) ) ) {
+		FormalRTEAlternation < SymbolType, RankType > & rightAlt = static_cast < FormalRTEAlternation < SymbolType, RankType > & > ( node->getRight ( ) );
+
+		if ( node->getLeft ( ) > rightAlt.getLeft ( ) ) {
+			ext::ptr_value < FormalRTEElement < SymbolType, RankType > > tmp ( std::move ( node->getLeft ( ) ) );
+
+			node->setLeft ( std::move ( rightAlt.getLeft ( ) ) );
+			rightAlt.setLeft ( std::move ( tmp ) );
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	return false;
+}
+
+/**
+  * optimization A3: x + \0 = x
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A3 ( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( n );
+	if( ! node ) return false;
+
+	// input can be \0 + \0, so at least one element must be preserved
+
+	if ( dynamic_cast < FormalRTEEmpty < SymbolType, RankType > * > ( & node->getRight ( ) ) ) {
+		n = std::move ( node->getLeft ( ) ).clone ( );
+		delete node;
+		return true;
+	}
+
+	if ( dynamic_cast < FormalRTEEmpty < SymbolType, RankType > * > ( & node->getLeft ( ) ) ) {
+		n = std::move ( node->getRight ( ) ).clone ( );
+		delete node;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A4: x + x = x
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A4( FormalRTEElement < SymbolType, RankType > * & n ) {
+	/*
+	 * two ways of implementing this opitimization:
+	 * - sort and call std::unique ( O(n lg n) + O(n) ), but it also sorts...
+	 * - check every element against other ( O(n*n) )
+	 *
+	 * As we always sort in optimization, we can use the first version, but A4 must be __always__ called __after__ A2
+	 */
+
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( n );
+	if ( ! node ) return false;
+
+	if ( node->getLeftElement() == node->getRightElement() ) {
+		n = std::move ( node->getRight ( ) ).clone ( );
+		delete node;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A5: x.(y.z) = (x.y).z = x.y.z
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A5( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTESubstitution < SymbolType, RankType > * node = dynamic_cast<FormalRTESubstitution < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTESubstitution < SymbolType, RankType > * leftNode = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getLeft ( ) );
+	if( leftNode && node->getSubstitutionSymbol ( ) == leftNode->getSubstitutionSymbol ( ) ) {
+		FormalRTESubstitution < SymbolType, RankType > leftCon ( std::move ( * leftNode ) );
+
+		node->setLeft ( std::move ( leftCon.getLeft ( ) ) );
+		leftCon.setLeft ( std::move ( leftCon.getRight ( ) ) );
+		leftCon.setRight ( std::move ( node->getRight ( ) ) );
+		node->setRight ( std::move ( leftCon ) );
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A6: \e.x = x.\e = x
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A6( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTESubstitution < SymbolType, RankType > * node = dynamic_cast<FormalRTESubstitution < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	// input can be \e + \e, so at least one element must be preserved
+
+	if ( node->getSubstitutionSymbol ( ) == node->getLeft ( ) ) {
+		n = std::move ( node->getRight ( ) ).clone ( );
+		delete node;
+		return true;
+	}
+
+	if ( node->getSubstitutionSymbol ( ) == node->getRight ( ) ) {
+		n = std::move ( node->getRight ( ) ).clone ( );
+		delete node;
+		return true;
+	}
+
+
+	return false;
+}
+
+/**
+  * optimization A7: \0.x = x.\0 = \0
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A7( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTESubstitution < SymbolType, RankType > * node = dynamic_cast<FormalRTESubstitution < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	if ( /*dynamic_cast < FormalRTEEmpty < SymbolType, RankType > * > ( & node->getRight ( ) ) || */ dynamic_cast < FormalRTEEmpty < SymbolType, RankType > * > ( & node->getLeft ( ) ) ) {
+		delete node;
+		n = new FormalRTEEmpty < SymbolType, RankType > { };
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A8: x.(y+z) = x.y + x.z
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A8( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTESubstitution < SymbolType, RankType > * left = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getLeft ( ) );
+	FormalRTESubstitution < SymbolType, RankType > * right = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getRight ( ) );
+	if ( left && right && left->getLeft ( ) == right->getLeft ( ) && left->getSubstitutionSymbol ( ) == right->getSubstitutionSymbol ( ) ) {
+		FormalRTEAlternation < SymbolType, RankType > alt { std::move ( left->getRight ( ) ), std::move ( right->getRight ( ) ) };
+
+		n = new FormalRTESubstitution < SymbolType, RankType > ( std::move ( left->getLeft ( ) ), std::move ( alt ), std::move ( left->getSubstitutionSymbol ( ) ) );
+		delete node;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A9: (x+y).z = x.z + y.z
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A9( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTESubstitution < SymbolType, RankType > * left = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getLeft ( ) );
+	FormalRTESubstitution < SymbolType, RankType > * right = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getRight ( ) );
+	if ( left && right && left->getRight ( ) == right->getRight ( ) && left->getSubstitutionSymbol ( ) == right->getSubstitutionSymbol ( ) ) {
+		FormalRTEAlternation < SymbolType, RankType > alt { std::move ( left->getLeft ( ) ), std::move ( right->getLeft ( ) ) };
+
+		n = new FormalRTESubstitution < SymbolType, RankType > ( std::move ( alt ), std::move ( left->getRight ( ) ), std::move ( left->getSubstitutionSymbol ( ) ) );
+		delete node;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+  * optimization A10: x* = \e + x*x
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::A10( FormalRTEElement < SymbolType, RankType > * & n ) {*/
+	/*
+	 * problem:
+	 * - \e + x*x = x*
+	 * - but if we do not have the eps, but we do have iteration, then \e \in h(iter), therefore \e in h(node).
+	 */
+
+/*	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > * > ( n );
+	if ( ! node ) return false;
+
+	if ( dynamic_cast < FormalRTESymbolSubst < SymbolType, RankType > * > ( & node->getLeft ( ) ) ) {
+		FormalRTESubstitution < SymbolType, RankType > * rightCon = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getRight ( ) );
+		if ( ! rightCon ) return false;
+
+		FormalRTEIteration < SymbolType, RankType > * rightLeftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & rightCon->getLeft ( ) );
+		if ( rightLeftIte ) {
+			if ( rightLeftIte->getElement ( ) == rightCon->getRightElement ( ) ) {
+				n = std::move ( rightCon->getLeft ( ) ).clone ( );
+				delete node;
+				return true;
+			}
+		}
+
+		FormalRTEIteration < SymbolType, RankType > * rightRightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & rightCon->getRight ( ) );
+		if ( rightRightIte ) {
+			if ( rightRightIte->getElement ( ) == rightCon->getLeftElement ( ) ) {
+				n = std::move ( rightCon->getRight ( ) ).clone ( );
+				delete node;
+				return true;
+			}
+		}
+	}
+
+	if ( dynamic_cast < FormalRTESymbolSubst < SymbolType, RankType > * > ( & node->getRight ( ) ) ) {
+		FormalRTESubstitution < SymbolType, RankType > * leftCon = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getLeft ( ) );
+		if ( ! leftCon ) return false;
+
+		FormalRTEIteration < SymbolType, RankType > * leftLeftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & leftCon->getLeft ( ) );
+		if ( leftLeftIte ) {
+			if ( leftLeftIte->getElement ( ) == leftCon->getRightElement ( ) ) {
+				n = std::move ( leftCon->getLeft ( ) ).clone ( );
+				delete node;
+				return true;
+			}
+		}
+
+		FormalRTEIteration < SymbolType, RankType > * leftRightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & leftCon->getRight ( ) );
+		if ( leftRightIte ) {
+			if ( leftRightIte->getElement ( ) == leftCon->getLeftElement ( ) ) {
+				n = std::move ( leftCon->getRight ( ) ).clone ( );
+				delete node;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}*/
+
+/**
+  * optimization A11: x* = (\e + x)*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::A11( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEIteration < SymbolType, RankType > * node = dynamic_cast<FormalRTEIteration < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTEAlternation < SymbolType, RankType > * childAlt = dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( & node->getChild ( ) );
+	if ( childAlt ) {
+		if ( childAlt->getLeft ( ) == node->getSubstitutionSymbol ( ) ) {
+			node->setChild ( std::move ( childAlt->getRight ( ) ) );
+			return true;
+		}
+		if ( childAlt->getRight ( ) == node->getSubstitutionSymbol ( ) ) {
+			node->setChild ( std::move ( childAlt->getLeft ( ) ) );
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+  * optimization V1: \0* = \e
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+template < class SymbolType, class RankType >
+bool RTEOptimize::V1( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEIteration < SymbolType, RankType > * node = dynamic_cast<FormalRTEIteration < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	if ( dynamic_cast < FormalRTEEmpty < SymbolType, RankType > * > ( & node->getChild ( ) ) ) {
+		delete std::exchange ( n, node->getSubstitutionSymbol ( ).clone ( ) );
+		return true;
+	}
+	return false;
+}
+
+/**
+  * optimization V2: x* + x = x*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V2( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * leftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & node->getLeft ( ) );
+	if ( leftIte ) {
+		if ( leftIte->getElement ( ) == node->getRightElement ( ) ) {
+			n = std::move ( node->getLeft ( ) ).clone ( );
+			delete node;
+			return true;
+		}
+	}
+
+	FormalRTEIteration < SymbolType, RankType > * rightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & node->getRight ( ) );
+	if ( rightIte ) {
+		if ( rightIte->getElement ( ) == node->getLeftElement ( ) ) {
+			n = std::move ( node->getRight ( ) ).clone ( );
+			delete node;
+			return true;
+		}
+	}
+
+	return false;
+}*/
+
+/**
+  * optimization V3: x** = x*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V3( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEIteration < SymbolType, RankType > * node = dynamic_cast<FormalRTEIteration < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * childIter = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & node->getChild ( ) );
+	if( childIter ) {
+		node->setChild ( std::move ( childIter->getChild ( ) ) );
+		return true;
+	}
+
+	return false;
+}*/
+
+/**
+  * optimization V4: (x+y)* = (x*y*)*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V4( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEIteration < SymbolType, RankType > * node = dynamic_cast < FormalRTEIteration < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTESubstitution < SymbolType, RankType > * child = dynamic_cast < FormalRTESubstitution < SymbolType, RankType > * > ( & node->getChild ( ) );
+	if( ! child ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * leftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & child->getLeft ( ) );
+	if( ! leftIte ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * rightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & child->getRight ( ) );
+	if( ! rightIte ) return false;
+
+	node->setChild ( FormalRTEAlternation < SymbolType, RankType >( std::move ( leftIte->getElement ( ) ), std::move ( rightIte->getElement ( ) ) ) );
+
+	return true;
+}*/
+
+/**
+  * optimization V5: x*y = y + x*xy
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V5( FormalRTEElement < SymbolType, RankType > * & *//* n *//*) {
+	return false; //TODO
+}*/
+
+/**
+  * optimization V6: x*y = y + xx*y
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V6( FormalRTEElement < SymbolType, RankType > * & *//* n *//*) {
+	return false; //TODO
+}*/
+
+/**
+  * optimization V8: \e in h(x) => xx*=x*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V8( FormalRTEElement < SymbolType, RankType > * & *//* n *//*) {
+	return false; //TODO
+}*/
+
+/**
+  * optimization V9: (xy)*x = x(yx)*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V9( FormalRTEElement < SymbolType, RankType > * & *//* n *//*) {
+	return false; //TODO
+}*/
+
+/**
+  * optimization V10: (x+y)* = (x*+y*)*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::V10( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEIteration < SymbolType, RankType > * node = dynamic_cast < FormalRTEIteration < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTEAlternation < SymbolType, RankType > * alt = dynamic_cast < FormalRTEAlternation < SymbolType, RankType > * > ( & node->getChild ( ) );
+	if( ! alt ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * leftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & alt->getLeft ( ) );
+	if( ! leftIte ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * rightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & alt->getRight ( ) );
+	if( ! rightIte ) return false;
+
+	alt->setLeft ( std::move ( leftIte->getChild ( ) ) );
+	alt->setRight ( std::move ( rightIte->getChild ( ) ) );
+
+	return true;
+}*/
+
+/**
+  * optimization X1: a* + \e = a*
+  * @param node FormalRTEElement < SymbolType, RankType > node
+  * @return bool true if optimization applied else false
+  */
+/*template < class SymbolType, class RankType >
+bool RTEOptimize::X1( FormalRTEElement < SymbolType, RankType > * & n ) {
+	FormalRTEAlternation < SymbolType, RankType > * node = dynamic_cast<FormalRTEAlternation < SymbolType, RankType > *>( n );
+	if( ! node ) return false;
+
+	FormalRTEIteration < SymbolType, RankType > * leftIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & node->getLeft ( ) );
+	if ( leftIte ) {
+		if ( dynamic_cast < FormalRTESymbolSubst < SymbolType, RankType > * > ( & node->getRight ( ) ) ) {
+			n = std::move ( node->getLeft ( ) ).clone ( );
+			delete node;
+			return true;
+		}
+	}
+
+	FormalRTEIteration < SymbolType, RankType > * rightIte = dynamic_cast < FormalRTEIteration < SymbolType, RankType > * > ( & node->getRight ( ) );
+	if ( rightIte ) {
+		if ( dynamic_cast < FormalRTESymbolSubst < SymbolType, RankType > * > ( & node->getLeft ( ) ) ) {
+			n = std::move ( node->getRight ( ) ).clone ( );
+			delete node;
+			return true;
+		}
+	}
+
+	return false;
+
+}*/
+
+} /* namespace simplify */
+
+} /* namespace rte */
-- 
GitLab