From e2fe0b22cf0974c20ad1aec0360adee20242272f Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 18 Nov 2014 23:04:27 +0100
Subject: [PATCH] operators < and == implemented via compare methods

---
 alib2data/src/alphabet/BarSymbol.cpp          | 20 +----
 alib2data/src/alphabet/BarSymbol.h            |  8 +-
 alib2data/src/alphabet/BlankSymbol.cpp        | 20 +----
 alib2data/src/alphabet/BlankSymbol.h          |  8 +-
 .../src/alphabet/BottomOfTheStackSymbol.cpp   | 20 +----
 .../src/alphabet/BottomOfTheStackSymbol.h     |  8 +-
 alib2data/src/alphabet/EndSymbol.cpp          | 20 +----
 alib2data/src/alphabet/EndSymbol.h            |  8 +-
 alib2data/src/alphabet/LabeledSymbol.cpp      | 20 +----
 alib2data/src/alphabet/LabeledSymbol.h        |  8 +-
 alib2data/src/alphabet/RankedBarSymbol.cpp    | 20 +----
 alib2data/src/alphabet/RankedBarSymbol.h      |  8 +-
 alib2data/src/alphabet/RankedSymbol.cpp       | 24 ++----
 alib2data/src/alphabet/RankedSymbol.h         |  8 +-
 .../src/alphabet/SubtreeWildcardSymbol.cpp    | 20 +----
 .../src/alphabet/SubtreeWildcardSymbol.h      |  8 +-
 alib2data/src/automaton/FSM/CompactNFA.cpp    | 32 ++++----
 alib2data/src/automaton/FSM/CompactNFA.h      |  8 +-
 alib2data/src/automaton/FSM/DFA.cpp           | 27 +++----
 alib2data/src/automaton/FSM/DFA.h             |  8 +-
 alib2data/src/automaton/FSM/EpsilonNFA.cpp    | 27 +++----
 alib2data/src/automaton/FSM/EpsilonNFA.h      |  8 +-
 alib2data/src/automaton/FSM/ExtendedNFA.cpp   | 27 +++----
 alib2data/src/automaton/FSM/ExtendedNFA.h     |  8 +-
 .../automaton/FSM/MultiInitialStateNFA.cpp    | 27 +++----
 .../src/automaton/FSM/MultiInitialStateNFA.h  |  8 +-
 alib2data/src/automaton/FSM/NFA.cpp           | 27 +++----
 alib2data/src/automaton/FSM/NFA.h             |  8 +-
 alib2data/src/automaton/PDA/DPDA.cpp          | 27 +++----
 alib2data/src/automaton/PDA/DPDA.h            |  9 +--
 .../src/automaton/PDA/InputDrivenNPDA.cpp     | 27 +++----
 alib2data/src/automaton/PDA/InputDrivenNPDA.h |  8 +-
 alib2data/src/automaton/PDA/NPDA.cpp          | 27 +++----
 alib2data/src/automaton/PDA/NPDA.h            |  9 +--
 .../PDA/RealTimeHeightDeterministicDPDA.cpp   | 27 +++----
 .../PDA/RealTimeHeightDeterministicDPDA.h     |  8 +-
 .../PDA/RealTimeHeightDeterministicNPDA.cpp   | 27 +++----
 .../PDA/RealTimeHeightDeterministicNPDA.h     |  8 +-
 alib2data/src/automaton/PDA/SinglePopDPDA.cpp | 27 +++----
 alib2data/src/automaton/PDA/SinglePopDPDA.h   |  8 +-
 alib2data/src/automaton/PDA/SinglePopNPDA.cpp | 27 +++----
 alib2data/src/automaton/PDA/SinglePopNPDA.h   |  8 +-
 .../src/automaton/PDA/VisiblyPushdownDPDA.cpp | 27 +++----
 .../src/automaton/PDA/VisiblyPushdownDPDA.h   |  8 +-
 .../src/automaton/PDA/VisiblyPushdownNPDA.cpp | 27 +++----
 .../src/automaton/PDA/VisiblyPushdownNPDA.h   |  8 +-
 alib2data/src/automaton/TM/OneTapeDTM.cpp     | 27 +++----
 alib2data/src/automaton/TM/OneTapeDTM.h       |  9 +--
 alib2data/src/common/base.hpp                 | 53 ++++++------
 alib2data/src/container/ObjectsMap.cpp        | 25 +++---
 alib2data/src/container/ObjectsMap.h          |  8 +-
 alib2data/src/container/ObjectsPair.cpp       | 30 +++----
 alib2data/src/container/ObjectsPair.h         |  8 +-
 alib2data/src/container/ObjectsSet.cpp        | 30 +++----
 alib2data/src/container/ObjectsSet.h          |  8 +-
 alib2data/src/container/ObjectsVector.cpp     | 30 +++----
 alib2data/src/container/ObjectsVector.h       |  8 +-
 alib2data/src/exception/AlibException.cpp     | 20 +----
 alib2data/src/exception/AlibException.h       |  8 +-
 alib2data/src/grammar/ContextFree/CFG.cpp     | 27 +++----
 alib2data/src/grammar/ContextFree/CFG.h       |  9 +--
 alib2data/src/grammar/ContextFree/CNF.cpp     | 27 +++----
 alib2data/src/grammar/ContextFree/CNF.h       |  9 +--
 .../grammar/ContextFree/EpsilonFreeCFG.cpp    | 27 +++----
 .../src/grammar/ContextFree/EpsilonFreeCFG.h  |  9 +--
 alib2data/src/grammar/ContextFree/GNF.cpp     | 27 +++----
 alib2data/src/grammar/ContextFree/GNF.h       |  9 +--
 alib2data/src/grammar/ContextFree/LG.cpp      | 27 +++----
 alib2data/src/grammar/ContextFree/LG.h        |  9 +--
 .../src/grammar/ContextSensitive/CSG.cpp      | 27 +++----
 alib2data/src/grammar/ContextSensitive/CSG.h  |  9 +--
 .../NonContractingGrammar.cpp                 | 27 +++----
 .../ContextSensitive/NonContractingGrammar.h  |  9 +--
 alib2data/src/grammar/Regular/LeftLG.cpp      | 27 +++----
 alib2data/src/grammar/Regular/LeftLG.h        |  9 +--
 alib2data/src/grammar/Regular/LeftRG.cpp      | 27 +++----
 alib2data/src/grammar/Regular/LeftRG.h        | 22 +----
 alib2data/src/grammar/Regular/RightLG.cpp     | 27 +++----
 alib2data/src/grammar/Regular/RightLG.h       |  9 +--
 alib2data/src/grammar/Regular/RightRG.cpp     | 27 +++----
 alib2data/src/grammar/Regular/RightRG.h       |  9 +--
 .../ContextPreservingUnrestrictedGrammar.cpp  | 27 +++----
 .../ContextPreservingUnrestrictedGrammar.h    |  9 +--
 .../Unrestricted/UnrestrictedGrammar.cpp      | 27 +++----
 .../Unrestricted/UnrestrictedGrammar.h        |  9 +--
 alib2data/src/label/HexavigesimalLabel.cpp    | 21 +----
 alib2data/src/label/HexavigesimalLabel.h      | 10 +--
 alib2data/src/label/LabelPairLabel.cpp        | 23 ++----
 alib2data/src/label/LabelPairLabel.h          | 10 +--
 alib2data/src/label/LabelSetLabel.cpp         | 27 +++----
 alib2data/src/label/LabelSetLabel.h           | 10 +--
 alib2data/src/label/ObjectLabel.cpp           | 20 +----
 alib2data/src/label/ObjectLabel.h             | 12 +--
 alib2data/src/label/PrimitiveLabel.cpp        | 21 +----
 alib2data/src/label/PrimitiveLabel.h          | 10 +--
 alib2data/src/object/Void.cpp                 | 20 +----
 alib2data/src/object/Void.h                   |  8 +-
 alib2data/src/primitive/Character.cpp         | 21 +----
 alib2data/src/primitive/Character.h           | 11 +--
 alib2data/src/primitive/Integer.cpp           | 20 +----
 alib2data/src/primitive/Integer.h             | 12 +--
 alib2data/src/primitive/String.cpp            | 21 +----
 alib2data/src/primitive/String.h              | 10 +--
 alib2data/src/regexp/formal/FormalRegExp.cpp  | 27 +++----
 alib2data/src/regexp/formal/FormalRegExp.h    |  9 +--
 .../regexp/formal/FormalRegExpAlternation.cpp | 24 ++----
 .../regexp/formal/FormalRegExpAlternation.h   |  8 +-
 .../formal/FormalRegExpConcatenation.cpp      | 24 ++----
 .../regexp/formal/FormalRegExpConcatenation.h |  8 +-
 .../src/regexp/formal/FormalRegExpEmpty.cpp   | 21 +----
 .../src/regexp/formal/FormalRegExpEmpty.h     |  8 +-
 .../src/regexp/formal/FormalRegExpEpsilon.cpp | 21 +----
 .../src/regexp/formal/FormalRegExpEpsilon.h   |  8 +-
 .../regexp/formal/FormalRegExpIteration.cpp   | 20 +----
 .../src/regexp/formal/FormalRegExpIteration.h |  8 +-
 .../src/regexp/formal/FormalRegExpSymbol.cpp  | 21 +----
 .../src/regexp/formal/FormalRegExpSymbol.h    |  8 +-
 .../src/regexp/unbounded/UnboundedRegExp.cpp  | 27 +++----
 .../src/regexp/unbounded/UnboundedRegExp.h    |  9 +--
 .../unbounded/UnboundedRegExpAlternation.cpp  | 38 ++-------
 .../unbounded/UnboundedRegExpAlternation.h    |  8 +-
 .../UnboundedRegExpConcatenation.cpp          | 38 ++-------
 .../unbounded/UnboundedRegExpConcatenation.h  |  8 +-
 .../regexp/unbounded/UnboundedRegExpEmpty.cpp | 21 +----
 .../regexp/unbounded/UnboundedRegExpEmpty.h   |  8 +-
 .../unbounded/UnboundedRegExpEpsilon.cpp      | 21 +----
 .../regexp/unbounded/UnboundedRegExpEpsilon.h |  8 +-
 .../unbounded/UnboundedRegExpIteration.cpp    | 20 +----
 .../unbounded/UnboundedRegExpIteration.h      |  8 +-
 .../unbounded/UnboundedRegExpSymbol.cpp       | 21 +----
 .../regexp/unbounded/UnboundedRegExpSymbol.h  |  8 +-
 alib2data/src/std/tuple.hpp                   |  7 +-
 alib2data/src/string/CyclicString.cpp         | 73 ++++++++++-------
 alib2data/src/string/CyclicString.h           | 16 ++--
 alib2data/src/string/Epsilon.cpp              | 81 ++++++++++---------
 alib2data/src/string/Epsilon.h                | 14 +---
 alib2data/src/string/LinearString.cpp         | 79 ++++++++++--------
 alib2data/src/string/LinearString.h           | 16 ++--
 alib2data/test-src/std/StdVisitorTest.cpp     | 60 +++-----------
 139 files changed, 885 insertions(+), 1711 deletions(-)

diff --git a/alib2data/src/alphabet/BarSymbol.cpp b/alib2data/src/alphabet/BarSymbol.cpp
index b357bd372f..03aeee92a6 100644
--- a/alib2data/src/alphabet/BarSymbol.cpp
+++ b/alib2data/src/alphabet/BarSymbol.cpp
@@ -21,24 +21,12 @@ SymbolBase* BarSymbol::plunder() && {
 	return new BarSymbol(std::move(*this));
 }
 
-bool BarSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int BarSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool BarSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool BarSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool BarSymbol::operator ==(const BarSymbol&) const {
-	return true;
-}
-
-bool BarSymbol::operator <(const BarSymbol&) const {
-	return false;
+int BarSymbol::compare(const BarSymbol&) const {
+	return 0;
 }
 
 void BarSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/BarSymbol.h b/alib2data/src/alphabet/BarSymbol.h
index 2932dd439e..1368321a3c 100644
--- a/alib2data/src/alphabet/BarSymbol.h
+++ b/alib2data/src/alphabet/BarSymbol.h
@@ -26,12 +26,8 @@ public:
 	virtual SymbolBase* clone() const;
 	virtual SymbolBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const BarSymbol& other) const;
