diff --git a/alib2common/src/abstraction/AnyaryOperationAbstraction.hpp b/alib2common/src/abstraction/AnyaryOperationAbstraction.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..180363e540df8871031b4c2f002a6afe552f9d85
--- /dev/null
+++ b/alib2common/src/abstraction/AnyaryOperationAbstraction.hpp
@@ -0,0 +1,93 @@
+/*
+ * AnyaryOperationAbstraction.hpp
+ *
+ *  Created on: 20. 8. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef _ANYARY_OPERATION_ABSTRACTION_HPP_
+#define _ANYARY_OPERATION_ABSTRACTION_HPP_
+
+#include <abstraction/ValueOperationAbstraction.hpp>
+#include <tuple>
+#include <memory>
+#include <abstraction/Registry.h>
+
+namespace abstraction {
+
+template < class ReturnType, class ParamType >
+class AnyaryOperationAbstraction : public ValueOperationAbstraction < ReturnType > {
+protected:
+	ext::vector < std::pair < std::shared_ptr < ValueProvider < ParamType > >, bool > > m_params;
+
+private:
+	virtual bool attachInput ( const std::shared_ptr < OperationAbstraction > & input, unsigned index, bool move ) override {
+		std::shared_ptr < ValueProvider < ParamType > > validData = std::dynamic_pointer_cast < ValueProvider < ParamType > > ( input );
+		if ( validData ) {
+			if ( m_params.size ( ) < index + 1 )
+				m_params.resize ( index + 1 );
+
+			m_params [ index ] = std::make_pair ( validData, move );
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	virtual bool detachInput ( unsigned index ) override {
+		if ( index >= m_params.size ( ) )
+			throw exception::CommonException ( "Parameter index out of bounds.");
+
+		m_params [ index ].first = nullptr;
+		m_params [ index ].second = false;
+
+		return true;
+	}
+
+public:
+	AnyaryOperationAbstraction ( ) {
+	}
+
+	virtual bool inputsReady ( ) const override {
+		for ( const auto & param : m_params )
+			if ( ! ( bool ) param.first || ! param.first->isReady ( ) )
+				return false;
+
+		return true;
+	}
+
+	virtual bool inputsAttached ( ) const override {
+		for ( const auto & param : m_params )
+			if ( ! ( bool ) param.first )
+				return false;
+
+		return true;
+	}
+
+	virtual bool eval ( ) override {
+		if ( ! inputsAttached ( ) )
+			return false;
+
+		if ( this->cached ( ) )
+			return true;
+
+		for ( const std::pair < std::shared_ptr < ValueProvider < ParamType > >, bool > & param : m_params )
+			if ( ! param.first->eval ( ) )
+				return false;
+
+		return this->run ( );
+	}
+
+	virtual unsigned numberOfParams ( ) const override {
+		return m_params.size ( );
+	}
+
+	virtual ext::type_index getParamTypeIndex ( unsigned ) const override {
+		return ext::type_index ( typeid ( ParamType ) );
+	}
+
+};
+
+} /* namespace abstraction */
+
+#endif /* _ANYARY_OPERATION_ABSTRACTION_HPP_ */
diff --git a/alib2common/src/abstraction/ContainerRegistry.cpp b/alib2common/src/abstraction/ContainerRegistry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5703a9e579bcec66edc4ac0ea6ef2a806a53a55d
--- /dev/null
+++ b/alib2common/src/abstraction/ContainerRegistry.cpp
@@ -0,0 +1,56 @@
+/*
+ * ContainerRegistry.cpp
+ *
+ *  Created on: 19. 8. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#include <abstraction/ContainerRegistry.hpp>
+#include <foreach>
+
+namespace abstraction {
+
+bool ContainerRegistry::hasAbstraction ( const std::string & container ) {
+	return getEntries ( ).count ( container );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > ContainerRegistry::getAbstraction ( const std::string & container, const std::string & paramType ) {
+	std::set < std::string > paramTypes;
+	if ( alib::namingApi::hasTypes ( paramType ) )
+		paramTypes = ext::transform < std::string > ( alib::namingApi::getTypes ( paramType ), [ ] ( const ext::type_index & type ) { return ext::to_string ( type ); } );
+	else
+		paramTypes.insert ( paramType );
+
+	auto group = getEntries ( ).find ( container );
+	if ( group == getEntries ( ).end ( ) )
+		throw exception::CommonException ( "Entry " + container + " not available" );
+
+	for ( const ext::pair < std::string, std::shared_ptr < Entry > > & entry : group->second )
+		if ( paramTypes.count ( entry.first ) )
+			return entry.second->getAbstraction ( );
+
+	throw exception::CommonException ( "Entry for " + container + " parametrized with " + paramType + " not available." );
+}
+
+ext::set < std::string > ContainerRegistry::listOverloads ( const std::string & container ) {
+	auto group = getEntries ( ).find ( container );
+	if ( group == getEntries ( ).end ( ) )
+		throw exception::CommonException ( "Entry " + container + " not available" );
+
+	ext::set < std::string > res;
+	for ( const ext::pair < std::string, std::shared_ptr < Entry > > & entry : group->second )
+		res.insert ( entry.first );
+
+	return res;
+}
+
+ext::set < std::string > ContainerRegistry::list ( ) {
+	ext::set < std::string > res;
+
+	for ( const std::pair < const std::string, ext::vector < ext::pair < std::string, std::shared_ptr < Entry > > > > & groups : getEntries ( ) )
+		res.insert ( groups.first );
+
+	return res;
+}
+
+} /* namespace abstraction */
diff --git a/alib2common/src/abstraction/ContainerRegistry.hpp b/alib2common/src/abstraction/ContainerRegistry.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6b3b75093c07676ab9933a81260e7678cfd580bc
--- /dev/null
+++ b/alib2common/src/abstraction/ContainerRegistry.hpp
@@ -0,0 +1,78 @@
+/*
+ * ContainerRegistry.hpp
+ *
+ *  Created on: 11. 7. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef _CONTAINER_REGISTRY_HPP_
+#define _CONTAINER_REGISTRY_HPP_
+
+#include <functional>
+#include <memory>
+#include <vector>
+#include <string>
+#include <set>
+
+#include <exception/CommonException.h>
+#include <abstraction/OperationAbstraction.hpp>
+
+#include <core/namingApi.hpp>
+
+namespace abstraction {
+
+class ContainerRegistry {
+	class Entry {
+	public:
+		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const = 0;
+	};
+
+	template < class Params >
+	class SetEntryImpl : public Entry {
+	public:
+		virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
+	};
+
+	static ext::map < std::string, ext::vector < ext::pair < std::string, std::shared_ptr < Entry > > > > & getEntries ( ) {
+		static ext::map < std::string, ext::vector < ext::pair < std::string, std::shared_ptr < Entry > > > > containerGroups;
+		return containerGroups;
+	};
+public:
+	template < class ParamTypes >
+	static void registerSet ( ) {
+		std::string container = "Set";
+
+		std::string paramName = ext::to_string < typename std::decay < ParamTypes >::type > ( );
+
+		auto & group = getEntries ( ) [ container ];
+		for ( const ext::pair < std::string, std::shared_ptr < Entry > > & entry : group )
+			if ( entry.first == paramName )
+				throw exception::CommonException ( "Callback for " + container + " already registered." );
+
+		std::shared_ptr < Entry > entryValue = std::make_shared < SetEntryImpl < ParamTypes > > ( );
+		group.push_back ( ext::make_pair ( paramName, entryValue ) );
+	}
+	
+	static bool hasAbstraction ( const std::string & container );
+
+	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & container, const std::string & paramType );
+
+	static ext::set < std::string > listOverloads ( const std::string & algorithm );
+
+	static ext::set < std::string > list ( );
+};
+
+} /* namespace abstraction */
+
+#include <abstraction/SetAbstraction.hpp>
+
+namespace abstraction {
+
+template < class Param >
+std::shared_ptr < abstraction::OperationAbstraction > ContainerRegistry::SetEntryImpl < Param >::getAbstraction ( ) const {
+	return std::make_shared < abstraction::SetAbstraction < Param > > ( );
+}
+
+} /* namespace abstraction */
+
+#endif /* _CONTAINER_REGISTRY_HPP_ */
diff --git a/alib2common/src/abstraction/PrimitiveRegistrator.cpp b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
index ad4be3902dd059aec097ff277d57478e18d32e30..de686e144c3d342282ce7f3b3a8beef7b389bd70 100644
--- a/alib2common/src/abstraction/PrimitiveRegistrator.cpp
+++ b/alib2common/src/abstraction/PrimitiveRegistrator.cpp
@@ -17,6 +17,8 @@
 #include <primitive/UnsignedLong.h>
 #include <primitive/String.h>
 