-	virtual bool operator <(const BarSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const BarSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/BlankSymbol.cpp b/alib2data/src/alphabet/BlankSymbol.cpp
index ff267cb0c6..6217ac0c8e 100644
--- a/alib2data/src/alphabet/BlankSymbol.cpp
+++ b/alib2data/src/alphabet/BlankSymbol.cpp
@@ -21,24 +21,12 @@ SymbolBase* BlankSymbol::plunder() && {
 	return new BlankSymbol(std::move(*this));
 }
 
-bool BlankSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int BlankSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool BlankSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool BlankSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool BlankSymbol::operator ==(const BlankSymbol&) const {
-	return true;
-}
-
-bool BlankSymbol::operator <(const BlankSymbol&) const {
-	return false;
+int BlankSymbol::compare(const BlankSymbol&) const {
+	return 0;
 }
 
 void BlankSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/BlankSymbol.h b/alib2data/src/alphabet/BlankSymbol.h
index 422432b38f..962095050e 100644
--- a/alib2data/src/alphabet/BlankSymbol.h
+++ b/alib2data/src/alphabet/BlankSymbol.h
@@ -26,12 +26,8 @@ public:
 	virtual SymbolBase* clone() const;
 	virtual SymbolBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const BlankSymbol& other) const;
-	virtual bool operator <(const BlankSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const BlankSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/BottomOfTheStackSymbol.cpp b/alib2data/src/alphabet/BottomOfTheStackSymbol.cpp
index e122375cc4..f20bbf187d 100644
--- a/alib2data/src/alphabet/BottomOfTheStackSymbol.cpp
+++ b/alib2data/src/alphabet/BottomOfTheStackSymbol.cpp
@@ -21,24 +21,12 @@ SymbolBase* BottomOfTheStackSymbol::plunder() && {
 	return new BottomOfTheStackSymbol(std::move(*this));
 }
 
-bool BottomOfTheStackSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int BottomOfTheStackSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool BottomOfTheStackSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool BottomOfTheStackSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool BottomOfTheStackSymbol::operator ==(const BottomOfTheStackSymbol&) const {
-	return true;
-}
-
-bool BottomOfTheStackSymbol::operator <(const BottomOfTheStackSymbol&) const {
-	return false;
+int BottomOfTheStackSymbol::compare(const BottomOfTheStackSymbol&) const {
+	return 0;
 }
 
 void BottomOfTheStackSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/BottomOfTheStackSymbol.h b/alib2data/src/alphabet/BottomOfTheStackSymbol.h
index 91c73bef28..3494fcbf27 100644
--- a/alib2data/src/alphabet/BottomOfTheStackSymbol.h
+++ b/alib2data/src/alphabet/BottomOfTheStackSymbol.h
@@ -26,12 +26,8 @@ public:
 	virtual SymbolBase* clone() const;
 	virtual SymbolBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const BottomOfTheStackSymbol& other) const;
-	virtual bool operator <(const BottomOfTheStackSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const BottomOfTheStackSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/EndSymbol.cpp b/alib2data/src/alphabet/EndSymbol.cpp
index 5ff720d88c..958950ee59 100644
--- a/alib2data/src/alphabet/EndSymbol.cpp
+++ b/alib2data/src/alphabet/EndSymbol.cpp
@@ -21,24 +21,12 @@ SymbolBase* EndSymbol::plunder() && {
 	return new EndSymbol(std::move(*this));
 }
 
-bool EndSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int EndSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool EndSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool EndSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool EndSymbol::operator ==(const EndSymbol&) const {
-	return true;
-}
-
-bool EndSymbol::operator <(const EndSymbol&) const {
-	return false;
+int EndSymbol::compare(const EndSymbol&) const {
+	return 0;
 }
 
 void EndSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/EndSymbol.h b/alib2data/src/alphabet/EndSymbol.h
index dd1f88c29c..49e07097a3 100644
--- a/alib2data/src/alphabet/EndSymbol.h
+++ b/alib2data/src/alphabet/EndSymbol.h
@@ -26,12 +26,8 @@ public:
 	virtual SymbolBase* clone() const;
 	virtual SymbolBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const EndSymbol& other) const;
-	virtual bool operator <(const EndSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const EndSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/LabeledSymbol.cpp b/alib2data/src/alphabet/LabeledSymbol.cpp
index 203cc91217..8bb3cee5d0 100644
--- a/alib2data/src/alphabet/LabeledSymbol.cpp
+++ b/alib2data/src/alphabet/LabeledSymbol.cpp
@@ -41,24 +41,12 @@ const label::Label& LabeledSymbol::getLabel() const {
 	return label;
 }
 
-bool LabeledSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int LabeledSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LabeledSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool LabeledSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool LabeledSymbol::operator ==(const LabeledSymbol& other) const {
-	return this->label == other.label;
-}
-
-bool LabeledSymbol::operator <(const LabeledSymbol& other) const {
-	return this->label < other.label;
+int LabeledSymbol::compare(const LabeledSymbol& other) const {
+	return this->label.getData().compare(other.label.getData());
 }
 
 void LabeledSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/LabeledSymbol.h b/alib2data/src/alphabet/LabeledSymbol.h
index 76a36e410d..e3ef61a405 100644
--- a/alib2data/src/alphabet/LabeledSymbol.h
+++ b/alib2data/src/alphabet/LabeledSymbol.h
@@ -41,12 +41,8 @@ public:
 	 */
 	const label::Label& getLabel() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const LabeledSymbol& other) const;
-	virtual bool operator <(const LabeledSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const LabeledSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/RankedBarSymbol.cpp b/alib2data/src/alphabet/RankedBarSymbol.cpp
index 577f390ac9..9fbee197e0 100644
--- a/alib2data/src/alphabet/RankedBarSymbol.cpp
+++ b/alib2data/src/alphabet/RankedBarSymbol.cpp
@@ -29,24 +29,12 @@ const primitive::Integer& RankedBarSymbol::getRank() const {
 	return rank;
 }
 
-bool RankedBarSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int RankedBarSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RankedBarSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool RankedBarSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool RankedBarSymbol::operator ==(const RankedBarSymbol&) const {
-	return true;
-}
-
-bool RankedBarSymbol::operator <(const RankedBarSymbol&) const {
-	return false;
+int RankedBarSymbol::compare(const RankedBarSymbol&) const {
+	return 0;
 }
 
 void RankedBarSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/RankedBarSymbol.h b/alib2data/src/alphabet/RankedBarSymbol.h
index ace0266530..64e7e598ad 100644
--- a/alib2data/src/alphabet/RankedBarSymbol.h
+++ b/alib2data/src/alphabet/RankedBarSymbol.h
@@ -34,12 +34,8 @@ public:
 	 */
 	const primitive::Integer& getRank() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const RankedBarSymbol& other) const;
-	virtual bool operator <(const RankedBarSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RankedBarSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/RankedSymbol.cpp b/alib2data/src/alphabet/RankedSymbol.cpp
index eab63d315e..5b09ee5b64 100644
--- a/alib2data/src/alphabet/RankedSymbol.cpp
+++ b/alib2data/src/alphabet/RankedSymbol.cpp
@@ -45,26 +45,14 @@ const primitive::Integer& RankedSymbol::getRank() const {
 	return rank;
 }
 
-bool RankedSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int RankedSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RankedSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool RankedSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool RankedSymbol::operator ==(const RankedSymbol& other) const {
-	return this->label == other.label && this -> rank == other.rank;
-}
-
-bool RankedSymbol::operator <(const RankedSymbol& other) const {
-	if (this->label < other.label) return true;
-	else if (this -> label == other.label) return this -> rank < other.rank;
-	else return false;
+int RankedSymbol::compare(const RankedSymbol& other) const {
+	int res = this->label.getData().compare(other.label.getData());
+	if(res == 0) res = this->rank.compare(other.rank);
+	return res;
 }
 
 void RankedSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/RankedSymbol.h b/alib2data/src/alphabet/RankedSymbol.h
index 4f2f2b43b6..e759a42fc4 100644
--- a/alib2data/src/alphabet/RankedSymbol.h
+++ b/alib2data/src/alphabet/RankedSymbol.h
@@ -49,12 +49,8 @@ public:
 	 */
 	const primitive::Integer& getRank() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const RankedSymbol& other) const;
-	virtual bool operator <(const RankedSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RankedSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/alphabet/SubtreeWildcardSymbol.cpp b/alib2data/src/alphabet/SubtreeWildcardSymbol.cpp
index 52d0d87b00..908adc43c0 100644
--- a/alib2data/src/alphabet/SubtreeWildcardSymbol.cpp
+++ b/alib2data/src/alphabet/SubtreeWildcardSymbol.cpp
@@ -21,24 +21,12 @@ SymbolBase* SubtreeWildcardSymbol::plunder() && {
 	return new SubtreeWildcardSymbol(std::move(*this));
 }
 
-bool SubtreeWildcardSymbol::operator <(const ObjectBase& other) const {
-	return other > *this;
+int SubtreeWildcardSymbol::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool SubtreeWildcardSymbol::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool SubtreeWildcardSymbol::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool SubtreeWildcardSymbol::operator ==(const SubtreeWildcardSymbol&) const {
-	return true;
-}
-
-bool SubtreeWildcardSymbol::operator <(const SubtreeWildcardSymbol&) const {
-	return false;
+int SubtreeWildcardSymbol::compare(const SubtreeWildcardSymbol&) const {
+	return 0;
 }
 
 void SubtreeWildcardSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/alphabet/SubtreeWildcardSymbol.h b/alib2data/src/alphabet/SubtreeWildcardSymbol.h
index 7237b9bc61..c9bcb75b2e 100644
--- a/alib2data/src/alphabet/SubtreeWildcardSymbol.h
+++ b/alib2data/src/alphabet/SubtreeWildcardSymbol.h
@@ -26,12 +26,8 @@ public:
 	virtual SymbolBase* clone() const;
 	virtual SymbolBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const SubtreeWildcardSymbol& other) const;
-	virtual bool operator <(const SubtreeWildcardSymbol& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const SubtreeWildcardSymbol& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/automaton/FSM/CompactNFA.cpp b/alib2data/src/automaton/FSM/CompactNFA.cpp
index 14a1d3b804..e57181fdb3 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.cpp
+++ b/alib2data/src/automaton/FSM/CompactNFA.cpp
@@ -164,24 +164,20 @@ std::map<std::pair<State, string::LinearString>, std::set<State>> CompactNFA::ge
 	return transitionsToState;
 }
 
-bool CompactNFA::operator==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool CompactNFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool CompactNFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool CompactNFA::operator==(const CompactNFA& other) const {
-	return states == other.states && inputAlphabet == other.inputAlphabet && initialState == other.initialState && finalStates == other.finalStates && transitions == other.transitions;
-}
-
-bool CompactNFA::operator<(const CompactNFA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+int CompactNFA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
+}
+
+int CompactNFA::compare(const CompactNFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void CompactNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h
index 9993c60998..22f0ac7c09 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.h
+++ b/alib2data/src/automaton/FSM/CompactNFA.h
@@ -79,12 +79,8 @@ public:
 	 */
 	std::map<std::pair<State, string::LinearString>, std::set<State>> getTransitionsToState(const State& from) const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const CompactNFA& other) const;
-	virtual bool operator<(const CompactNFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const CompactNFA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/FSM/DFA.cpp b/alib2data/src/automaton/FSM/DFA.cpp
index 5037f60424..1c8c5e1706 100644
--- a/alib2data/src/automaton/FSM/DFA.cpp
+++ b/alib2data/src/automaton/FSM/DFA.cpp
@@ -132,24 +132,21 @@ bool DFA::isTotal() const {
 	return transitions.size() == inputAlphabet.size() * states.size();
 }
 
-bool DFA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int DFA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool DFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool DFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int DFA::compare(const DFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
 
-bool DFA::operator==(const DFA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool DFA::operator<(const DFA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void DFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/DFA.h b/alib2data/src/automaton/FSM/DFA.h
index cd5344e6f3..3059c4d775 100644
--- a/alib2data/src/automaton/FSM/DFA.h
+++ b/alib2data/src/automaton/FSM/DFA.h
@@ -80,12 +80,8 @@ public:
 	 */
 	bool isTotal() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const DFA& other) const;
-	virtual bool operator<(const DFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const DFA& other) const;
 	
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index 1c47c21f66..99ebddec32 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -265,24 +265,21 @@ bool EpsilonNFA::isTotal() const {
 	return isDeterministic() && transitions.size() == inputAlphabet.size() * states.size();
 }
 
-bool EpsilonNFA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int EpsilonNFA::compare(const ObjectBase& other) const {
+	return other.compare(*this);
 }
 
-bool EpsilonNFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool EpsilonNFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int EpsilonNFA::compare(const EpsilonNFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
 
-bool EpsilonNFA::operator==(const EpsilonNFA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool EpsilonNFA::operator<(const EpsilonNFA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void EpsilonNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.h b/alib2data/src/automaton/FSM/EpsilonNFA.h
index 317e3cb8b4..22aabff97a 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.h
@@ -158,12 +158,8 @@ public:
 	 */
 	bool isTotal() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const EpsilonNFA& other) const;
-	virtual bool operator<(const EpsilonNFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const EpsilonNFA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index bbbc018197..9e9a7a4201 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -176,24 +176,21 @@ std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTra
 	return transitionsToState;
 }
 
-bool ExtendedNFA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int ExtendedNFA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool ExtendedNFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ExtendedNFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int ExtendedNFA::compare(const ExtendedNFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
 
-bool ExtendedNFA::operator==(const ExtendedNFA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool ExtendedNFA::operator<(const ExtendedNFA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void ExtendedNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index d13f02c02f..375f682c4a 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -81,12 +81,8 @@ public:
 	 */
 	std::map<std::pair<State, regexp::RegExp>, std::set<State> > getTransitionsToState(const State& from) const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ExtendedNFA& other) const;
-	virtual bool operator<(const ExtendedNFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ExtendedNFA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
index 40cf2cd0fa..368272c2ac 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
@@ -155,24 +155,21 @@ unsigned MultiInitialStateNFA::transitionsSize() const {
 	return res;
 }
 
-bool MultiInitialStateNFA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int MultiInitialStateNFA::compare(const ObjectBase& other) const {
+	return other.compare(*this);
 }
 
-bool MultiInitialStateNFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool MultiInitialStateNFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int MultiInitialStateNFA::compare(const MultiInitialStateNFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
 
-bool MultiInitialStateNFA::operator==(const MultiInitialStateNFA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool MultiInitialStateNFA::operator<(const MultiInitialStateNFA& other) const {
-	return std::tie(states, inputAlphabet, initialStates, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void MultiInitialStateNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
index d026d17e22..bef36397b1 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
@@ -97,12 +97,8 @@ public:
 
 	unsigned transitionsSize() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const MultiInitialStateNFA& other) const;
-	virtual bool operator<(const MultiInitialStateNFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const MultiInitialStateNFA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp
index f92be7d733..510bf9c92d 100644
--- a/alib2data/src/automaton/FSM/NFA.cpp
+++ b/alib2data/src/automaton/FSM/NFA.cpp
@@ -138,24 +138,21 @@ unsigned NFA::transitionsSize() const {
 	return res;
 }
 
-bool NFA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int NFA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool NFA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool NFA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int NFA::compare(const NFA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
 
-bool NFA::operator==(const NFA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool NFA::operator<(const NFA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void NFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/NFA.h b/alib2data/src/automaton/FSM/NFA.h
index 0221b9d36a..c998bad2e7 100644
--- a/alib2data/src/automaton/FSM/NFA.h
+++ b/alib2data/src/automaton/FSM/NFA.h
@@ -95,12 +95,8 @@ public:
 
 	unsigned transitionsSize() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const NFA& other) const;
-	virtual bool operator<(const NFA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const NFA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/DPDA.cpp b/alib2data/src/automaton/PDA/DPDA.cpp
index 08bf733a06..9db8052048 100644
--- a/alib2data/src/automaton/PDA/DPDA.cpp
+++ b/alib2data/src/automaton/PDA/DPDA.cpp
@@ -222,24 +222,21 @@ std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std:
 	return transitionsToState;
 }
 
-bool DPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int DPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool DPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool DPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int DPDA::compare(const DPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
 
-bool DPDA::operator==(const DPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbol == other.initialSymbol && this->transitions == other.transitions;
-}
-
-bool DPDA::operator<(const DPDA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void DPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/DPDA.h b/alib2data/src/automaton/PDA/DPDA.h
index 4cd0154110..4a3b2cba81 100644
--- a/alib2data/src/automaton/PDA/DPDA.h
+++ b/alib2data/src/automaton/PDA/DPDA.h
@@ -91,13 +91,8 @@ public:
 	 */
 	std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::pair<State, std::vector<alphabet::Symbol> > > getTransitionsToState(const State& from) const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const DPDA& other) const;
-
-	virtual bool operator<(const DPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const DPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
index 573c4aab55..c91056b197 100644
--- a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
+++ b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
@@ -174,24 +174,21 @@ bool InputDrivenNPDA::isDeterministic() const {
 	return true;
 }
 
-bool InputDrivenNPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int InputDrivenNPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool InputDrivenNPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool InputDrivenNPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int InputDrivenNPDA::compare(const InputDrivenNPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
 
-bool InputDrivenNPDA::operator==(const InputDrivenNPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->transitions == other.transitions;
-}
-
-bool InputDrivenNPDA::operator<(const InputDrivenNPDA& other) const {
-	return std::tie(states, inputAlphabet, initialStates, finalStates, transitions) < std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void InputDrivenNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/InputDrivenNPDA.h b/alib2data/src/automaton/PDA/InputDrivenNPDA.h
index 40e4c13b11..1054c421a4 100644
--- a/alib2data/src/automaton/PDA/InputDrivenNPDA.h
+++ b/alib2data/src/automaton/PDA/InputDrivenNPDA.h
@@ -88,12 +88,8 @@ public:
 	 */
 	bool isDeterministic() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const InputDrivenNPDA& other) const;
-	virtual bool operator<(const InputDrivenNPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const InputDrivenNPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp
index 7d01b68d80..c546b60c81 100644
--- a/alib2data/src/automaton/PDA/NPDA.cpp
+++ b/alib2data/src/automaton/PDA/NPDA.cpp
@@ -133,24 +133,21 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 	return transitions;
 }
 
-bool NPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int NPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool NPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool NPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int NPDA::compare(const NPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
 
-bool NPDA::operator==(const NPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions;
-}
-
-bool NPDA::operator<(const NPDA& other) const {
-	return std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions) < std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void NPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/NPDA.h b/alib2data/src/automaton/PDA/NPDA.h
index cf066b4f4b..dbaf1b76d1 100644
--- a/alib2data/src/automaton/PDA/NPDA.h
+++ b/alib2data/src/automaton/PDA/NPDA.h
@@ -75,13 +75,8 @@ public:
 	 */
 	const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& getTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const NPDA& other) const;
-
-	virtual bool operator<(const NPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const NPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
index 054fa7492d..fe7b406fdc 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
@@ -366,24 +366,21 @@ const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>
 		return localTransitions;
 }
 
-bool RealTimeHeightDeterministicDPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int RealTimeHeightDeterministicDPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RealTimeHeightDeterministicDPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool RealTimeHeightDeterministicDPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int RealTimeHeightDeterministicDPDA::compare(const RealTimeHeightDeterministicDPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-bool RealTimeHeightDeterministicDPDA::operator==(const RealTimeHeightDeterministicDPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->bottomOfTheStackSymbol == other.bottomOfTheStackSymbol && this->callTransitions == other.callTransitions && this->returnTransitions == other.returnTransitions && this->localTransitions == other.localTransitions;
-}
-
-bool RealTimeHeightDeterministicDPDA::operator<(const RealTimeHeightDeterministicDPDA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void RealTimeHeightDeterministicDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.h b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.h
index 505fec37f0..772e86ac02 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.h
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.h
@@ -118,12 +118,8 @@ public:
 
 	const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>, State>& getLocalTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const RealTimeHeightDeterministicDPDA& other) const;
-	virtual bool operator<(const RealTimeHeightDeterministicDPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RealTimeHeightDeterministicDPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
index 2d2d84169e..4f1ee73d7c 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.cpp
@@ -257,24 +257,21 @@ const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>
 		return localTransitions;
 }
 
-bool RealTimeHeightDeterministicNPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int RealTimeHeightDeterministicNPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RealTimeHeightDeterministicNPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool RealTimeHeightDeterministicNPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int RealTimeHeightDeterministicNPDA::compare(const RealTimeHeightDeterministicNPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-bool RealTimeHeightDeterministicNPDA::operator==(const RealTimeHeightDeterministicNPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->bottomOfTheStackSymbol == other.bottomOfTheStackSymbol && this->callTransitions == other.callTransitions && this->returnTransitions == other.returnTransitions && this->localTransitions == other.localTransitions;
-}
-
-bool RealTimeHeightDeterministicNPDA::operator<(const RealTimeHeightDeterministicNPDA& other) const {
-	return std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions) < std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void RealTimeHeightDeterministicNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.h b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.h
index 335111cd88..bf74a0fb6f 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.h
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicNPDA.h
@@ -118,12 +118,8 @@ public:
 
 	const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>, std::set<State> >& getLocalTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const RealTimeHeightDeterministicNPDA& other) const;
-	virtual bool operator<(const RealTimeHeightDeterministicNPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RealTimeHeightDeterministicNPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/SinglePopDPDA.cpp b/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
index 2b14eb9227..e46690da38 100644
--- a/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
+++ b/alib2data/src/automaton/PDA/SinglePopDPDA.cpp
@@ -168,24 +168,21 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 	return transitions;
 }
 
-bool SinglePopDPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int SinglePopDPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool SinglePopDPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool SinglePopDPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int SinglePopDPDA::compare(const SinglePopDPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
 
-bool SinglePopDPDA::operator==(const SinglePopDPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbol == other.initialSymbol && this->transitions == other.transitions;
-}
-
-bool SinglePopDPDA::operator<(const SinglePopDPDA& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first == second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void SinglePopDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/SinglePopDPDA.h b/alib2data/src/automaton/PDA/SinglePopDPDA.h
index 7bb5678904..0601a411a4 100644
--- a/alib2data/src/automaton/PDA/SinglePopDPDA.h
+++ b/alib2data/src/automaton/PDA/SinglePopDPDA.h
@@ -81,12 +81,8 @@ public:
 	 */
 	const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::pair<State, std::vector<alphabet::Symbol> > >& getTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const SinglePopDPDA& other) const;
-	virtual bool operator<(const SinglePopDPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const SinglePopDPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/SinglePopNPDA.cpp b/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
index 3c8ab22981..e8c41744c0 100644
--- a/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
+++ b/alib2data/src/automaton/PDA/SinglePopNPDA.cpp
@@ -129,24 +129,21 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 	return transitions;
 }
 
-bool SinglePopNPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int SinglePopNPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool SinglePopNPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool SinglePopNPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int SinglePopNPDA::compare(const SinglePopNPDA& other) const {
+	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
 
-bool SinglePopNPDA::operator==(const SinglePopNPDA& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions;
-}
-
-bool SinglePopNPDA::operator<(const SinglePopNPDA& other) const {
-	return std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions) < std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void SinglePopNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/SinglePopNPDA.h b/alib2data/src/automaton/PDA/SinglePopNPDA.h
index 158f829819..cfb143ee80 100644
--- a/alib2data/src/automaton/PDA/SinglePopNPDA.h
+++ b/alib2data/src/automaton/PDA/SinglePopNPDA.h
@@ -75,12 +75,8 @@ public:
 	 */
 	const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& getTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const SinglePopNPDA& other) const;
-	virtual bool operator<(const SinglePopNPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const SinglePopNPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
index 40fd741337..34228a0666 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.cpp
@@ -264,24 +264,21 @@ const std::map<std::pair<State, alphabet::Symbol>, State>& VisiblyPushdownDPDA::
 		return localTransitions;
 }
 
-bool VisiblyPushdownDPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int VisiblyPushdownDPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool VisiblyPushdownDPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool VisiblyPushdownDPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int VisiblyPushdownDPDA::compare(const VisiblyPushdownDPDA& other) const {
+	auto first = std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
+	auto second = std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-bool VisiblyPushdownDPDA::operator==(const VisiblyPushdownDPDA& other) const {
-	return this->states == other.states && this->callInputAlphabet == other.callInputAlphabet && this->returnInputAlphabet == other.returnInputAlphabet && this->localInputAlphabet == other.localInputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->bottomOfTheStackSymbol == other.bottomOfTheStackSymbol && this->callTransitions == other.callTransitions && this->returnTransitions == other.returnTransitions && this->localTransitions == other.localTransitions;
-}
-
-bool VisiblyPushdownDPDA::operator<(const VisiblyPushdownDPDA& other) const {
-	return std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions) < std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void VisiblyPushdownDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.h b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.h
index a4560a4c6a..5337610be8 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.h
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownDPDA.h
@@ -104,12 +104,8 @@ public:
 
 	const std::map<std::pair<State, alphabet::Symbol>, State>& getLocalTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const VisiblyPushdownDPDA& other) const;
-	virtual bool operator<(const VisiblyPushdownDPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const VisiblyPushdownDPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
index 1963146e55..bb270a28e7 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.cpp
@@ -197,24 +197,21 @@ const std::map<std::pair<State, alphabet::Symbol>, std::set<State> >& VisiblyPus
 		return localTransitions;
 }
 
-bool VisiblyPushdownNPDA::operator==(const ObjectBase& other) const {
-	return other == *this;
+int VisiblyPushdownNPDA::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool VisiblyPushdownNPDA::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool VisiblyPushdownNPDA::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int VisiblyPushdownNPDA::compare(const VisiblyPushdownNPDA& other) const {
+	auto first = std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
+	auto second = std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
 
-bool VisiblyPushdownNPDA::operator==(const VisiblyPushdownNPDA& other) const {
-	return this->states == other.states && this->callInputAlphabet == other.callInputAlphabet && this->returnInputAlphabet == other.returnInputAlphabet && this->localInputAlphabet == other.localInputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->bottomOfTheStackSymbol == other.bottomOfTheStackSymbol && this->callTransitions == other.callTransitions && this->returnTransitions == other.returnTransitions && this->localTransitions == other.localTransitions;
-}
-
-bool VisiblyPushdownNPDA::operator<(const VisiblyPushdownNPDA& other) const {
-	return std::tie(states, callInputAlphabet, returnInputAlphabet, localInputAlphabet, initialStates, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions) < std::tie(other.states, other.callInputAlphabet, other.returnInputAlphabet, other.localInputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void VisiblyPushdownNPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.h b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.h
index cb4d663312..90fcae5106 100644
--- a/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.h
+++ b/alib2data/src/automaton/PDA/VisiblyPushdownNPDA.h
@@ -104,12 +104,8 @@ public:
 
 	const std::map<std::pair<State, alphabet::Symbol>, std::set<State> >& getLocalTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const VisiblyPushdownNPDA& other) const;
-	virtual bool operator<(const VisiblyPushdownNPDA& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const VisiblyPushdownNPDA& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/automaton/TM/OneTapeDTM.cpp b/alib2data/src/automaton/TM/OneTapeDTM.cpp
index 77b7281862..9951f1f2c3 100644
--- a/alib2data/src/automaton/TM/OneTapeDTM.cpp
+++ b/alib2data/src/automaton/TM/OneTapeDTM.cpp
@@ -114,24 +114,21 @@ const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::S
 	return transitions;
 }
 
-bool OneTapeDTM::operator==(const ObjectBase& other) const {
-	return other == *this;
+int OneTapeDTM::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool OneTapeDTM::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool OneTapeDTM::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int OneTapeDTM::compare(const OneTapeDTM& other) const {
+	auto first = std::tie(states, inputAlphabet, initialState, finalStates, tapeAlphabet, blankSymbol, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.tapeAlphabet, other.blankSymbol, other.transitions);
 
-bool OneTapeDTM::operator==(const OneTapeDTM& other) const {
-	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->tapeAlphabet == other.tapeAlphabet && this->blankSymbol == other.blankSymbol && this->transitions == other.transitions;
-}
-
-bool OneTapeDTM::operator<(const OneTapeDTM& other) const {
-	return std::tie(states, inputAlphabet, initialState, finalStates, tapeAlphabet, blankSymbol, transitions) < std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.tapeAlphabet, other.blankSymbol, other.transitions);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void OneTapeDTM::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/TM/OneTapeDTM.h b/alib2data/src/automaton/TM/OneTapeDTM.h
index 40a366862a..b8da5bdc4c 100644
--- a/alib2data/src/automaton/TM/OneTapeDTM.h
+++ b/alib2data/src/automaton/TM/OneTapeDTM.h
@@ -73,13 +73,8 @@ public:
 	 */
 	const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> >& getTransitions() const;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const OneTapeDTM& other) const;
-
-	virtual bool operator<(const OneTapeDTM& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const OneTapeDTM& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/common/base.hpp b/alib2data/src/common/base.hpp
index 54c1a5df1b..4e13245d96 100644
--- a/alib2data/src/common/base.hpp
+++ b/alib2data/src/common/base.hpp
@@ -10,17 +10,13 @@
 
 #include <typeinfo>
 #include <ostream>
+#include <stdexcept>
 
 namespace alib {
 
 template<int ID>
 class base_base {
 public:
-/*	template<typename T>
-	static int typeId() {
-		return ID;
-	}*/
-
 	virtual int selfTypeId() const = 0;
 
 	virtual ~base_base() noexcept {
@@ -39,20 +35,20 @@ public:
 		return ID;
 	}
 
-	virtual bool operator==(const T &) const {
-		return false;
-	}
-
-	virtual bool operator<(const T &) const {
-		return this->selfTypeId() < typeId<T>();
+	virtual int compare(const T &) const {
+		if(this->selfTypeId() < typeId<T>())
+			return -1;
+		else if(this->selfTypeId() > typeId<T>())
+			return 1;
+		else
+			throw std::logic_error("Should not be reached");
 	}
 };
 
 template<int ID, typename T, typename... Types>
 class base_helper<ID, T, Types...> : public base_helper<ID + 1, Types...> {
 public:
-	using base_helper<ID + 1, Types...>::operator==;
-	using base_helper<ID + 1, Types...>::operator<;
+	using base_helper<ID + 1, Types...>::compare;
 	using base_helper<ID + 1, Types...>::typeId;
 
 	template<typename R, typename std::enable_if < std::is_same< R, T >::value >::type* = nullptr >
@@ -60,20 +56,20 @@ public:
 		return ID;
 	}
 
-	virtual bool operator==(const T &) const {
-		return false;
-	}
-
-	virtual bool operator<(const T &) const {
-		return this->selfTypeId() < typeId<T>();
+	virtual int compare(const T &) const {
+		if(this->selfTypeId() < typeId<T>())
+			return -1;
+		else if(this->selfTypeId() > typeId<T>())
+			return 1;
+		else
+			throw std::logic_error("Should not be reached");
 	}
 };
 
 template<typename T, typename... Types>
 class base : public base_helper<1, Types...> {
 public:
-	using base_helper<1, Types...>::operator==;
-	using base_helper<1, Types...>::operator<;
+	using base_helper<1, Types...>::compare;
 	using base_helper<1, Types...>::typeId;
 
 	virtual T* clone() const = 0;
@@ -84,10 +80,19 @@ public:
 		return !(*this == other);
 	}
 
-	virtual bool operator==(const T& other) const = 0;
+	bool operator==(const T& other) const {
+		return this->compare(other) == 0;
+	}
+
+	bool operator<(const T& other) const {
+		return this->compare(other) < 0;
+	}
+
+	bool operator>(const T& other) const {
+		return this->compare(other) > 0;
+	}
 
-	virtual bool operator<(const T& other) const = 0;
-	virtual bool operator>(const T& other) const = 0;
+	virtual int compare(const T& other) const = 0;
 
 	friend std::ostream& operator<<(std::ostream& os, const T& instance) {
 		instance >> os;
diff --git a/alib2data/src/container/ObjectsMap.cpp b/alib2data/src/container/ObjectsMap.cpp
index f8b07ca4bb..9dfc2156b5 100644
--- a/alib2data/src/container/ObjectsMap.cpp
+++ b/alib2data/src/container/ObjectsMap.cpp
@@ -22,24 +22,19 @@ ContainerBase* ObjectsMap::plunder() && {
 	return new ObjectsMap(std::move(*this));
 }
 
-bool ObjectsMap::operator==(const ObjectBase& other) const {
-	return other == *this;
+int ObjectsMap::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool ObjectsMap::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ObjectsMap::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool ObjectsMap::operator==(const ObjectsMap& other) const {
-	return static_cast<const std::map<alib::Object, alib::Object>>(*this) == static_cast<const std::map<alib::Object, alib::Object>>(other);
-}
+int ObjectsMap::compare(const ObjectsMap& other) const {
+	if(static_cast<const std::map<alib::Object, alib::Object>>(*this) == static_cast<const std::map<alib::Object, alib::Object>>(other)) {
+		return 0;
+	} else if(static_cast<const std::map<alib::Object, alib::Object>>(*this) < static_cast<const std::map<alib::Object, alib::Object>>(other)) {
+		return -1;
+	} else {
+		return 1;
+	}
 
-bool ObjectsMap::operator<(const ObjectsMap& other) const {
-	return static_cast<const std::map<alib::Object, alib::Object>>(*this) < static_cast<const std::map<alib::Object, alib::Object>>(other);
 }
 
 void ObjectsMap::operator>>(std::ostream& os) const {
diff --git a/alib2data/src/container/ObjectsMap.h b/alib2data/src/container/ObjectsMap.h
index a2b989e869..fbb2820190 100644
--- a/alib2data/src/container/ObjectsMap.h
+++ b/alib2data/src/container/ObjectsMap.h
@@ -26,12 +26,8 @@ public:
 	
 	virtual ContainerBase* plunder() &&;
 
-	virtual bool operator>(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ObjectsMap& other) const;
-	virtual bool operator<(const ObjectsMap& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ObjectsMap& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/container/ObjectsPair.cpp b/alib2data/src/container/ObjectsPair.cpp
index 4517e6a089..b44b02887e 100644
--- a/alib2data/src/container/ObjectsPair.cpp
+++ b/alib2data/src/container/ObjectsPair.cpp
@@ -26,24 +26,18 @@ ContainerBase* ObjectsPair::plunder() && {
 	return new ObjectsPair(std::move(*this));
 }
 
-bool ObjectsPair::operator==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool ObjectsPair::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ObjectsPair::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool ObjectsPair::operator==(const ObjectsPair& other) const {
-	return static_cast<const std::pair<alib::Object, alib::Object>>(*this) == static_cast<const std::pair<alib::Object, alib::Object>>(other);
-}
-
-bool ObjectsPair::operator<(const ObjectsPair& other) const {
-	return static_cast<const std::pair<alib::Object, alib::Object>>(*this) < static_cast<const std::pair<alib::Object, alib::Object>>(other);
+int ObjectsPair::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
+}
+
+int ObjectsPair::compare(const ObjectsPair& other) const {
+	if(static_cast<const std::pair<alib::Object, alib::Object>>(*this) == static_cast<const std::pair<alib::Object, alib::Object>>(other)) {
+		return 0;
+	} else if(static_cast<const std::pair<alib::Object, alib::Object>>(*this) < static_cast<const std::pair<alib::Object, alib::Object>>(other)) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void ObjectsPair::operator>>(std::ostream& os) const {
diff --git a/alib2data/src/container/ObjectsPair.h b/alib2data/src/container/ObjectsPair.h
index 270dcdea62..484a637ec1 100644
--- a/alib2data/src/container/ObjectsPair.h
+++ b/alib2data/src/container/ObjectsPair.h
@@ -28,12 +28,8 @@ public:
 	
 	virtual ContainerBase* plunder() &&;
 
-	virtual bool operator>(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ObjectsPair& other) const;
-	virtual bool operator<(const ObjectsPair& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ObjectsPair& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/container/ObjectsSet.cpp b/alib2data/src/container/ObjectsSet.cpp
index c127b8a5ad..464e69e862 100644
--- a/alib2data/src/container/ObjectsSet.cpp
+++ b/alib2data/src/container/ObjectsSet.cpp
@@ -22,24 +22,18 @@ ContainerBase* ObjectsSet::plunder() && {
 	return new ObjectsSet(std::move(*this));
 }
 
-bool ObjectsSet::operator==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool ObjectsSet::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ObjectsSet::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool ObjectsSet::operator==(const ObjectsSet& other) const {
-	return static_cast<const std::set<alib::Object>>(*this) == static_cast<const std::set<alib::Object>>(other);
-}
-
-bool ObjectsSet::operator<(const ObjectsSet& other) const {
-	return static_cast<const std::set<alib::Object>>(*this) < static_cast<const std::set<alib::Object>>(other);
+int ObjectsSet::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
+}
+
+int ObjectsSet::compare(const ObjectsSet& other) const {
+	if(static_cast<const std::set<alib::Object>>(*this) == static_cast<const std::set<alib::Object>>(other)) {
+		return 0;
+	} else if(static_cast<const std::set<alib::Object>>(*this) < static_cast<const std::set<alib::Object>>(other)) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void ObjectsSet::operator>>(std::ostream& os) const {
diff --git a/alib2data/src/container/ObjectsSet.h b/alib2data/src/container/ObjectsSet.h
index 0a5fec7f9f..35382caddf 100644
--- a/alib2data/src/container/ObjectsSet.h
+++ b/alib2data/src/container/ObjectsSet.h
@@ -26,12 +26,8 @@ public:
 	
 	virtual ContainerBase* plunder() &&;
 
-	virtual bool operator>(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ObjectsSet& other) const;
-	virtual bool operator<(const ObjectsSet& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ObjectsSet& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/container/ObjectsVector.cpp b/alib2data/src/container/ObjectsVector.cpp
index d8105a41d2..9efb9292c9 100644
--- a/alib2data/src/container/ObjectsVector.cpp
+++ b/alib2data/src/container/ObjectsVector.cpp
@@ -22,24 +22,18 @@ ContainerBase* ObjectsVector::plunder() && {
 	return new ObjectsVector(std::move(*this));
 }
 
-bool ObjectsVector::operator==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool ObjectsVector::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ObjectsVector::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool ObjectsVector::operator==(const ObjectsVector& other) const {
-	return static_cast<const std::vector<alib::Object>>(*this) == static_cast<const std::vector<alib::Object>>(other);
-}
-
-bool ObjectsVector::operator<(const ObjectsVector& other) const {
-	return static_cast<const std::vector<alib::Object>>(*this) < static_cast<const std::vector<alib::Object>>(other);
+int ObjectsVector::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
+}
+
+int ObjectsVector::compare(const ObjectsVector& other) const {
+	if(static_cast<const std::vector<alib::Object>>(*this) == static_cast<const std::vector<alib::Object>>(other)) {
+		return 0;
+	} else if(static_cast<const std::vector<alib::Object>>(*this) < static_cast<const std::vector<alib::Object>>(other)) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void ObjectsVector::operator>>(std::ostream& os) const {
diff --git a/alib2data/src/container/ObjectsVector.h b/alib2data/src/container/ObjectsVector.h
index 03e89ebad7..da7c1373bb 100644
--- a/alib2data/src/container/ObjectsVector.h
+++ b/alib2data/src/container/ObjectsVector.h
@@ -26,12 +26,8 @@ public:
 	
 	virtual ContainerBase* plunder() &&;
 
-	virtual bool operator>(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ObjectsVector& other) const;
-	virtual bool operator<(const ObjectsVector& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ObjectsVector& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/exception/AlibException.cpp b/alib2data/src/exception/AlibException.cpp
index 8571d7527d..5373bb86b9 100644
--- a/alib2data/src/exception/AlibException.cpp
+++ b/alib2data/src/exception/AlibException.cpp
@@ -67,24 +67,12 @@ const std::string & AlibException::getBacktrace ( ) const {
 	return backtrace;
 }
 
-bool AlibException::operator==(const ObjectBase& other) const {
-	return other == *this;
+int AlibException::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool AlibException::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool AlibException::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool AlibException::operator==(const AlibException& other) const {
-	return this->whatMessage == other.whatMessage;
-}
-
-bool AlibException::operator<(const AlibException& other) const {
-	return this->whatMessage < other.whatMessage;
+int AlibException::compare(const AlibException& other) const {
+	return this->whatMessage.compare(other.whatMessage);
 }
 
 void AlibException::operator>>(std::ostream& os) const {
diff --git a/alib2data/src/exception/AlibException.h b/alib2data/src/exception/AlibException.h
index 09f53c66c1..8cadc496a5 100644
--- a/alib2data/src/exception/AlibException.h
+++ b/alib2data/src/exception/AlibException.h
@@ -53,12 +53,8 @@ public:
 	 */
 	const std::string & getBacktrace ( ) const;
 
-	virtual bool operator>(const alib::ObjectBase& other) const;
-	virtual bool operator==(const alib::ObjectBase& other) const;
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const AlibException& other) const;
-	virtual bool operator<(const AlibException& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const AlibException& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextFree/CFG.cpp b/alib2data/src/grammar/ContextFree/CFG.cpp
index 6c2eca1b20..bab73c29f2 100644
--- a/alib2data/src/grammar/ContextFree/CFG.cpp
+++ b/alib2data/src/grammar/ContextFree/CFG.cpp
@@ -89,24 +89,21 @@ bool CFG::removeRule(const alphabet::Symbol& leftHandSide, const std::vector<alp
 	return rules[leftHandSide].erase(rightHandSide);
 }
 
-bool CFG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int CFG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool CFG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool CFG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int CFG::compare(const CFG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool CFG::operator==(const CFG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool CFG::operator<(const CFG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void CFG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextFree/CFG.h b/alib2data/src/grammar/ContextFree/CFG.h
index bb36acd063..afb714ca86 100644
--- a/alib2data/src/grammar/ContextFree/CFG.h
+++ b/alib2data/src/grammar/ContextFree/CFG.h
@@ -47,13 +47,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const CFG& other) const;
-
-	virtual bool operator<(const CFG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const CFG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextFree/CNF.cpp b/alib2data/src/grammar/ContextFree/CNF.cpp
index 03da6a5575..449f53d362 100644
--- a/alib2data/src/grammar/ContextFree/CNF.cpp
+++ b/alib2data/src/grammar/ContextFree/CNF.cpp
@@ -171,24 +171,21 @@ bool CNF::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool CNF::operator==(const ObjectBase& other) const {
-	return other == *this;
+int CNF::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool CNF::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool CNF::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int CNF::compare(const CNF& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool CNF::operator==(const CNF& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool CNF::operator<(const CNF& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void CNF::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextFree/CNF.h b/alib2data/src/grammar/ContextFree/CNF.h
index af5c56a409..e972f0eda3 100644
--- a/alib2data/src/grammar/ContextFree/CNF.h
+++ b/alib2data/src/grammar/ContextFree/CNF.h
@@ -56,13 +56,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const CNF& other) const;
-
-	virtual bool operator<(const CNF& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const CNF& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.cpp b/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.cpp
index 081e3bddc4..9a9c80c507 100644
--- a/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.cpp
+++ b/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.cpp
@@ -122,24 +122,21 @@ bool EpsilonFreeCFG::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool EpsilonFreeCFG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int EpsilonFreeCFG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool EpsilonFreeCFG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool EpsilonFreeCFG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int EpsilonFreeCFG::compare(const EpsilonFreeCFG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool EpsilonFreeCFG::operator==(const EpsilonFreeCFG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool EpsilonFreeCFG::operator<(const EpsilonFreeCFG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void EpsilonFreeCFG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.h b/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.h
index 629b8cfaf3..17addf33f2 100644
--- a/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.h
+++ b/alib2data/src/grammar/ContextFree/EpsilonFreeCFG.h
@@ -51,13 +51,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const EpsilonFreeCFG& other) const;
-
-	virtual bool operator<(const EpsilonFreeCFG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const EpsilonFreeCFG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextFree/GNF.cpp b/alib2data/src/grammar/ContextFree/GNF.cpp
index 802169e44e..93f6b393db 100644
--- a/alib2data/src/grammar/ContextFree/GNF.cpp
+++ b/alib2data/src/grammar/ContextFree/GNF.cpp
@@ -130,24 +130,21 @@ bool GNF::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool GNF::operator==(const ObjectBase& other) const {
-	return other == *this;
+int GNF::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool GNF::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool GNF::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int GNF::compare(const GNF& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool GNF::operator==(const GNF& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool GNF::operator<(const GNF& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void GNF::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextFree/GNF.h b/alib2data/src/grammar/ContextFree/GNF.h
index 2a9caa5336..6858955ce1 100644
--- a/alib2data/src/grammar/ContextFree/GNF.h
+++ b/alib2data/src/grammar/ContextFree/GNF.h
@@ -50,13 +50,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const GNF& other) const;
-
-	virtual bool operator<(const GNF& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const GNF& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextFree/LG.cpp b/alib2data/src/grammar/ContextFree/LG.cpp
index 630de907b3..03a2b0336f 100644
--- a/alib2data/src/grammar/ContextFree/LG.cpp
+++ b/alib2data/src/grammar/ContextFree/LG.cpp
@@ -180,24 +180,21 @@ bool LG::removeRawRule(const alphabet::Symbol& leftHandSide, const std::vector<a
 	}
 }
 
-bool LG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int LG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool LG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int LG::compare(const LG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool LG::operator==(const LG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool LG::operator<(const LG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void LG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextFree/LG.h b/alib2data/src/grammar/ContextFree/LG.h
index 7c56b5e9dc..c531f4a59a 100644
--- a/alib2data/src/grammar/ContextFree/LG.h
+++ b/alib2data/src/grammar/ContextFree/LG.h
@@ -52,13 +52,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const LG& other) const;
-
-	virtual bool operator<(const LG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const LG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextSensitive/CSG.cpp b/alib2data/src/grammar/ContextSensitive/CSG.cpp
index 77e48595d3..6f580f2f01 100644
--- a/alib2data/src/grammar/ContextSensitive/CSG.cpp
+++ b/alib2data/src/grammar/ContextSensitive/CSG.cpp
@@ -119,24 +119,21 @@ bool CSG::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool CSG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int CSG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool CSG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool CSG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int CSG::compare(const CSG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool CSG::operator==(const CSG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool CSG::operator<(const CSG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void CSG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextSensitive/CSG.h b/alib2data/src/grammar/ContextSensitive/CSG.h
index f75ac10870..0427a348b6 100644
--- a/alib2data/src/grammar/ContextSensitive/CSG.h
+++ b/alib2data/src/grammar/ContextSensitive/CSG.h
@@ -44,13 +44,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const ObjectBase& other) const;
-	virtual bool operator ==(const ObjectBase& other) const;
-	virtual bool operator >(const ObjectBase& other) const;
-
-	virtual bool operator==(const CSG& other) const;
-
-	virtual bool operator<(const CSG& other) const;
+	virtual int compare(const ObjectBase& other) const;
+	virtual int compare(const CSG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.cpp b/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.cpp
index 922140c3b9..44b8108f0c 100644
--- a/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.cpp
+++ b/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.cpp
@@ -100,24 +100,21 @@ bool NonContractingGrammar::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool NonContractingGrammar::operator==(const ObjectBase& other) const {
-	return other == *this;
+int NonContractingGrammar::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool NonContractingGrammar::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool NonContractingGrammar::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int NonContractingGrammar::compare(const NonContractingGrammar& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool NonContractingGrammar::operator==(const NonContractingGrammar& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool NonContractingGrammar::operator<(const NonContractingGrammar& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void NonContractingGrammar::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.h b/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.h
index fc5cf10cd0..fd20c21381 100644
--- a/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.h
+++ b/alib2data/src/grammar/ContextSensitive/NonContractingGrammar.h
@@ -44,13 +44,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const NonContractingGrammar& other) const;
-
-	virtual bool operator<(const NonContractingGrammar& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const NonContractingGrammar& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/Regular/LeftLG.cpp b/alib2data/src/grammar/Regular/LeftLG.cpp
index 1c66201141..b379a7208e 100644
--- a/alib2data/src/grammar/Regular/LeftLG.cpp
+++ b/alib2data/src/grammar/Regular/LeftLG.cpp
@@ -165,24 +165,21 @@ bool LeftLG::removeRawRule(const alphabet::Symbol& leftHandSide, const std::vect
 	}
 }
 
-bool LeftLG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int LeftLG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LeftLG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool LeftLG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int LeftLG::compare(const LeftLG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool LeftLG::operator==(const LeftLG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool LeftLG::operator<(const LeftLG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void LeftLG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Regular/LeftLG.h b/alib2data/src/grammar/Regular/LeftLG.h
index 068b835035..95e46cb355 100644
--- a/alib2data/src/grammar/Regular/LeftLG.h
+++ b/alib2data/src/grammar/Regular/LeftLG.h
@@ -51,13 +51,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const LeftLG& other) const;
-
-	virtual bool operator<(const LeftLG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const LeftLG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/Regular/LeftRG.cpp b/alib2data/src/grammar/Regular/LeftRG.cpp
index 3f789ea2cb..1af289bbbb 100644
--- a/alib2data/src/grammar/Regular/LeftRG.cpp
+++ b/alib2data/src/grammar/Regular/LeftRG.cpp
@@ -169,24 +169,21 @@ bool LeftRG::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool LeftRG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int LeftRG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LeftRG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool LeftRG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int LeftRG::compare(const LeftRG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool LeftRG::operator==(const LeftRG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool LeftRG::operator<(const LeftRG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void LeftRG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Regular/LeftRG.h b/alib2data/src/grammar/Regular/LeftRG.h
index 6800315605..acfcd932ba 100644
--- a/alib2data/src/grammar/Regular/LeftRG.h
+++ b/alib2data/src/grammar/Regular/LeftRG.h
@@ -124,29 +124,13 @@ public:
 	/**
 	 * double dispatch operator helper
 	 */
-	virtual bool operator <(const alib::ObjectBase& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
 
 	/**
-	 * double dispatch operator helper
-	 */
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-
-	/**
-	 * double dispatch operator helper
-	 */
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	/**
-	 * equals operator
-	 * @param other the other instance
-	 */
-	virtual bool operator==(const LeftRG& other) const;
-
-	/**
-	 * less operator
+	 * compare
 	 * @param other the other instance
 	 */
-	virtual bool operator<(const LeftRG& other) const;
+	virtual int compare(const LeftRG& other) const;
 
 	/**
 	 * print this instance as raw representation to ostream
diff --git a/alib2data/src/grammar/Regular/RightLG.cpp b/alib2data/src/grammar/Regular/RightLG.cpp
index 08faa71a17..6585010a01 100644
--- a/alib2data/src/grammar/Regular/RightLG.cpp
+++ b/alib2data/src/grammar/Regular/RightLG.cpp
@@ -165,24 +165,21 @@ bool RightLG::removeRawRule(const alphabet::Symbol& leftHandSide, const std::vec
 	}
 }
 
-bool RightLG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int RightLG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RightLG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool RightLG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int RightLG::compare(const RightLG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool RightLG::operator==(const RightLG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool RightLG::operator<(const RightLG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void RightLG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Regular/RightLG.h b/alib2data/src/grammar/Regular/RightLG.h
index fc0d2cf7d3..fd13d01a82 100644
--- a/alib2data/src/grammar/Regular/RightLG.h
+++ b/alib2data/src/grammar/Regular/RightLG.h
@@ -51,13 +51,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const RightLG& other) const;
-
-	virtual bool operator<(const RightLG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RightLG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/Regular/RightRG.cpp b/alib2data/src/grammar/Regular/RightRG.cpp
index 07eb323a39..e89179b96d 100644
--- a/alib2data/src/grammar/Regular/RightRG.cpp
+++ b/alib2data/src/grammar/Regular/RightRG.cpp
@@ -169,24 +169,21 @@ bool RightRG::getGeneratesEpsilon() const {
 	return generatesEpsilon;
 }
 
-bool RightRG::operator==(const ObjectBase& other) const {
-	return other == *this;
+int RightRG::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool RightRG::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool RightRG::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int RightRG::compare(const RightRG& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool RightRG::operator==(const RightRG& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
-}
-
-bool RightRG::operator<(const RightRG& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void RightRG::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Regular/RightRG.h b/alib2data/src/grammar/Regular/RightRG.h
index b21e848b73..0580625a7f 100644
--- a/alib2data/src/grammar/Regular/RightRG.h
+++ b/alib2data/src/grammar/Regular/RightRG.h
@@ -71,13 +71,8 @@ public:
 	void setGeneratesEpsilon(bool genEps);
 	bool getGeneratesEpsilon() const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const RightRG& other) const;
-
-	virtual bool operator<(const RightRG& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const RightRG& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp b/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp
index f600000099..e10ea337dc 100644
--- a/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp
+++ b/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp
@@ -105,24 +105,21 @@ bool ContextPreservingUnrestrictedGrammar::removeRule(const std::vector<alphabet
 	return rules[make_tuple(lContext, leftHandSide, rContext)].erase(rightHandSide);
 }
 
-bool ContextPreservingUnrestrictedGrammar::operator==(const ObjectBase& other) const {
-	return other == *this;
+int ContextPreservingUnrestrictedGrammar::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool ContextPreservingUnrestrictedGrammar::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool ContextPreservingUnrestrictedGrammar::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int ContextPreservingUnrestrictedGrammar::compare(const ContextPreservingUnrestrictedGrammar& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool ContextPreservingUnrestrictedGrammar::operator==(const ContextPreservingUnrestrictedGrammar& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool ContextPreservingUnrestrictedGrammar::operator<(const ContextPreservingUnrestrictedGrammar& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void ContextPreservingUnrestrictedGrammar::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h b/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h
index bb23181be0..c781aded66 100644
--- a/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h
+++ b/alib2data/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h
@@ -40,13 +40,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const ContextPreservingUnrestrictedGrammar& other) const;
-
-	virtual bool operator<(const ContextPreservingUnrestrictedGrammar& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const ContextPreservingUnrestrictedGrammar& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.cpp b/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.cpp
index e5417bac4b..4bce0a3fc3 100644
--- a/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.cpp
+++ b/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.cpp
@@ -86,24 +86,21 @@ bool UnrestrictedGrammar::removeRule(const std::vector<alphabet::Symbol>& leftHa
 	return rules[leftHandSide].erase(rightHandSide);
 }
 
-bool UnrestrictedGrammar::operator==(const ObjectBase& other) const {
-	return other == *this;
+int UnrestrictedGrammar::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool UnrestrictedGrammar::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool UnrestrictedGrammar::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
+int UnrestrictedGrammar::compare(const UnrestrictedGrammar& other) const {
+	auto first = std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules);
+	auto second = std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
 
-bool UnrestrictedGrammar::operator==(const UnrestrictedGrammar& other) const {
-	return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
-}
-
-bool UnrestrictedGrammar::operator<(const UnrestrictedGrammar& other) const {
-	return std::tie(terminalAlphabet, nonterminalAlphabet, initialSymbol, rules) < std::tie(other.terminalAlphabet, other.nonterminalAlphabet, other.initialSymbol, other.rules);
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void UnrestrictedGrammar::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.h b/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.h
index 46ec38d06f..d0b66dbe25 100644
--- a/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.h
+++ b/alib2data/src/grammar/Unrestricted/UnrestrictedGrammar.h
@@ -40,13 +40,8 @@ public:
 
 	bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const UnrestrictedGrammar& other) const;
-
-	virtual bool operator<(const UnrestrictedGrammar& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const UnrestrictedGrammar& other) const;
 
 	virtual void operator>>(std::ostream& os) const;
 
diff --git a/alib2data/src/label/HexavigesimalLabel.cpp b/alib2data/src/label/HexavigesimalLabel.cpp
index 58c101f8af..1aa1a2e703 100644
--- a/alib2data/src/label/HexavigesimalLabel.cpp
+++ b/alib2data/src/label/HexavigesimalLabel.cpp
@@ -26,25 +26,12 @@ int HexavigesimalLabel::getData() const {
 	return hexavigesimal;
 }
 
-bool HexavigesimalLabel::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int HexavigesimalLabel::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool HexavigesimalLabel::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool HexavigesimalLabel::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool HexavigesimalLabel::operator <(const HexavigesimalLabel& other) const {
-	return hexavigesimal < other.hexavigesimal;
-}
-
-bool HexavigesimalLabel::operator ==(const HexavigesimalLabel& other) const {
-	return hexavigesimal == other.hexavigesimal;
+int HexavigesimalLabel::compare(const HexavigesimalLabel& other) const {
+	return hexavigesimal - other.hexavigesimal;
 }
 
 void HexavigesimalLabel::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/label/HexavigesimalLabel.h b/alib2data/src/label/HexavigesimalLabel.h
index ce844d5ab8..57494ab60c 100644
--- a/alib2data/src/label/HexavigesimalLabel.h
+++ b/alib2data/src/label/HexavigesimalLabel.h
@@ -33,19 +33,13 @@ public:
 
 	virtual LabelBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	int getData() const;
 
-	virtual bool operator <(const HexavigesimalLabel& other) const;
-	virtual bool operator ==(const HexavigesimalLabel& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const HexavigesimalLabel& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/label/LabelPairLabel.cpp b/alib2data/src/label/LabelPairLabel.cpp
index 50dd7391a7..5b7c485203 100644
--- a/alib2data/src/label/LabelPairLabel.cpp
+++ b/alib2data/src/label/LabelPairLabel.cpp
@@ -31,25 +31,14 @@ const std::pair<Label, Label>& LabelPairLabel::getData() const {
 	return label;
 }
 
-bool LabelPairLabel::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int LabelPairLabel::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LabelPairLabel::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool LabelPairLabel::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool LabelPairLabel::operator <(const LabelPairLabel& other) const {
-	return label < other.label;
-}
-
-bool LabelPairLabel::operator ==(const LabelPairLabel& other) const {
-	return label == other.label;
+int LabelPairLabel::compare(const LabelPairLabel& other) const {
+	int res = label.first.getData().compare(other.label.first.getData());
+	if(res == 0) res = label.second.getData().compare(other.label.second.getData());
+	return res;
 }
 
 void LabelPairLabel::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/label/LabelPairLabel.h b/alib2data/src/label/LabelPairLabel.h
index 9241485690..aeb32623e1 100644
--- a/alib2data/src/label/LabelPairLabel.h
+++ b/alib2data/src/label/LabelPairLabel.h
@@ -37,19 +37,13 @@ public:
 
 	virtual LabelBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	const std::pair<Label, Label>& getData() const;
 
-	virtual bool operator <(const LabelPairLabel& other) const;
-	virtual bool operator ==(const LabelPairLabel& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const LabelPairLabel& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/label/LabelSetLabel.cpp b/alib2data/src/label/LabelSetLabel.cpp
index 45e00debe4..81c5225a29 100644
--- a/alib2data/src/label/LabelSetLabel.cpp
+++ b/alib2data/src/label/LabelSetLabel.cpp
@@ -31,25 +31,18 @@ const std::set<Label>& LabelSetLabel::getData() const {
 	return label;
 }
 
-bool LabelSetLabel::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int LabelSetLabel::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LabelSetLabel::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool LabelSetLabel::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool LabelSetLabel::operator <(const LabelSetLabel& other) const {
-	return label < other.label;
-}
-
-bool LabelSetLabel::operator ==(const LabelSetLabel& other) const {
-	return label == other.label;
+int LabelSetLabel::compare(const LabelSetLabel& other) const {
+	if(label == other.label) {
+		return 0;
+	} else if(label < other.label) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 void LabelSetLabel::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/label/LabelSetLabel.h b/alib2data/src/label/LabelSetLabel.h
index 9bdf8266c3..2bc5b77d60 100644
--- a/alib2data/src/label/LabelSetLabel.h
+++ b/alib2data/src/label/LabelSetLabel.h
@@ -37,19 +37,13 @@ public:
 
 	virtual LabelBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	const std::set<Label>& getData() const;
 
-	virtual bool operator <(const LabelSetLabel& other) const;
-	virtual bool operator ==(const LabelSetLabel& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const LabelSetLabel& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/label/ObjectLabel.cpp b/alib2data/src/label/ObjectLabel.cpp
index b235b61a25..985115b3e7 100644
--- a/alib2data/src/label/ObjectLabel.cpp
+++ b/alib2data/src/label/ObjectLabel.cpp
@@ -29,24 +29,12 @@ const alib::Object& ObjectLabel::getData() const {
 	return label;
 }
 
-bool ObjectLabel::operator <(const alib::ObjectBase& other) const {
-	return other > *this;
+int ObjectLabel::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool ObjectLabel::operator ==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool ObjectLabel::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-bool ObjectLabel::operator <(const ObjectLabel& other) const {
-	return label < other.label;
-}
-
-bool ObjectLabel::operator ==(const ObjectLabel& other) const {
-	return label == other.label;
+int ObjectLabel::compare(const ObjectLabel& other) const {
+	return label.getData().compare(other.label.getData());
 }
 
 void ObjectLabel::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/label/ObjectLabel.h b/alib2data/src/label/ObjectLabel.h
index a4bc6ff70f..d5485d6c51 100644
--- a/alib2data/src/label/ObjectLabel.h
+++ b/alib2data/src/label/ObjectLabel.h
@@ -35,20 +35,14 @@ public:
 
 	virtual LabelBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	const alib::Object& getData() const;
 
-	virtual bool operator <(const ObjectLabel& other) const;
-	
-	virtual bool operator ==(const ObjectLabel& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+
+	virtual int compare(const ObjectLabel& other) const;
 	
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/label/PrimitiveLabel.cpp b/alib2data/src/label/PrimitiveLabel.cpp
index 7826e901ff..35f63ae282 100644
--- a/alib2data/src/label/PrimitiveLabel.cpp
+++ b/alib2data/src/label/PrimitiveLabel.cpp
@@ -29,25 +29,12 @@ const primitive::Primitive& PrimitiveLabel::getData() const {
 	return primitive;
 }
 
-bool PrimitiveLabel::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int PrimitiveLabel::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool PrimitiveLabel::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool PrimitiveLabel::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool PrimitiveLabel::operator <(const PrimitiveLabel& other) const {
-	return primitive < other.primitive;
-}
-
-bool PrimitiveLabel::operator ==(const PrimitiveLabel& other) const {
-	return primitive == other.primitive;
+int PrimitiveLabel::compare(const PrimitiveLabel& other) const {
+	return primitive.getData().compare(other.primitive.getData());
 }
 
 void PrimitiveLabel::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/label/PrimitiveLabel.h b/alib2data/src/label/PrimitiveLabel.h
index 784f9fb44e..6faa087a12 100644
--- a/alib2data/src/label/PrimitiveLabel.h
+++ b/alib2data/src/label/PrimitiveLabel.h
@@ -35,19 +35,13 @@ public:
 
 	virtual LabelBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	const primitive::Primitive& getData() const;
 
-	virtual bool operator <(const PrimitiveLabel& other) const;
-	virtual bool operator ==(const PrimitiveLabel& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const PrimitiveLabel& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/object/Void.cpp b/alib2data/src/object/Void.cpp
index 4c86fe19fa..4476934083 100644
--- a/alib2data/src/object/Void.cpp
+++ b/alib2data/src/object/Void.cpp
@@ -21,24 +21,12 @@ ObjectBase* Void::plunder() && {
 	return new Void(std::move(*this));
 }
 
-bool Void::operator <(const ObjectBase& other) const {
-	return other > *this;
+int Void::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool Void::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool Void::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
-bool Void::operator ==(const Void&) const {
-	return true;
-}
-
-bool Void::operator <(const Void&) const {
-	return false;
+int Void::compare(const Void&) const {
+	return 0;
 }
 
 void Void::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/object/Void.h b/alib2data/src/object/Void.h
index fa35b2295d..1218433d7d 100644
--- a/alib2data/src/object/Void.h
+++ b/alib2data/src/object/Void.h
@@ -28,12 +28,8 @@ public:
 	virtual ObjectBase* clone() const;
 	virtual ObjectBase* plunder() &&;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator ==(const Void& other) const;
-	virtual bool operator <(const Void& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const Void& other) const;
 
 	virtual void operator>>(std::ostream& out) const;
 
diff --git a/alib2data/src/primitive/Character.cpp b/alib2data/src/primitive/Character.cpp
index b982d97912..925d7da08b 100644
--- a/alib2data/src/primitive/Character.cpp
+++ b/alib2data/src/primitive/Character.cpp
@@ -25,25 +25,12 @@ char Character::getData() const {
 	return data;
 }
 
-bool Character::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int Character::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool Character::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool Character::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool Character::operator <(const Character& other) const {
-	return data < other.data;
-}
-
-bool Character::operator ==(const Character& other) const {
-	return data == other.data;
+int Character::compare(const Character& other) const {
+	return data - other.data;
 }
 
 void Character::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/primitive/Character.h b/alib2data/src/primitive/Character.h
index ad358b7bba..f36c11e0cc 100644
--- a/alib2data/src/primitive/Character.h
+++ b/alib2data/src/primitive/Character.h
@@ -33,20 +33,13 @@ public:
 
 	virtual PrimitiveBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	char getData() const;
 
-	virtual bool operator <(const Character& other) const;
-
-	virtual bool operator ==(const Character& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const Character& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/primitive/Integer.cpp b/alib2data/src/primitive/Integer.cpp
index 79eabd451d..45635444cc 100644
--- a/alib2data/src/primitive/Integer.cpp
+++ b/alib2data/src/primitive/Integer.cpp
@@ -25,24 +25,12 @@ int Integer::getData() const {
 	return data;
 }
 
-bool Integer::operator <(const alib::ObjectBase& other) const {
-	return other > *this;
+int Integer::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool Integer::operator ==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool Integer::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-bool Integer::operator <(const Integer& other) const {
-	return data < other.data;
-}
-
-bool Integer::operator ==(const Integer& other) const {
-	return data == other.data;
+int Integer::compare(const Integer& other) const {
+	return data - other.data;
 }
 
 void Integer::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/primitive/Integer.h b/alib2data/src/primitive/Integer.h
index e70ca141c7..6453e3905b 100644
--- a/alib2data/src/primitive/Integer.h
+++ b/alib2data/src/primitive/Integer.h
@@ -32,20 +32,14 @@ public:
 
 	virtual PrimitiveBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-	
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	int getData() const;
 
-	virtual bool operator <(const Integer& other) const;
-	
-	virtual bool operator ==(const Integer& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+
+	virtual int compare(const Integer& other) const;
 	
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/primitive/String.cpp b/alib2data/src/primitive/String.cpp
index af62a6e549..659b031045 100644
--- a/alib2data/src/primitive/String.cpp
+++ b/alib2data/src/primitive/String.cpp
@@ -29,25 +29,12 @@ const std::string& String::getData() const {
 	return data;
 }
 
-bool String::operator<(const alib::ObjectBase& other) const {
-	return other > *this;
+int String::compare(const alib::ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool String::operator==(const alib::ObjectBase& other) const {
-	return other == *this;
-}
-
-bool String::operator >(const alib::ObjectBase& other) const {
-	return other < *this;
-}
-
-
-bool String::operator <(const String& other) const {
-	return data < other.data;
-}
-
-bool String::operator ==(const String& other) const {
-	return data == other.data;
+int String::compare(const String& other) const {
+	return data.compare(other.data);
 }
 
 void String::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/primitive/String.h b/alib2data/src/primitive/String.h
index 5007dfd8fd..dd74681d17 100644
--- a/alib2data/src/primitive/String.h
+++ b/alib2data/src/primitive/String.h
@@ -35,20 +35,14 @@ public:
 
 	virtual PrimitiveBase* plunder() &&;
 
-	virtual bool operator<(const alib::ObjectBase& other) const;
-
-	virtual bool operator>(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return name of the symbol
 	 */
 	const std::string& getData() const;
 
-	virtual bool operator <(const String& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
 
-	virtual bool operator ==(const String& other) const;
+	virtual int compare(const String& other) const;
 
 	virtual void operator>>(std::ostream&) const;
 
diff --git a/alib2data/src/regexp/formal/FormalRegExp.cpp b/alib2data/src/regexp/formal/FormalRegExp.cpp
index 62241b7b6b..7e9df81cc2 100644
--- a/alib2data/src/regexp/formal/FormalRegExp.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExp.cpp
@@ -142,24 +142,21 @@ void FormalRegExp::operator >>(std::ostream& out) const {
 	out << "(FormalRegExp " << *(this->regExp) << ")";
 }
 
-bool FormalRegExp::operator<(const FormalRegExp& other) const {
-	return std::tie(*regExp, alphabet) < std::tie(*other.regExp, other.alphabet);
+int FormalRegExp::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExp::operator==(const FormalRegExp& other) const {
-	return *regExp == *other.regExp && this->alphabet == other.alphabet;
-}
-
-bool FormalRegExp::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
+int FormalRegExp::compare(const FormalRegExp& other) const {
+	auto first = std::tie(*regExp, alphabet);
+	auto second = std::tie(*other.regExp, other.alphabet);
 
-bool FormalRegExp::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool FormalRegExp::operator >(const ObjectBase& other) const {
-	return other < *this;
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 FormalRegExp::operator std::string () const {
diff --git a/alib2data/src/regexp/formal/FormalRegExp.h b/alib2data/src/regexp/formal/FormalRegExp.h
index 2322d43694..705e59715f 100644
--- a/alib2data/src/regexp/formal/FormalRegExp.h
+++ b/alib2data/src/regexp/formal/FormalRegExp.h
@@ -112,13 +112,8 @@ public:
 	 */
 	virtual void operator>>(std::ostream& out) const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const FormalRegExp& other) const;
-
-	virtual bool operator<(const FormalRegExp& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const FormalRegExp& other) const;
 
 	virtual operator std::string() const;
 
diff --git a/alib2data/src/regexp/formal/FormalRegExpAlternation.cpp b/alib2data/src/regexp/formal/FormalRegExpAlternation.cpp
index d01a6a9508..d6cae69d65 100644
--- a/alib2data/src/regexp/formal/FormalRegExpAlternation.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpAlternation.cpp
@@ -128,26 +128,14 @@ UnboundedRegExpElement* FormalRegExpAlternation::cloneAsUnbounded() const {
 	return res;
 }
 
-bool FormalRegExpAlternation::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpAlternation::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpAlternation::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpAlternation::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool FormalRegExpAlternation::operator<(const FormalRegExpAlternation& other) const {
-	if(*left == *other.left) return *right < *other.right;
-	return *left < *other.left;
-}
-
-bool FormalRegExpAlternation::operator==(const FormalRegExpAlternation& other) const {
-	return *left == *other.left && *right == *other.right;
+int FormalRegExpAlternation::compare(const FormalRegExpAlternation& other) const {
+	int res = left->compare(*other.left);
+	if(res == 0) res = right->compare(*other.right);
+	return res;
 }
 
 void FormalRegExpAlternation::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpAlternation.h b/alib2data/src/regexp/formal/FormalRegExpAlternation.h
index 0ff6327c5b..5d4e51bdb1 100644
--- a/alib2data/src/regexp/formal/FormalRegExpAlternation.h
+++ b/alib2data/src/regexp/formal/FormalRegExpAlternation.h
@@ -92,12 +92,8 @@ public:
 	void setRightElement(const FormalRegExpElement& element);
 	void setRightElement(FormalRegExpElement&& element);
 
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpAlternation&) const;
-	virtual bool operator==(const FormalRegExpAlternation&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpAlternation&) const;
 	
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/formal/FormalRegExpConcatenation.cpp b/alib2data/src/regexp/formal/FormalRegExpConcatenation.cpp
index 07c1b4327f..5eb76c295e 100644
--- a/alib2data/src/regexp/formal/FormalRegExpConcatenation.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpConcatenation.cpp
@@ -127,26 +127,14 @@ FormalRegExpElement* FormalRegExpConcatenation::plunder() && {
 	return new FormalRegExpConcatenation(std::move(*this));
 }
 
-bool FormalRegExpConcatenation::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpConcatenation::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpConcatenation::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpConcatenation::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool FormalRegExpConcatenation::operator<(const FormalRegExpConcatenation& other) const {
-	if(*left == *other.left) return *right < *other.right;
-	return *left < *other.left;
-}
-
-bool FormalRegExpConcatenation::operator==(const FormalRegExpConcatenation& other) const {
-	return *left == *other.left && *right == *other.right;
+int FormalRegExpConcatenation::compare(const FormalRegExpConcatenation& other) const {
+	int res = left->compare(*other.left);
+	if(res == 0) res = right->compare(*other.right);
+	return res;
 }
 
 void FormalRegExpConcatenation::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpConcatenation.h b/alib2data/src/regexp/formal/FormalRegExpConcatenation.h
index b88af6b589..ca2463c3bc 100644
--- a/alib2data/src/regexp/formal/FormalRegExpConcatenation.h
+++ b/alib2data/src/regexp/formal/FormalRegExpConcatenation.h
@@ -90,12 +90,8 @@ public:
 	void setRightElement(const FormalRegExpElement& element);
 	void setRightElement(FormalRegExpElement&& element);
 
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpConcatenation&) const;
-	virtual bool operator==(const FormalRegExpConcatenation&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpConcatenation&) const;
 
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/formal/FormalRegExpEmpty.cpp b/alib2data/src/regexp/formal/FormalRegExpEmpty.cpp
index a55e9a92bd..964ac14ea6 100644
--- a/alib2data/src/regexp/formal/FormalRegExpEmpty.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpEmpty.cpp
@@ -44,25 +44,12 @@ UnboundedRegExpElement* FormalRegExpEmpty::cloneAsUnbounded() const {
 	return new UnboundedRegExpEmpty();
 }
 
-bool FormalRegExpEmpty::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpEmpty::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpEmpty::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpEmpty::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool FormalRegExpEmpty::operator<(const FormalRegExpEmpty&) const {
-	return false;
-}
-
-bool FormalRegExpEmpty::operator==(const FormalRegExpEmpty&) const {
-	return true;
+int FormalRegExpEmpty::compare(const FormalRegExpEmpty&) const {
+	return 0;
 }
 
 void FormalRegExpEmpty::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpEmpty.h b/alib2data/src/regexp/formal/FormalRegExpEmpty.h
index 300cd803fa..94fe4f5129 100644
--- a/alib2data/src/regexp/formal/FormalRegExpEmpty.h
+++ b/alib2data/src/regexp/formal/FormalRegExpEmpty.h
@@ -55,12 +55,8 @@ public:
 	 */
 	virtual FormalRegExpElement* plunder() &&;
 
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpEmpty&) const;
-	virtual bool operator==(const FormalRegExpEmpty&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpEmpty&) const;
 	
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/formal/FormalRegExpEpsilon.cpp b/alib2data/src/regexp/formal/FormalRegExpEpsilon.cpp
index 8d3d8563a2..ad3414027f 100644
--- a/alib2data/src/regexp/formal/FormalRegExpEpsilon.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpEpsilon.cpp
@@ -45,25 +45,12 @@ UnboundedRegExpElement* FormalRegExpEpsilon::cloneAsUnbounded() const {
 	return new UnboundedRegExpEpsilon();
 }
 
-bool FormalRegExpEpsilon::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpEpsilon::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpEpsilon::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpEpsilon::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool FormalRegExpEpsilon::operator<(const FormalRegExpEpsilon&) const {
-	  return false;
-}
-
-bool FormalRegExpEpsilon::operator==(const FormalRegExpEpsilon&) const {
-	  return true;
+int FormalRegExpEpsilon::compare(const FormalRegExpEpsilon&) const {
+	  return 0;
 }
 
 void FormalRegExpEpsilon::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpEpsilon.h b/alib2data/src/regexp/formal/FormalRegExpEpsilon.h
index e146862bca..6ab5146a97 100644
--- a/alib2data/src/regexp/formal/FormalRegExpEpsilon.h
+++ b/alib2data/src/regexp/formal/FormalRegExpEpsilon.h
@@ -56,12 +56,8 @@ public:
 	 */
 	virtual FormalRegExpElement* plunder() &&;
 	
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpEpsilon&) const;
-	virtual bool operator==(const FormalRegExpEpsilon&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpEpsilon&) const;
 	
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/formal/FormalRegExpIteration.cpp b/alib2data/src/regexp/formal/FormalRegExpIteration.cpp
index ea044dc85c..785f8543ca 100644
--- a/alib2data/src/regexp/formal/FormalRegExpIteration.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpIteration.cpp
@@ -93,24 +93,12 @@ UnboundedRegExpElement* FormalRegExpIteration::cloneAsUnbounded() const {
 	return res;
 }
 
-bool FormalRegExpIteration::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpIteration::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpIteration::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpIteration::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-bool FormalRegExpIteration::operator<(const FormalRegExpIteration& other) const {
-	return *element < *other.element;
-}
-
-bool FormalRegExpIteration::operator==(const FormalRegExpIteration& other) const {
-	return *element == *other.element;
+int FormalRegExpIteration::compare(const FormalRegExpIteration& other) const {
+	return element->compare(*other.element);
 }
 
 void FormalRegExpIteration::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpIteration.h b/alib2data/src/regexp/formal/FormalRegExpIteration.h
index 9d0629cd76..830d6e8562 100644
--- a/alib2data/src/regexp/formal/FormalRegExpIteration.h
+++ b/alib2data/src/regexp/formal/FormalRegExpIteration.h
@@ -85,12 +85,8 @@ public:
 	
 	void setElement(FormalRegExpElement&& element);
 
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpIteration&) const;
-	virtual bool operator==(const FormalRegExpIteration&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpIteration&) const;
 
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/formal/FormalRegExpSymbol.cpp b/alib2data/src/regexp/formal/FormalRegExpSymbol.cpp
index 6849734da8..ef8ec7f7ee 100644
--- a/alib2data/src/regexp/formal/FormalRegExpSymbol.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExpSymbol.cpp
@@ -78,25 +78,12 @@ bool operator==(const alphabet::Symbol& first, const FormalRegExpSymbol& second)
 	return first == second.symbol;
 }
 
-bool FormalRegExpSymbol::operator<(const FormalRegExpElement& other) const {
-	return other > *this;
+int FormalRegExpSymbol::compare(const FormalRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool FormalRegExpSymbol::operator==(const FormalRegExpElement& other) const {
-	return other == *this;
-}
-
-bool FormalRegExpSymbol::operator>(const FormalRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool FormalRegExpSymbol::operator<(const FormalRegExpSymbol& other) const {
-	return symbol < other.symbol;
-}
-
-bool FormalRegExpSymbol::operator==(const FormalRegExpSymbol& other) const {
-	return symbol == other.symbol;
+int FormalRegExpSymbol::compare(const FormalRegExpSymbol& other) const {
+	return symbol.getData().compare(other.symbol.getData());
 }
 
 void FormalRegExpSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/formal/FormalRegExpSymbol.h b/alib2data/src/regexp/formal/FormalRegExpSymbol.h
index 05cbbb1219..110adea9af 100644
--- a/alib2data/src/regexp/formal/FormalRegExpSymbol.h
+++ b/alib2data/src/regexp/formal/FormalRegExpSymbol.h
@@ -67,12 +67,8 @@ public:
 	bool operator==(const alphabet::Symbol&) const;
 	friend bool operator==(const alphabet::Symbol&, const FormalRegExpSymbol&);
 
-	virtual bool operator<(const FormalRegExpElement&) const;
-	virtual bool operator==(const FormalRegExpElement&) const;
-	virtual bool operator>(const FormalRegExpElement&) const;
-
-	virtual bool operator<(const FormalRegExpSymbol&) const;
-	virtual bool operator==(const FormalRegExpSymbol&) const;
+	virtual int compare(const FormalRegExpElement&) const;
+	virtual int compare(const FormalRegExpSymbol&) const;
 	
 	/**
 	 * @copydoc FormalRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
index 237f6bb309..ec8e69e6cd 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
@@ -142,24 +142,21 @@ void UnboundedRegExp::operator >>(std::ostream& out) const {
 	out << "(UnboundedRegExp " << *(this->regExp) << ")";
 }
 
-bool UnboundedRegExp::operator<(const UnboundedRegExp& other) const {
-	return std::tie(*regExp, alphabet) < std::tie(*other.regExp, other.alphabet);
+int UnboundedRegExp::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExp::operator==(const UnboundedRegExp& other) const {
-	return *regExp == *other.regExp && this->alphabet == other.alphabet;
-}
-
-bool UnboundedRegExp::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
+int UnboundedRegExp::compare(const UnboundedRegExp& other) const {
+	auto first = std::tie(*regExp, alphabet);
+	auto second = std::tie(*other.regExp, other.alphabet);
 
-bool UnboundedRegExp::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExp::operator >(const ObjectBase& other) const {
-	return other < *this;
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
 UnboundedRegExp::operator std::string () const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExp.h b/alib2data/src/regexp/unbounded/UnboundedRegExp.h
index 81a0f29af3..934492fac8 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExp.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExp.h
@@ -112,13 +112,8 @@ public:
 	 */
 	virtual void operator>>(std::ostream& out) const;
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
-	virtual bool operator==(const UnboundedRegExp& other) const;
-
-	virtual bool operator<(const UnboundedRegExp& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
+	virtual int compare(const UnboundedRegExp& other) const;
 
 	virtual operator std::string() const;
 
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp
index 52f17c3fcc..b81cb5a0f6 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp
@@ -108,45 +108,23 @@ FormalRegExpElement* UnboundedRegExpAlternation::cloneAsFormal() const {
 	return res;
 }
 
-bool UnboundedRegExpAlternation::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpAlternation::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpAlternation::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpAlternation::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool UnboundedRegExpAlternation::operator<(const UnboundedRegExpAlternation& other) const {
+int UnboundedRegExpAlternation::compare(const UnboundedRegExpAlternation& other) const {
 	int thisSize = this->elements.size();
 	int otherSize = other.elements.size();
-	if(thisSize < otherSize) return true;
-	if(thisSize > otherSize) return false;
+	if(thisSize < otherSize) return -1;
+	if(thisSize > otherSize) return 1;
 
 	auto thisIter = this->elements.begin();
 	auto otherIter = other.elements.begin();
 	for(; thisIter != this->elements.end(); thisIter++, otherIter++) {
-	  if(**thisIter != **otherIter) break;
+		int res = (*thisIter)->compare(**otherIter);
+		if(res != 0) return res;
 	}
-	if(thisIter == this->elements.end()) return false;
-
-	return **thisIter < **otherIter;
-}
-
-bool UnboundedRegExpAlternation::operator==(const UnboundedRegExpAlternation& other) const {
-	if(this->elements.size() != other.elements.size()) return false;
-
-	auto thisIter = this->elements.begin();
-	auto otherIter = other.elements.begin();
-	for(; thisIter != this->elements.end(); thisIter++, otherIter++) {
-	  if(**thisIter != **otherIter) return false;
-	}
-
-	return true;
+	return 0;
 }
 
 void UnboundedRegExpAlternation::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h
index ab78cbfdac..669d29d913 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h
@@ -86,12 +86,8 @@ public:
 	 */
 	void appendElement(UnboundedRegExpElement&& element);
 
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpAlternation&) const;
-	virtual bool operator==(const UnboundedRegExpAlternation&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpAlternation&) const;
 
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp
index 96a9f65834..a632d5bcac 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp
@@ -107,45 +107,23 @@ FormalRegExpElement* UnboundedRegExpConcatenation::cloneAsFormal() const {
 	return res;
 }
 
-bool UnboundedRegExpConcatenation::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpConcatenation::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpConcatenation::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpConcatenation::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool UnboundedRegExpConcatenation::operator<(const UnboundedRegExpConcatenation& other) const {
+int UnboundedRegExpConcatenation::compare(const UnboundedRegExpConcatenation& other) const {
 	int thisSize = this->elements.size();
 	int otherSize = other.elements.size();
-	if(thisSize < otherSize) return true;
-	if(thisSize > otherSize) return false;
+	if(thisSize < otherSize) return -1;
+	if(thisSize > otherSize) return 1;
 
 	auto thisIter = this->elements.begin();
 	auto otherIter = other.elements.begin();
 	for(; thisIter != this->elements.end(); thisIter++, otherIter++) {
-		if(**thisIter != **otherIter) break;
+		int res = (*thisIter)->compare(**otherIter);
+		if(res != 0) return res;
 	}
-	if(thisIter == this->elements.end()) return false;
-
-	return **thisIter < **otherIter;
-}
-
-bool UnboundedRegExpConcatenation::operator==(const UnboundedRegExpConcatenation& other) const {
-	if(this->elements.size() != other.elements.size()) return false;
-
-	auto thisIter = this->elements.begin();
-	auto otherIter = other.elements.begin();
-	for(; thisIter != this->elements.end(); thisIter++, otherIter++) {
-		if(**thisIter != **otherIter) return false;
-	}
-
-	return true;
+	return 0;
 }
 
 void UnboundedRegExpConcatenation::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h
index 04314dfad6..c69543fc03 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h
@@ -85,12 +85,8 @@ public:
 	
 	void appendElement(UnboundedRegExpElement&& element);
 
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpConcatenation&) const;
-	virtual bool operator==(const UnboundedRegExpConcatenation&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpConcatenation&) const;
 
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp
index 06d15fa34e..893ab6b978 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp
@@ -45,25 +45,12 @@ FormalRegExpElement* UnboundedRegExpEmpty::cloneAsFormal() const {
 	return new FormalRegExpEmpty();
 }
 
-bool UnboundedRegExpEmpty::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpEmpty::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpEmpty::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpEmpty::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool UnboundedRegExpEmpty::operator<(const UnboundedRegExpEmpty&) const {
-	return false;
-}
-
-bool UnboundedRegExpEmpty::operator==(const UnboundedRegExpEmpty&) const {
-	return true;
+int UnboundedRegExpEmpty::compare(const UnboundedRegExpEmpty&) const {
+	return 0;
 }
 
 void UnboundedRegExpEmpty::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h
index 97fd1c08fe..eff46b8832 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h
@@ -54,12 +54,8 @@ public:
 	 */
 	virtual UnboundedRegExpElement* plunder() &&;
 
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpEmpty&) const;
-	virtual bool operator==(const UnboundedRegExpEmpty&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpEmpty&) const;
 	
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp
index f190a6055f..c1662b17e3 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp
@@ -45,25 +45,12 @@ FormalRegExpElement* UnboundedRegExpEpsilon::cloneAsFormal() const {
 	return new FormalRegExpEpsilon();
 }
 
-bool UnboundedRegExpEpsilon::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpEpsilon::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpEpsilon::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpEpsilon::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool UnboundedRegExpEpsilon::operator<(const UnboundedRegExpEpsilon&) const {
-	  return false;
-}
-
-bool UnboundedRegExpEpsilon::operator==(const UnboundedRegExpEpsilon&) const {
-	  return true;
+int UnboundedRegExpEpsilon::compare(const UnboundedRegExpEpsilon&) const {
+	  return 0;
 }
 
 void UnboundedRegExpEpsilon::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h
index df1c9205c4..974a276582 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h
@@ -56,12 +56,8 @@ public:
 	virtual UnboundedRegExpElement* plunder() &&;
 	
 	
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpEpsilon&) const;
-	virtual bool operator==(const UnboundedRegExpEpsilon&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpEpsilon&) const;
 	
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp
index e2f9d5cf20..2e59769638 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp
@@ -93,24 +93,12 @@ FormalRegExpElement* UnboundedRegExpIteration::cloneAsFormal() const {
 	return res;
 }
 
-bool UnboundedRegExpIteration::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpIteration::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpIteration::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpIteration::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-bool UnboundedRegExpIteration::operator<(const UnboundedRegExpIteration& other) const {
-	return *(this->element) < *(other.element);
-}
-
-bool UnboundedRegExpIteration::operator==(const UnboundedRegExpIteration& other) const {
-	return *(this->element) == *(other.element);
+int UnboundedRegExpIteration::compare(const UnboundedRegExpIteration& other) const {
+	return element->compare(*other.element);
 }
 
 void UnboundedRegExpIteration::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h
index 26901d9629..30bf2f8fe3 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h
@@ -84,12 +84,8 @@ public:
 	
 	void setElement(UnboundedRegExpElement&& element);
 
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpIteration&) const;
-	virtual bool operator==(const UnboundedRegExpIteration&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpIteration&) const;
 
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp
index 77f399bead..f06d1c1686 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp
@@ -78,25 +78,12 @@ bool operator==(const alphabet::Symbol& first, const UnboundedRegExpSymbol& seco
 	return first == second.symbol;
 }
 
-bool UnboundedRegExpSymbol::operator<(const UnboundedRegExpElement& other) const {
-	return other > *this;
+int UnboundedRegExpSymbol::compare(const UnboundedRegExpElement& other) const {
+	return -other.compare(*this);
 }
 
-bool UnboundedRegExpSymbol::operator==(const UnboundedRegExpElement& other) const {
-	return other == *this;
-}
-
-bool UnboundedRegExpSymbol::operator>(const UnboundedRegExpElement& other) const {
-	return other < *this;
-}
-
-
-bool UnboundedRegExpSymbol::operator<(const UnboundedRegExpSymbol& other) const {
-	return symbol < other.symbol;
-}
-
-bool UnboundedRegExpSymbol::operator==(const UnboundedRegExpSymbol& other) const {
-	return symbol == other.symbol;
+int UnboundedRegExpSymbol::compare(const UnboundedRegExpSymbol& other) const {
+	return symbol.getData().compare(other.symbol.getData());
 }
 
 void UnboundedRegExpSymbol::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h
index d0c08c69e4..8491667ba3 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h
@@ -66,12 +66,8 @@ public:
 	bool operator==(const alphabet::Symbol&) const;
 	friend bool operator==(const alphabet::Symbol&, const UnboundedRegExpSymbol&);
 
-	virtual bool operator<(const UnboundedRegExpElement&) const;
-	virtual bool operator==(const UnboundedRegExpElement&) const;
-	virtual bool operator>(const UnboundedRegExpElement&) const;
-
-	virtual bool operator<(const UnboundedRegExpSymbol&) const;
-	virtual bool operator==(const UnboundedRegExpSymbol&) const;
+	virtual int compare(const UnboundedRegExpElement&) const;
+	virtual int compare(const UnboundedRegExpSymbol&) const;
 	
 	/**
 	 * @copydoc UnboundedRegExpElement::operator>>() const
diff --git a/alib2data/src/std/tuple.hpp b/alib2data/src/std/tuple.hpp
index 76fe870ac5..93396f3188 100644
--- a/alib2data/src/std/tuple.hpp
+++ b/alib2data/src/std/tuple.hpp
@@ -37,15 +37,10 @@ struct operator_shift_left_impl<0, Tuple> {
 	}
 };
 
-template<class Tuple>
-void operator_shift_left(ostream& out, const Tuple& t) {
-	operator_shift_left_impl<tuple_size<Tuple>::value - 1, Tuple>::operator_shift_left(out, t);
-}
-
 template< class... Ts>
 std::ostream& operator<<(std::ostream& out, const std::tuple<Ts...>& tuple) {
 	out << "(";
-	operator_shift_left(out, tuple);
+	operator_shift_left_impl<tuple_size<std::tuple<Ts...>>::value - 1, std::tuple<Ts...>>::operator_shift_left(out, tuple);
 	out << ")";
 	return out;
 }
diff --git a/alib2data/src/string/CyclicString.cpp b/alib2data/src/string/CyclicString.cpp
index fafb145726..0ccfdc33fe 100644
--- a/alib2data/src/string/CyclicString.cpp
+++ b/alib2data/src/string/CyclicString.cpp
@@ -50,6 +50,10 @@ CyclicString::CyclicString(const std::string& str) {
 	alphabet = std::set<alphabet::Symbol>(m_Data.begin(), m_Data.end());
 }
 
+CyclicString::CyclicString(const Epsilon& epsilon) {
+	alphabet = epsilon.getAlphabet();
+}
+
 StringBase* CyclicString::clone() const {
 	return new CyclicString(*this);
 }
@@ -65,18 +69,6 @@ bool CyclicString::removeSymbolFromAlphabet(const alphabet::Symbol & symbol) {
 	return alphabet.erase(symbol);
 }
 
-bool CyclicString::operator <(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool CyclicString::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool CyclicString::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
 const std::vector<alphabet::Symbol>& CyclicString::getContent() const {
 	return this->m_Data;
 }
@@ -97,32 +89,53 @@ bool CyclicString::isEmpty() const {
 	return this->m_Data.size() == 0;
 }
 
-bool CyclicString::operator<(const LinearString& other) const {
-	if(this->isEmpty() && other.isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
+int CyclicString::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool CyclicString::operator<(const CyclicString& other) const {
-	return std::tie(m_Data, alphabet) < std::tie(other.m_Data, other.alphabet);
+int CyclicString::compare(const LinearString& other) const {
+	if(this->isEmpty() && other.isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		else if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
+	
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
 }
 
-bool CyclicString::operator<(const Epsilon& other) const {
-	if(this->isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
-}
+int CyclicString::compare(const CyclicString& other) const {
+	auto first = std::tie(m_Data, alphabet);
+	auto second = std::tie(other.m_Data, other.alphabet);
 
-bool CyclicString::operator==(const LinearString& other) const {
-	if(this->isEmpty() && other.isEmpty()) return alphabet == other.getAlphabet();
-	return false;
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
-bool CyclicString::operator==(const CyclicString& other) const {
-	return m_Data == other.m_Data && alphabet == other.getAlphabet();
-}
+int CyclicString::compare(const Epsilon& other) const {
+	if(this->isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		else if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
 
-bool CyclicString::operator==(const Epsilon& other) const {
-	if(this->isEmpty()) return alphabet == other.getAlphabet();
-	return false;
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
 }
 
 void CyclicString::operator >>(std::ostream& out) const {
diff --git a/alib2data/src/string/CyclicString.h b/alib2data/src/string/CyclicString.h
index 61e5b8851b..c85099f747 100644
--- a/alib2data/src/string/CyclicString.h
+++ b/alib2data/src/string/CyclicString.h
@@ -16,6 +16,7 @@
 #include "../alphabet/Symbol.h"
 #include "StringBase.h"
 #include "common/StringAlphabet.h"
+#include "Epsilon.h"
 
 namespace string {
 
@@ -32,16 +33,13 @@ public:
 	explicit CyclicString(const std::vector<alphabet::Symbol>& data);
 	explicit CyclicString(std::vector<alphabet::Symbol>&& data);
 	explicit CyclicString(const std::string& str);
+	explicit CyclicString(const Epsilon& epsilon);
 
 	virtual StringBase* clone() const;
 	virtual StringBase* plunder() &&;
 
 	virtual bool removeSymbolFromAlphabet(const alphabet::Symbol & symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return List of symbols forming string (const version).
 	 */
@@ -54,13 +52,11 @@ public:
 	 */
 	bool isEmpty() const;
 
-	virtual bool operator<(const LinearString& other) const;
-	virtual bool operator<(const CyclicString& other) const;
-	virtual bool operator<(const Epsilon& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
 
-	virtual bool operator==(const LinearString& other) const;
-	virtual bool operator==(const CyclicString& other) const;
-	virtual bool operator==(const Epsilon& other) const;
+	virtual int compare(const LinearString& other) const;
+	virtual int compare(const CyclicString& other) const;
+	virtual int compare(const Epsilon& other) const;
 
 	virtual void operator >>(std::ostream& out) const;
 
diff --git a/alib2data/src/string/Epsilon.cpp b/alib2data/src/string/Epsilon.cpp
index 7950335b84..d7cb03b2b9 100644
--- a/alib2data/src/string/Epsilon.cpp
+++ b/alib2data/src/string/Epsilon.cpp
@@ -26,18 +26,6 @@ bool Epsilon::removeSymbolFromAlphabet(const alphabet::Symbol & symbol) {
 	return alphabet.erase(symbol);
 }
 
-bool Epsilon::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool Epsilon::operator==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool Epsilon::operator>(const ObjectBase& other) const {
-	return other < *this;
-}
-
 std::vector<alphabet::Symbol> Epsilon::getContent() const {
 	return {};
 }
@@ -46,32 +34,49 @@ bool Epsilon::isEmpty() const {
 	return true;
 }
 
-bool Epsilon::operator<(const Epsilon& other) const {
-	return alphabet < other.alphabet;
-}
-
-bool Epsilon::operator<(const LinearString& other) const {
-	if(other.isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
-}
-
-bool Epsilon::operator<(const CyclicString& other) const {
-	if(other.isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
-}
-
-bool Epsilon::operator==(const Epsilon& other) const {
-	return alphabet == other.alphabet;
-}
-
-bool Epsilon::operator==(const LinearString& other) const {
-	if(other.isEmpty()) return alphabet == other.getAlphabet();
-	return false;
-}
-
-bool Epsilon::operator==(const CyclicString& other) const {
-	if(other.isEmpty()) return alphabet == other.getAlphabet();
-	return false;
+int Epsilon::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
+}
+
+int Epsilon::compare(const Epsilon& other) const {
+	if(alphabet == other.alphabet)
+		return 0;
+	else if(alphabet < other.alphabet)
+		return -1;
+	else
+		return 1;
+}
+
+int Epsilon::compare(const LinearString& other) const {
+	if(other.isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		else if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
+
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
+}
+
+int Epsilon::compare(const CyclicString& other) const {
+	if(other.isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		else if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
+
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
 }
 
 void Epsilon::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/string/Epsilon.h b/alib2data/src/string/Epsilon.h
index bf39c0cf98..81ecbf3202 100644
--- a/alib2data/src/string/Epsilon.h
+++ b/alib2data/src/string/Epsilon.h
@@ -30,10 +30,6 @@ public:
 
 	virtual bool removeSymbolFromAlphabet(const alphabet::Symbol & symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return List of symbols forming string (const version).
 	 */
@@ -44,13 +40,11 @@ public:
 	 */
 	bool isEmpty() const;
 
-	virtual bool operator<(const LinearString& other) const;
-	virtual bool operator<(const CyclicString& other) const;
-	virtual bool operator<(const Epsilon& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
 
-	virtual bool operator==(const LinearString& other) const;
-	virtual bool operator==(const CyclicString& other) const;
-	virtual bool operator==(const Epsilon& other) const;
+	virtual int compare(const LinearString& other) const;
+	virtual int compare(const CyclicString& other) const;
+	virtual int compare(const Epsilon& other) const;
 
 	virtual void operator >>(std::ostream& out) const;
 
diff --git a/alib2data/src/string/LinearString.cpp b/alib2data/src/string/LinearString.cpp
index d1e1626c0c..840336ce9a 100644
--- a/alib2data/src/string/LinearString.cpp
+++ b/alib2data/src/string/LinearString.cpp
@@ -50,6 +50,10 @@ LinearString::LinearString(const std::string& str) {
 	alphabet = std::set<alphabet::Symbol>(m_Data.begin(), m_Data.end());
 }
 
+LinearString::LinearString(const Epsilon& epsilon) {
+	alphabet = epsilon.getAlphabet();
+}
+
 StringBase* LinearString::clone() const {
 	return new LinearString(*this);
 }
@@ -77,18 +81,6 @@ void LinearString::appendSymbol(alphabet::Symbol&& symbol) {
 	m_Data.push_back(std::move(symbol));
 }
 
-bool LinearString::operator<(const ObjectBase& other) const {
-	return other > *this;
-}
-
-bool LinearString::operator ==(const ObjectBase& other) const {
-	return other == *this;
-}
-
-bool LinearString::operator >(const ObjectBase& other) const {
-	return other < *this;
-}
-
 const std::vector<alphabet::Symbol>& LinearString::getContent() const {
 	return this->m_Data;
 }
@@ -108,32 +100,53 @@ bool LinearString::isEmpty() const {
 	return this->m_Data.size() == 0;
 }
 
-bool LinearString::operator<(const LinearString& other) const {
-	return std::tie(m_Data, alphabet) < std::tie(other.m_Data, other.alphabet);
+int LinearString::compare(const ObjectBase& other) const {
+	return -other.compare(*this);
 }
 
-bool LinearString::operator<(const CyclicString& other) const {
-	if(this->isEmpty() && other.isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
-}
+int LinearString::compare(const LinearString& other) const {
+	auto first = std::tie(m_Data, alphabet);
+	auto second = std::tie(other.m_Data, other.alphabet);
 
-bool LinearString::operator<(const Epsilon& other) const {
-	if(this->isEmpty()) return alphabet < other.getAlphabet();
-	return typeid(*this).before(typeid(other));
-}
-
-bool LinearString::operator==(const LinearString& other) const {
-	return m_Data == other.m_Data && alphabet == other.getAlphabet();
-}
-
-bool LinearString::operator==(const CyclicString& other) const {
-	if(this->isEmpty() && other.isEmpty()) return alphabet == other.getAlphabet();
-	return false;
+	if(first == second) {
+		return 0;
+	} else if(first < second) {
+		return -1;
+	} else {
+		return 1;
+	}
 }
 
-bool LinearString::operator==(const Epsilon& other) const {
-	if(this->isEmpty()) return alphabet == other.getAlphabet();
-	return false;
+int LinearString::compare(const CyclicString& other) const {
+	if(this->isEmpty() && other.isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
+	
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
+}
+
+int LinearString::compare(const Epsilon& other) const {
+	if(this->isEmpty()) {
+		if(alphabet == other.getAlphabet())
+			return 0;
+		else if(alphabet < other.getAlphabet())
+			return -1;
+		else
+			return 1;
+	}
+	
+	if(typeid(*this).before(typeid(other)))
+		return -1;
+	else
+		return 1;
 }
 
 void LinearString::operator >>(std::ostream& out) const {
diff --git a/alib2data/src/string/LinearString.h b/alib2data/src/string/LinearString.h
index 914386b1e3..a74a468fb1 100644
--- a/alib2data/src/string/LinearString.h
+++ b/alib2data/src/string/LinearString.h
@@ -16,6 +16,7 @@
 #include "../alphabet/Symbol.h"
 #include "StringBase.h"
 #include "common/StringAlphabet.h"
+#include "Epsilon.h"
 
 namespace string {
 
@@ -33,6 +34,7 @@ public:
 	explicit LinearString(const std::vector<alphabet::Symbol>& data);
 	explicit LinearString(std::vector<alphabet::Symbol>&& data);
 	explicit LinearString(const std::string& str);
+	explicit LinearString(const Epsilon& epsilon);
 
 	virtual StringBase* clone() const;
 	virtual StringBase* plunder() &&;
@@ -46,10 +48,6 @@ public:
 	
 	void appendSymbol(alphabet::Symbol&& symbol);
 
-	virtual bool operator <(const alib::ObjectBase& other) const;
-	virtual bool operator ==(const alib::ObjectBase& other) const;
-	virtual bool operator >(const alib::ObjectBase& other) const;
-
 	/**
 	 * @return List of symbols forming string (const version).
 	 */
@@ -62,13 +60,11 @@ public:
 	 */
 	bool isEmpty() const;
 
-	virtual bool operator<(const LinearString& other) const;
-	virtual bool operator<(const CyclicString& other) const;
-	virtual bool operator<(const Epsilon& other) const;
+	virtual int compare(const alib::ObjectBase& other) const;
 
-	virtual bool operator==(const LinearString& other) const;
-	virtual bool operator==(const CyclicString& other) const;
-	virtual bool operator==(const Epsilon& other) const;
+	virtual int compare(const LinearString& other) const;
+	virtual int compare(const CyclicString& other) const;
+	virtual int compare(const Epsilon& other) const;
 
 	virtual void operator >>(std::ostream& out) const;
 
diff --git a/alib2data/test-src/std/StdVisitorTest.cpp b/alib2data/test-src/std/StdVisitorTest.cpp
index dbd7e2cedb..2d275a47fb 100644
--- a/alib2data/test-src/std/StdVisitorTest.cpp
+++ b/alib2data/test-src/std/StdVisitorTest.cpp
@@ -44,24 +44,12 @@ public:
 		return new Tmp1(*this);
 	}
 
-	virtual bool operator<(const TmpBase& other) const {
-		return other > *this;
+	virtual int compare(const TmpBase& other) const {
+		return -other.compare(*this);
 	}
 
-	virtual bool operator==(const TmpBase& other) const {
-		return other == *this;
-	}
-
-	virtual bool operator>(const TmpBase& other) const {
-		return other < *this;
-	}
-
-	virtual bool operator==(const Tmp1& other) const {
-		return this->data == other.data;
-	}
-
-	virtual bool operator<(const Tmp1& other) const {
-		return this->data < other.data;
+	virtual int compare(const Tmp1& other) const {
+		return this->data - other.data;
 	}
 
 	virtual void operator>>(std::ostream& os) const {
@@ -101,24 +89,12 @@ public:
 		return new Tmp2(*this);
 	}
 
-	virtual bool operator<(const TmpBase& other) const {
-		return other > *this;
-	}
-
-	virtual bool operator==(const TmpBase& other) const {
-		return other == *this;
-	}
-
-	virtual bool operator>(const TmpBase& other) const {
-		return other < *this;
-	}
-
-	virtual bool operator==(const Tmp2& other) const {
-		return this->data == other.data;
+	virtual int compare(const TmpBase& other) const {
+		return -other.compare(*this);
 	}
 
-	virtual bool operator<(const Tmp2& other) const {
-		return this->data < other.data;
+	virtual int compare(const Tmp2& other) const {
+		return this->data - other.data;
 	}
 
 	virtual void operator>>(std::ostream& os) const {
@@ -162,24 +138,12 @@ public:
 		return new Tmp3(*this);
 	}
 
-	virtual bool operator<(const TmpBase& other) const {
-		return other > *this;
-	}
-
-	virtual bool operator==(const TmpBase& other) const {
-		return other == *this;
-	}
-
-	virtual bool operator>(const TmpBase& other) const {
-		return other < *this;
-	}
-
-	virtual bool operator==(const Tmp3& other) const {
-		return this->data == other.data;
+	virtual int compare(const TmpBase& other) const {
+		return -other.compare(*this);
 	}
 
-	virtual bool operator<(const Tmp3& other) const {
-		return this->data < other.data;
+	virtual int compare(const Tmp3& other) const {
+		return this->data.compare(other.data);
 	}
 
 	virtual void operator>>(std::ostream& os) const {
-- 
GitLab