+#include "SetAbstraction.hpp"
+
 namespace abstraction {
 
 class PrimitiveCasts {
diff --git a/alib2common/src/abstraction/Registry.cpp b/alib2common/src/abstraction/Registry.cpp
index dde8c227eac9bf629ee8a249a2a7a6da141ac6c6..0b874f96c8c04e9b2b128201c98aa95ac9a00814 100644
--- a/alib2common/src/abstraction/Registry.cpp
+++ b/alib2common/src/abstraction/Registry.cpp
@@ -16,6 +16,7 @@
 #include <abstraction/CastRegistry.hpp>
 #include <abstraction/NormalizeRegistry.hpp>
 #include <abstraction/DowncastRegistry.hpp>
+#include <abstraction/ContainerRegistry.hpp>
 
 #include <core/namingApi.hpp>
 
@@ -57,6 +58,10 @@ ext::set < ext::pair < ext::pair < std::string, ext::set < abstraction::ParamQua
 	return AlgorithmRegistry::listOverloads ( algorithm );
 }
 
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getContainerAbstraction ( const std::string & container, const std::string & type ) {
+	return ContainerRegistry::getAbstraction ( container, type );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes ) {
 	return AlgorithmRegistry::getAbstraction ( name, paramTypes );
 }
diff --git a/alib2common/src/abstraction/Registry.h b/alib2common/src/abstraction/Registry.h
index 027c0fd5e6f6aa287f91aef2f8e262a6526964f9..8af926b16a7aa65fd726c78a12bc7eef91a3d85a 100644
--- a/alib2common/src/abstraction/Registry.h
+++ b/alib2common/src/abstraction/Registry.h
@@ -10,6 +10,7 @@
 
 #include <abstraction/OperationAbstraction.hpp>
 #include <abstraction/common/ParamQualifiers.hpp>
+#include <abstraction/common/AlgorithmCategories.hpp>
 
 namespace abstraction {
 
@@ -29,6 +30,7 @@ public:
 
 	static ext::set < ext::pair < std::string, ext::set < std::string > > > listNames ( );
 
+	static std::shared_ptr < abstraction::OperationAbstraction > getContainerAbstraction ( const std::string & container, const std::string & type );
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes );
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, bool & unwrap, bool & normalize );
 	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( const std::string & target, const std::string & param, bool & normalize );
diff --git a/alib2common/src/abstraction/SetAbstraction.hpp b/alib2common/src/abstraction/SetAbstraction.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cf1395b7880d7d75ecdd73a77f8074c0ce9d1801
--- /dev/null
+++ b/alib2common/src/abstraction/SetAbstraction.hpp
@@ -0,0 +1,47 @@
+/*
+ * SetAbstraction.hpp
+ *
+ *  Created on: 11. 7. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef _SET_ABSTRACTION_HPP_
+#define _SET_ABSTRACTION_HPP_
+
+#include <abstraction/AnyaryOperationAbstraction.hpp>
+#include <tuple>
+#include <memory>
+#include <abstraction/Registry.h>
+#include <foreach>
+
+namespace abstraction {
+
+template < class ParamType >
+class SetAbstraction : public AnyaryOperationAbstraction < ext::set < ParamType >, ParamType > {
+
+public:
+	SetAbstraction ( ) {
+	}
+
+	virtual bool run ( ) override {
+		if ( ! this->inputsReady ( ) )
+			return false;
+
+		if ( this->cached ( ) )
+			return true;
+
+		ext::set < ParamType > theSet;
+		for ( const std::pair < std::shared_ptr < ValueProvider < ParamType > >, bool > & param : this->m_params ) {
+			theSet.insert ( param.first->getValue ( param.second ) );
+		}
+
+		this->m_data = theSet;
+
+		return true;
+	}
+
+};
+
+} /* namespace abstraction */
+
+#endif /* _SET_ABSTRACTION_HPP_ */