/*
 *  SubCircuit -- An implementation of the Ullmann Subgraph Isomorphism
 *                algorithm for coarse grain logic networks
 *
 *  Copyright (C) 2013  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "subcircuit.h"

#include <algorithm>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>

#ifdef _YOSYS_
#  include "kernel/yosys.h"
#  define my_printf YOSYS_NAMESPACE_PREFIX log
#else
#  define my_printf printf
#endif

using namespace SubCircuit;

#ifndef _YOSYS_
static std::string my_stringf(const char *fmt, ...)
{
	std::string string;
	char *str = NULL;
	va_list ap;

	va_start(ap, fmt);
	if (vasprintf(&str, fmt, ap) < 0)
		str = NULL;
	va_end(ap);

	if (str != NULL) {
		string = str;
		free(str);
	}

	return string;
}
#else
#  define my_stringf YOSYS_NAMESPACE_PREFIX stringf
#endif

SubCircuit::Graph::Graph(const Graph &other, const std::vector<std::string> &otherNodes)
{
	allExtern = other.allExtern;

	std::map<int, int> other2this;
	for (int i = 0; i < int(otherNodes.size()); i++) {
		assert(other.nodeMap.count(otherNodes[i]) > 0);
		other2this[other.nodeMap.at(otherNodes[i])] = i;
		nodeMap[otherNodes[i]] = i;
	}

	std::map<int, int> edges2this;
	for (auto &i1 : other2this)
	for (auto &i2 : other.nodes[i1.first].ports)
	for (auto &i3 : i2.bits)
		if (edges2this.count(i3.edgeIdx) == 0) {
			int next_idx = edges2this.size();
			edges2this[i3.edgeIdx] = next_idx;
		}

	edges.resize(edges2this.size());
	for (auto &it : edges2this) {
		for (auto &bit : other.edges[it.first].portBits)
			if (other2this.count(bit.nodeIdx) > 0)
				edges[it.second].portBits.insert(BitRef(other2this[bit.nodeIdx], bit.portIdx, bit.bitIdx));
		edges[it.second].constValue = other.edges[it.first].constValue;
		edges[it.second].isExtern = other.edges[it.first].isExtern;
	}

	nodes.resize(other2this.size());
	for (auto &it : other2this) {
		nodes[it.second] = other.nodes[it.first];
		for (auto &i2 : nodes[it.second].ports)
		for (auto &i3 : i2.bits)
			i3.edgeIdx = edges2this.at(i3.edgeIdx);
	}
}

bool SubCircuit::Graph::BitRef::operator < (const BitRef &other) const
{
	if (nodeIdx != other.nodeIdx)
		return nodeIdx < other.nodeIdx;
	if (portIdx != other.portIdx)
		return portIdx < other.portIdx;
	return bitIdx < other.bitIdx;
}

void  SubCircuit::Graph::createNode(std::string nodeId, std::string typeId, void *userData, bool shared)
{
	assert(nodeMap.count(nodeId) == 0);
	nodeMap[nodeId] = nodes.size();
	nodes.push_back(Node());

	Node &newNode = nodes.back();
	newNode.nodeId = nodeId;
	newNode.typeId = typeId;
	newNode.userData = userData;
	newNode.shared = shared;
}

void SubCircuit::Graph::createPort(std::string nodeId, std::string portId, int width, int minWidth)
{
	assert(nodeMap.count(nodeId) != 0);
	int nodeIdx = nodeMap[nodeId];
	Node &node = nodes[nodeIdx];

	assert(node.portMap.count(portId) == 0);

	int portIdx = node.ports.size();
	node.portMap[portId] = portIdx;
	node.ports.push_back(Port());
	Port &port = node.ports.back();

	port.portId = portId;
	port.minWidth = minWidth < 0 ? width : minWidth;
	port.bits.insert(port.bits.end(), width, PortBit());

	for (int i = 0; i < width; i++) {
		port.bits[i].edgeIdx = edges.size();
		edges.push_back(Edge());
		edges.back().portBits.insert(BitRef(nodeIdx, portIdx, i));
	}
}

void SubCircuit::Graph::createConnection(std::string fromNodeId, std::string fromPortId, int fromBit, std::string toNodeId, std::string toPortId, int toBit, int width)
{
	assert(nodeMap.count(fromNodeId) != 0);
	assert(nodeMap.count(toNodeId) != 0);

	int fromNodeIdx = nodeMap[fromNodeId];
	Node &fromNode = nodes[fromNodeIdx];

	int toNodeIdx = nodeMap[toNodeId];
	Node &toNode = nodes[toNodeIdx];

	assert(fromNode.portMap.count(fromPortId) != 0);
	assert(toNode.portMap.count(toPortId) != 0);

	int fromPortIdx = fromNode.portMap[fromPortId];
	Port &fromPort = fromNode.ports[fromPortIdx];

	int toPortIdx = toNode.portMap[toPortId];
	Port &toPort = toNode.ports[toPortIdx];

	if (width < 0) {
		assert(fromBit == 0 && toBit == 0);
		assert(fromPort.bits.size() == toPort.bits.size());
		width = fromPort.bits.size();
	}

	assert(fromBit >= 0 && toBit >= 0);
	for (int i = 0; i < width; i++)
	{
		assert(fromBit + i < int(fromPort.bits.size()));
		assert(toBit + i < int(toPort.bits.size()));

		int fromEdgeIdx = fromPort.bits[fromBit + i].edgeIdx;
		int toEdgeIdx = toPort.bits[toBit + i].edgeIdx;

		if (fromEdgeIdx == toEdgeIdx)
			continue;

		// merge toEdge into fromEdge
		if (edges[toEdgeIdx].isExtern)
			edges[fromEdgeIdx].isExtern = true;
		if (edges[toEdgeIdx].constValue) {
			assert(edges[fromEdgeIdx].constValue == 0);
			edges[fromEdgeIdx].constValue = edges[toEdgeIdx].constValue;
		}
		for (const auto &ref : edges[toEdgeIdx].portBits) {
			edges[fromEdgeIdx].portBits.insert(ref);
			nodes[ref.nodeIdx].ports[ref.portIdx].bits[ref.bitIdx].edgeIdx = fromEdgeIdx;
		}

		// remove toEdge (move last edge over toEdge if needed)
		if (toEdgeIdx+1 != int(edges.size())) {
			edges[toEdgeIdx] = edges.back();
			for (const auto &ref : edges[toEdgeIdx].portBits)
				nodes[ref.nodeIdx].ports[ref.portIdx].bits[ref.bitIdx].edgeIdx = toEdgeIdx;
		}
		edges.pop_back();
	}
}

void SubCircuit::Graph::createConnection(std::string fromNodeId, std::string fromPortId, std::string toNodeId, std::string toPortId)
{
	createConnection(fromNodeId, fromPortId, 0, toNodeId, toPortId, 0, -1);
}

void SubCircuit::Graph::createConstant(std::string toNodeId, std::string toPortId, int toBit, int constValue)
{
	assert(nodeMap.count(toNodeId) != 0);
	int toNodeIdx = nodeMap[toNodeId];
	Node &toNode = nodes[toNodeIdx];

	assert(toNode.portMap.count(toPortId) != 0);
	int toPortIdx = toNode.portMap[toPortId];
	Port &toPort = toNode.ports[toPortIdx];

	assert(toBit >= 0 && toBit < int(toPort.bits.size()));
	int toEdgeIdx = toPort.bits[toBit].edgeIdx;

	assert(edges[toEdgeIdx].constValue == 0);
	edges[toEdgeIdx].constValue = constValue;
}

void SubCircuit::Graph::createConstant(std::string toNodeId, std::string toPortId, int constValue)
{
	assert(nodeMap.count(toNodeId) != 0);
	int toNodeIdx = nodeMap[toNodeId];
	Node &toNode = nodes[toNodeIdx];

	assert(toNode.portMap.count(toPortId) != 0);
	int toPortIdx = toNode.portMap[toPortId];
	Port &toPort = toNode.ports[toPortIdx];

	for (int i = 0; i < int(toPort.bits.size()); i++) {
		int toEdgeIdx = toPort.bits[i].edgeIdx;
		assert(edges[toEdgeIdx].constValue == 0);
		edges[toEdgeIdx].constValue = constValue % 2 ? '1' : '0';
		constValue = constValue >> 1;
	}
}

void SubCircuit::Graph::markExtern(std::string nodeId, std::string portId, int bit)
{
	assert(nodeMap.count(nodeId) != 0);
	Node &node = nodes[nodeMap[nodeId]];

	assert(node.portMap.count(portId) != 0);
	Port &port = node.ports[node.portMap[portId]];

	if (bit < 0) {
		for (const auto portBit : port.bits)
			edges[portBit.edgeIdx].isExtern = true;
	} else {
		assert(bit < int(port.bits.size()));
		edges[port.bits[bit].edgeIdx].isExtern = true;
	}
}

void SubCircuit::Graph::markAllExtern()
{
	allExtern = true;
}

void SubCircuit::Graph::print()
{
	for (int i = 0; i < int(nodes.size()); i++) {
		const Node &node = nodes[i];
		my_printf("NODE %d: %s (%s)\n", i, node.nodeId.c_str(), node.typeId.c_str());
		for (int j = 0; j < int(node.ports.size()); j++) {
			const Port &port = node.ports[j];
			my_printf("  PORT %d: %s (%d/%d)\n", j, port.portId.c_str(), port.minWidth, int(port.bits.size()));
			for (int k = 0; k < int(port.bits.size()); k++) {
				int edgeIdx = port.bits[k].edgeIdx;
				my_printf("    BIT %d (%d):", k, edgeIdx);
				for (const auto &ref : edges[edgeIdx].portBits)
					my_printf(" %d.%d.%d", ref.nodeIdx, ref.portIdx, ref.bitIdx);
				if (edges[edgeIdx].isExtern)
					my_printf(" [extern]");
				my_printf("\n");
			}
		}
	}
}

class SubCircuit::SolverWorker
{
	// basic internal data structures

	typedef std::vector<std::map<int, int>> adjMatrix_t;

	struct GraphData {
		std::string graphId;
		Graph graph;
		adjMatrix_t adjMatrix;
		std::vector<bool> usedNodes;
	};

	static void printAdjMatrix(const adjMatrix_t &matrix)
	{
		my_printf("%7s", "");
		for (int i = 0; i < int(matrix.size()); i++)
			my_printf("%4d:", i);
		my_printf("\n");
		for (int i = 0; i < int(matrix.size()); i++) {
			my_printf("%5d:", i);
			for (int j = 0; j < int(matrix.size()); j++)
				if (matrix.at(i).count(j) == 0)
					my_printf("%5s", "-");
				else
					my_printf("%5d", matrix.at(i).at(j));
			my_printf("\n");
		}
	}

	// helper functions for handling permutations

	static const int maxPermutationsLimit = 1000000;

	static int numberOfPermutations(const std::vector<std::string> &list)
	{
		constexpr size_t mappedPermutationsSize = 10;
		constexpr int mappedPermutations[mappedPermutationsSize] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
		assert(list.size() < mappedPermutationsSize);
		return mappedPermutations[list.size()];
	}

	static void permutateVectorToMap(std::map<std::string, std::string> &map, const std::vector<std::string> &list, int idx)
	{
		// convert idx to a list.size() digits factoradic number

		std::vector<int> factoradicDigits;
		for (int i = 0; i < int(list.size()); i++) {
			factoradicDigits.push_back(idx % (i+1));
			idx = idx / (i+1);
		}

		// construct permutation

		std::vector<std::string> pool = list;
		std::vector<std::string> permutation;

		while (!factoradicDigits.empty()) {
			int i = factoradicDigits.back();
			factoradicDigits.pop_back();
			permutation.push_back(pool[i]);
			pool.erase(pool.begin() + i);
		}

		// update map

		for (int i = 0; i < int(list.size()); i++)
			map[list[i]] = permutation[i];
	}

	static int numberOfPermutationsArray(const std::vector<std::vector<std::string>> &list)
	{
		int numPermutations = 1;
		for (const auto &it : list) {
			int thisPermutations = numberOfPermutations(it);
			assert(float(numPermutations) * float(thisPermutations) < maxPermutationsLimit);
			numPermutations *= thisPermutations;
		}
		return numPermutations;
	}

	static void permutateVectorToMapArray(std::map<std::string, std::string> &map, const std::vector<std::vector<std::string>> &list, int idx)
	{
		for (const auto &it : list) {
			int thisPermutations = numberOfPermutations(it);
			int thisIdx = idx % thisPermutations;
			permutateVectorToMap(map, it, thisIdx);
			idx /= thisPermutations;
		}
	}

	static void applyPermutation(std::map<std::string, std::string> &map, const std::map<std::string, std::string> &permutation)
	{
		std::vector<std::pair<std::string, std::string>> changeLog;
		for (const auto &it : permutation)
			if (map.count(it.second))
				changeLog.push_back(std::pair<std::string, std::string>(it.first, map.at(it.second)));
			else
				changeLog.push_back(std::pair<std::string, std::string>(it.first, it.second));
		for (const auto &it : changeLog)
			map[it.first] = it.second;
	}

	// classes for internal digraph representation

	struct DiBit
	{
		std::string fromPort, toPort;
		int fromBit, toBit;

		DiBit() : fromPort(), toPort(), fromBit(-1), toBit(-1) { }
		DiBit(std::string fromPort, int fromBit, std::string toPort, int toBit) : fromPort(fromPort), toPort(toPort), fromBit(fromBit), toBit(toBit) { }

		bool operator < (const DiBit &other) const
		{
			if (fromPort != other.fromPort)
				return fromPort < other.fromPort;
			if (toPort != other.toPort)
				return toPort < other.toPort;
			if (fromBit != other.fromBit)
				return fromBit < other.fromBit;
			return toBit < other.toBit;
		}

		std::string toString() const
		{
			return my_stringf("%s[%d]:%s[%d]", fromPort.c_str(), fromBit, toPort.c_str(), toBit);
		}
	};

	struct DiNode
	{
		std::string typeId;
		std::map<std::string, int> portSizes;

		DiNode()
		{
		}

		DiNode(const Graph &graph, int nodeIdx)
		{
			const Graph::Node &node = graph.nodes.at(nodeIdx);
			typeId = node.typeId;
			for (const auto &port : node.ports)
				portSizes[port.portId] = port.bits.size();
		}

		bool operator < (const DiNode &other) const
		{
			if (typeId != other.typeId)
				return typeId < other.typeId;
			return portSizes < other.portSizes;
		}

		std::string toString() const
		{
			std::string str;
			bool firstPort = true;
			for (const auto &it : portSizes) {
				str += my_stringf("%s%s[%d]", firstPort ? "" : ",", it.first.c_str(), it.second);
				firstPort = false;
			}
			return typeId + "(" + str + ")";
		}
	};

	struct DiEdge
	{
		DiNode fromNode, toNode;
		std::set<DiBit> bits;
		std::string userAnnotation;

		bool operator < (const DiEdge &other) const
		{
			if (fromNode < other.fromNode || other.fromNode < fromNode)
				return fromNode < other.fromNode;
			if (toNode < other.toNode || other.toNode < toNode)
				return toNode < other.toNode;
			if (bits < other.bits || other.bits < bits)
				return bits < other.bits;
			return userAnnotation < other.userAnnotation;
		}

		bool compare(const DiEdge &other, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::string> &mapToPorts) const
		{
			// Rules for matching edges:
			//
			// For all bits in the needle edge:
			//   - ignore if needle ports don't exist in haystack edge
			//   - otherwise: matching bit in haystack edge must exist
			//
			// There is no need to check in the other direction, as checking
			// of the isExtern properties is already performed in node matching.
			//
			// Note: "this" is needle, "other" is haystack

			for (auto bit : bits)
			{
				if (mapFromPorts.count(bit.fromPort) > 0)
					bit.fromPort = mapFromPorts.at(bit.fromPort);
				if (mapToPorts.count(bit.toPort) > 0)
					bit.toPort = mapToPorts.at(bit.toPort);

				if (other.fromNode.portSizes.count(bit.fromPort) == 0)
					continue;
				if (other.toNode.portSizes.count(bit.toPort) == 0)
					continue;

				if (bit.fromBit >= other.fromNode.portSizes.at(bit.fromPort))
					continue;
				if (bit.toBit >= other.toNode.portSizes.at(bit.toPort))
					continue;

				if (other.bits.count(bit) == 0)
					return false;
			}

			return true;
		}

		bool compareWithFromAndToPermutations(const DiEdge &other, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::string> &mapToPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations) const
		{
			if (swapPermutations.count(fromNode.typeId) > 0)
				for (const auto &permutation : swapPermutations.at(fromNode.typeId)) {
					std::map<std::string, std::string> thisMapFromPorts = mapFromPorts;
					applyPermutation(thisMapFromPorts, permutation);
					if (compareWithToPermutations(other, thisMapFromPorts, mapToPorts, swapPermutations))
						return true;
				}
			return compareWithToPermutations(other, mapFromPorts, mapToPorts, swapPermutations);
		}

		bool compareWithToPermutations(const DiEdge &other, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::string> &mapToPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations) const
		{
			if (swapPermutations.count(toNode.typeId) > 0)
				for (const auto &permutation : swapPermutations.at(toNode.typeId)) {
					std::map<std::string, std::string> thisMapToPorts = mapToPorts;
					applyPermutation(thisMapToPorts, permutation);
					if (compare(other, mapFromPorts, thisMapToPorts))
						return true;
				}
			return compare(other, mapFromPorts, mapToPorts);
		}

		bool compare(const DiEdge &other, const std::map<std::string, std::set<std::set<std::string>>> &swapPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations) const
		{
			// brute force method for port swapping: try all variations

			std::vector<std::vector<std::string>> swapFromPorts;
			std::vector<std::vector<std::string>> swapToPorts;

			// only use groups that are relevant for this edge

			if (swapPorts.count(fromNode.typeId) > 0)
				for (const auto &ports : swapPorts.at(fromNode.typeId)) {
					for (const auto &bit : bits)
						if (ports.count(bit.fromPort))
							goto foundFromPortMatch;
					if (0) {
				foundFromPortMatch:
						std::vector<std::string> portsVector;
						for (const auto &port : ports)
							portsVector.push_back(port);
						swapFromPorts.push_back(portsVector);
					}
				}

			if (swapPorts.count(toNode.typeId) > 0)
				for (const auto &ports : swapPorts.at(toNode.typeId)) {
					for (const auto &bit : bits)
						if (ports.count(bit.toPort))
							goto foundToPortMatch;
					if (0) {
				foundToPortMatch:
						std::vector<std::string> portsVector;
						for (const auto &port : ports)
							portsVector.push_back(port);
						swapToPorts.push_back(portsVector);
					}
				}

			// try all permutations

			std::map<std::string, std::string> mapFromPorts, mapToPorts;
			int fromPortsPermutations = numberOfPermutationsArray(swapFromPorts);
			int toPortsPermutations = numberOfPermutationsArray(swapToPorts);

			for (int i = 0; i < fromPortsPermutations; i++)
			{
				permutateVectorToMapArray(mapFromPorts, swapFromPorts, i);

				for (int j = 0; j < toPortsPermutations; j++) {
					permutateVectorToMapArray(mapToPorts, swapToPorts, j);
					if (compareWithFromAndToPermutations(other, mapFromPorts, mapToPorts, swapPermutations))
						return true;
				}
			}

			return false;
		}

		bool compare(const DiEdge &other, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::set<std::set<std::string>>> &swapPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations) const
		{
			// strip-down version of the last function: only try permutations for mapToPorts, mapFromPorts is already provided by the caller

			std::vector<std::vector<std::string>> swapToPorts;

			if (swapPorts.count(toNode.typeId) > 0)
				for (const auto &ports : swapPorts.at(toNode.typeId)) {
					for (const auto &bit : bits)
						if (ports.count(bit.toPort))
							goto foundToPortMatch;
					if (0) {
				foundToPortMatch:
						std::vector<std::string> portsVector;
						for (const auto &port : ports)
							portsVector.push_back(port);
						swapToPorts.push_back(portsVector);
					}
				}

			std::map<std::string, std::string> mapToPorts;
			int toPortsPermutations = numberOfPermutationsArray(swapToPorts);

			for (int j = 0; j < toPortsPermutations; j++) {
				permutateVectorToMapArray(mapToPorts, swapToPorts, j);
				if (compareWithToPermutations(other, mapFromPorts, mapToPorts, swapPermutations))
					return true;
			}

			return false;
		}

		std::string toString() const
		{
			std::string buffer = fromNode.toString() + " " + toNode.toString();
			for (const auto &bit : bits)
				buffer += " " + bit.toString();
			if (!userAnnotation.empty())
				buffer += " " + userAnnotation;
			return buffer;
		}

		static void findEdgesInGraph(const Graph &graph, std::map<std::pair<int, int>, DiEdge> &edges)
		{
			edges.clear();
			for (const auto &edge : graph.edges) {
				if (edge.constValue != 0)
					continue;
				for (const auto &fromBit : edge.portBits)
				for (const auto &toBit : edge.portBits)
					if (&fromBit != &toBit) {
						DiEdge &de = edges[std::pair<int, int>(fromBit.nodeIdx, toBit.nodeIdx)];
						de.fromNode = DiNode(graph, fromBit.nodeIdx);
						de.toNode = DiNode(graph, toBit.nodeIdx);
						std::string fromPortId = graph.nodes[fromBit.nodeIdx].ports[fromBit.portIdx].portId;
						std::string toPortId = graph.nodes[toBit.nodeIdx].ports[toBit.portIdx].portId;
						de.bits.insert(DiBit(fromPortId, fromBit.bitIdx, toPortId, toBit.bitIdx));
					}
			}
		}
	};

	struct DiCache
	{
		std::map<DiEdge, int> edgeTypesMap;
		std::vector<DiEdge> edgeTypes;
		std::map<std::pair<int, int>, bool> compareCache;

		void add(const Graph &graph, adjMatrix_t &adjMatrix, const std::string &graphId, Solver *userSolver)
		{
			std::map<std::pair<int, int>, DiEdge> edges;
			DiEdge::findEdgesInGraph(graph, edges);

			adjMatrix.clear();
			adjMatrix.resize(graph.nodes.size());

			for (auto &it : edges) {
				const Graph::Node &fromNode = graph.nodes[it.first.first];
				const Graph::Node &toNode = graph.nodes[it.first.second];
				it.second.userAnnotation = userSolver->userAnnotateEdge(graphId, fromNode.nodeId, fromNode.userData, toNode.nodeId, toNode.userData);
			}

			for (const auto &it : edges) {
				if (edgeTypesMap.count(it.second) == 0) {
					edgeTypesMap[it.second] = edgeTypes.size();
					edgeTypes.push_back(it.second);
				}
				adjMatrix[it.first.first][it.first.second] = edgeTypesMap[it.second];
			}
		}

		bool compare(int needleEdge, int haystackEdge, const std::map<std::string, std::set<std::set<std::string>>> &swapPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations)
		{
			std::pair<int, int> key(needleEdge, haystackEdge);
			if (!compareCache.count(key))
				compareCache[key] = edgeTypes.at(needleEdge).compare(edgeTypes.at(haystackEdge), swapPorts, swapPermutations);
			return compareCache[key];
		}

		bool compare(int needleEdge, int haystackEdge, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::set<std::set<std::string>>> &swapPorts,
				const std::map<std::string, std::set<std::map<std::string, std::string>>> &swapPermutations) const
		{
			return edgeTypes.at(needleEdge).compare(edgeTypes.at(haystackEdge), mapFromPorts, swapPorts, swapPermutations);
		}

		bool compare(int needleEdge, int haystackEdge, const std::map<std::string, std::string> &mapFromPorts, const std::map<std::string, std::string> &mapToPorts) const
		{
			return edgeTypes.at(needleEdge).compare(edgeTypes.at(haystackEdge), mapFromPorts, mapToPorts);
		}

		void printEdgeTypes() const
		{
			for (int i = 0; i < int(edgeTypes.size()); i++)
				my_printf("%5d: %s\n", i, edgeTypes[i].toString().c_str());
		}
	};

	// solver state variables

	Solver *userSolver;
	std::map<std::string, GraphData> graphData;
	std::map<std::string, std::set<std::string>> compatibleTypes;
	std::map<int, std::set<int>> compatibleConstants;
	std::map<std::string, std::set<std::set<std::string>>> swapPorts;
	std::map<std::string, std::set<std::map<std::string, std::string>>> swapPermutations;
	DiCache diCache;
	bool verbose;

	// main solver functions

	bool matchNodePorts(const Graph &needle, int needleNodeIdx, const Graph &haystack, int haystackNodeIdx, const std::map<std::string, std::string> &swaps) const
	{
		const Graph::Node &nn = needle.nodes[needleNodeIdx];
		const Graph::Node &hn = haystack.nodes[haystackNodeIdx];
		assert(nn.ports.size() == hn.ports.size());

		for (int i = 0; i < int(nn.ports.size()); i++)
		{
			std::string hnPortId = nn.ports[i].portId;
			if (swaps.count(hnPortId) > 0)
				hnPortId = swaps.at(hnPortId);

			if (hn.portMap.count(hnPortId) == 0)
				return false;

			const Graph::Port &np = nn.ports[i];
			const Graph::Port &hp = hn.ports[hn.portMap.at(hnPortId)];

			if (int(hp.bits.size()) < np.minWidth || hp.bits.size() > np.bits.size())
				return false;

			for (int j = 0; j < int(hp.bits.size()); j++)
			{
				const Graph::Edge &ne = needle.edges[np.bits[j].edgeIdx];
				const Graph::Edge &he = haystack.edges[hp.bits[j].edgeIdx];

				if (ne.constValue || he.constValue) {
					if (ne.constValue != he.constValue)
						if (compatibleConstants.count(ne.constValue) == 0 || compatibleConstants.at(ne.constValue).count(he.constValue) == 0)
							return false;
					continue;
				}

				if (ne.isExtern || needle.allExtern) {
					if (he.portBits.size() < ne.portBits.size())
						return false;
				} else {
					if (he.portBits.size() != ne.portBits.size())
						return false;
					if (he.isExtern || haystack.allExtern)
						return false;
				}
			}
		}

		return true;
	}

	bool matchNodes(const GraphData &needle, int needleNodeIdx, const GraphData &haystack, int haystackNodeIdx) const
	{
		// Rules for matching nodes:
		//
		// 1. their typeId must be identical or compatible
		//    (this is checked before calling this function)
		//
		// 2. they must have the same ports and the haystack port
		//    widths must match the needle port width range
		//
		// 3. All edges from the needle must match the haystack:
		//    a) if the needle edge is extern:
		//         - the haystack edge must have at least as many components as the needle edge
		//    b) if the needle edge is not extern:
		//         - the haystack edge must have the same number of components as the needle edge
		//         - the haystack edge must not be extern

		const Graph::Node &nn = needle.graph.nodes[needleNodeIdx];
		const Graph::Node &hn = haystack.graph.nodes[haystackNodeIdx];

		assert(nn.typeId == hn.typeId || (compatibleTypes.count(nn.typeId) > 0 && compatibleTypes.at(nn.typeId).count(hn.typeId) > 0));

		if (nn.ports.size() != hn.ports.size())
			return false;

		std::map<std::string, std::string> currentCandidate;

		for (const auto &port : needle.graph.nodes[needleNodeIdx].ports)
			currentCandidate[port.portId] = port.portId;

		if (swapPorts.count(needle.graph.nodes[needleNodeIdx].typeId) == 0)
		{
			if (matchNodePorts(needle.graph, needleNodeIdx, haystack.graph, haystackNodeIdx, currentCandidate) &&
					userSolver->userCompareNodes(needle.graphId, nn.nodeId, nn.userData, haystack.graphId, hn.nodeId, hn.userData, currentCandidate))
				return true;

			if (swapPermutations.count(needle.graph.nodes[needleNodeIdx].typeId) > 0)
				for (const auto &permutation : swapPermutations.at(needle.graph.nodes[needleNodeIdx].typeId)) {
					std::map<std::string, std::string> currentSubCandidate = currentCandidate;
					applyPermutation(currentSubCandidate, permutation);
					if (matchNodePorts(needle.graph, needleNodeIdx, haystack.graph, haystackNodeIdx, currentCandidate) &&
							userSolver->userCompareNodes(needle.graphId, nn.nodeId, nn.userData, haystack.graphId, hn.nodeId, hn.userData, currentCandidate))
						return true;
				}
		}
		else
		{
			std::vector<std::vector<std::string>> thisSwapPorts;
			for (const auto &ports : swapPorts.at(needle.graph.nodes[needleNodeIdx].typeId)) {
				std::vector<std::string> portsVector;
				for (const auto &port : ports)
					portsVector.push_back(port);
				thisSwapPorts.push_back(portsVector);
			}

			int thisPermutations = numberOfPermutationsArray(thisSwapPorts);
			for (int i = 0; i < thisPermutations; i++)
			{
				permutateVectorToMapArray(currentCandidate, thisSwapPorts, i);

				if (matchNodePorts(needle.graph, needleNodeIdx, haystack.graph, haystackNodeIdx, currentCandidate) &&
						userSolver->userCompareNodes(needle.graphId, nn.nodeId, nn.userData, haystack.graphId, hn.nodeId, hn.userData, currentCandidate))
					return true;

				if (swapPermutations.count(needle.graph.nodes[needleNodeIdx].typeId) > 0)
					for (const auto &permutation : swapPermutations.at(needle.graph.nodes[needleNodeIdx].typeId)) {
						std::map<std::string, std::string> currentSubCandidate = currentCandidate;
						applyPermutation(currentSubCandidate, permutation);
						if (matchNodePorts(needle.graph, needleNodeIdx, haystack.graph, haystackNodeIdx, currentCandidate) &&
								userSolver->userCompareNodes(needle.graphId, nn.nodeId, nn.userData, haystack.graphId, hn.nodeId, hn.userData, currentCandidate))
							return true;
					}
			}
		}

		return false;
	}

	void generateEnumerationMatrix(std::vector<std::set<int>> &enumerationMatrix, const GraphData &needle, const GraphData &haystack, const std::map<std::string, std::set<std::string>> &initialMappings) const
	{
		std::map<std::string, std::set<int>> haystackNodesByTypeId;
		for (int i = 0; i < int(haystack.graph.nodes.size()); i++)
			haystackNodesByTypeId[haystack.graph.nodes[i].typeId].insert(i);

		enumerationMatrix.clear();
		enumerationMatrix.resize(needle.graph.nodes.size());
		for (int i = 0; i < int(needle.graph.nodes.size()); i++)
		{
			const Graph::Node &nn = needle.graph.nodes[i];

			for (int j : haystackNodesByTypeId[nn.typeId]) {
				const Graph::Node &hn = haystack.graph.nodes[j];
				if (initialMappings.count(nn.nodeId) > 0 && initialMappings.at(nn.nodeId).count(hn.nodeId) == 0)
					continue;
				if (!matchNodes(needle, i, haystack, j))
					continue;
				enumerationMatrix[i].insert(j);
			}

			if (compatibleTypes.count(nn.typeId) > 0)
				for (const std::string &compatibleTypeId : compatibleTypes.at(nn.typeId))
					for (int j : haystackNodesByTypeId[compatibleTypeId]) {
						const Graph::Node &hn = haystack.graph.nodes[j];
						if (initialMappings.count(nn.nodeId) > 0 && initialMappings.at(nn.nodeId).count(hn.nodeId) == 0)
							continue;
						if (!matchNodes(needle, i, haystack, j))
							continue;
						enumerationMatrix[i].insert(j);
					}
		}
	}

	bool checkEnumerationMatrix(std::vector<std::set<int>> &enumerationMatrix, int i, int j, const GraphData &needle, const GraphData &haystack)
	{
		for (const auto &it_needle : needle.adjMatrix.at(i))
		{
			int needleNeighbour = it_needle.first;
			int needleEdgeType = it_needle.second;

			for (int haystackNeighbour : enumerationMatrix[needleNeighbour])
				if (haystack.adjMatrix.at(j).count(haystackNeighbour) > 0) {
					int haystackEdgeType = haystack.adjMatrix.at(j).at(haystackNeighbour);
					if (diCache.compare(needleEdgeType, haystackEdgeType, swapPorts, swapPermutations)) {
						const Graph::Node &needleFromNode = needle.graph.nodes[i];
						const Graph::Node &needleToNode = needle.graph.nodes[needleNeighbour];
						const Graph::Node &haystackFromNode = haystack.graph.nodes[j];
						const Graph::Node &haystackToNode = haystack.graph.nodes[haystackNeighbour];
						if (userSolver->userCompareEdge(needle.graphId, needleFromNode.nodeId,  needleFromNode.userData, needleToNode.nodeId,  needleToNode.userData,
								haystack.graphId, haystackFromNode.nodeId, haystackFromNode.userData, haystackToNode.nodeId, haystackToNode.userData))
							goto found_match;
					}
				}

			return false;
		found_match:;
		}

		return true;
	}

	bool pruneEnumerationMatrix(std::vector<std::set<int>> &enumerationMatrix, const GraphData &needle, const GraphData &haystack, int &nextRow, bool allowOverlap)
	{
		bool didSomething = true;
		while (didSomething)
		{
			nextRow = -1;
			didSomething = false;
			for (int i = 0; i < int(enumerationMatrix.size()); i++) {
				std::set<int> newRow;
				for (int j : enumerationMatrix[i]) {
					if (!checkEnumerationMatrix(enumerationMatrix, i, j, needle, haystack))
						didSomething = true;
					else if (!allowOverlap && haystack.usedNodes[j])
						didSomething = true;
					else
						newRow.insert(j);
				}
				if (newRow.size() == 0)
					return false;
				if (newRow.size() >= 2 && (nextRow < 0 || needle.adjMatrix.at(nextRow).size() < needle.adjMatrix.at(i).size()))
					nextRow = i;
				enumerationMatrix[i].swap(newRow);
			}
		}
		return true;
	}

	void printEnumerationMatrix(const std::vector<std::set<int>> &enumerationMatrix, int maxHaystackNodeIdx = -1) const
	{
		if (maxHaystackNodeIdx < 0) {
			for (const auto &it : enumerationMatrix)
				for (int idx : it)
					maxHaystackNodeIdx = std::max(maxHaystackNodeIdx, idx);
		}

		my_printf("       ");
		for (int j = 0; j < maxHaystackNodeIdx; j += 5)
			my_printf("%-6d", j);
		my_printf("\n");

		for (int i = 0; i < int(enumerationMatrix.size()); i++)
		{
			my_printf("%5d:", i);
			for (int j = 0; j < maxHaystackNodeIdx; j++) {
				if (j % 5 == 0)
					my_printf(" ");
				my_printf("%c", enumerationMatrix[i].count(j) > 0 ? '*' : '.');
			}
			my_printf("\n");
		}
	}

	bool checkPortmapCandidate(const std::vector<std::set<int>> &enumerationMatrix, const GraphData &needle,  const GraphData &haystack, int idx, const std::map<std::string, std::string> &currentCandidate)
	{
		assert(enumerationMatrix[idx].size() == 1);
		int idxHaystack = *enumerationMatrix[idx].begin();

		const Graph::Node &nn = needle.graph.nodes[idx];
		const Graph::Node &hn = haystack.graph.nodes[idxHaystack];

		if (!matchNodePorts(needle.graph, idx, haystack.graph, idxHaystack, currentCandidate) ||
				!userSolver->userCompareNodes(needle.graphId, nn.nodeId, nn.userData, haystack.graphId, hn.nodeId, hn.userData, currentCandidate))
			return false;

		for (const auto &it_needle : needle.adjMatrix.at(idx))
		{
			int needleNeighbour = it_needle.first;
			int needleEdgeType = it_needle.second;

			assert(enumerationMatrix[needleNeighbour].size() == 1);
			int haystackNeighbour = *enumerationMatrix[needleNeighbour].begin();

			assert(haystack.adjMatrix.at(idxHaystack).count(haystackNeighbour) > 0);
			int haystackEdgeType = haystack.adjMatrix.at(idxHaystack).at(haystackNeighbour);
			if (!diCache.compare(needleEdgeType, haystackEdgeType, currentCandidate, swapPorts, swapPermutations))
				return false;
		}

		return true;
	}

	void generatePortmapCandidates(std::set<std::map<std::string, std::string>> &portmapCandidates, const std::vector<std::set<int>> &enumerationMatrix,
			const GraphData &needle, const GraphData &haystack, int idx)
	{
		std::map<std::string, std::string> currentCandidate;

		for (const auto &port : needle.graph.nodes[idx].ports)
			currentCandidate[port.portId] = port.portId;

		if (swapPorts.count(needle.graph.nodes[idx].typeId) == 0)
		{
			if (checkPortmapCandidate(enumerationMatrix, needle, haystack, idx, currentCandidate))
				portmapCandidates.insert(currentCandidate);

			if (swapPermutations.count(needle.graph.nodes[idx].typeId) > 0)
				for (const auto &permutation : swapPermutations.at(needle.graph.nodes[idx].typeId)) {
					std::map<std::string, std::string> currentSubCandidate = currentCandidate;
					applyPermutation(currentSubCandidate, permutation);
					if (checkPortmapCandidate(enumerationMatrix, needle, haystack, idx, currentSubCandidate))
						portmapCandidates.insert(currentSubCandidate);
				}
		}
		else
		{
			std::vector<std::vector<std::string>> thisSwapPorts;
			for (const auto &ports : swapPorts.at(needle.graph.nodes[idx].typeId)) {
				std::vector<std::string> portsVector;
				for (const auto &port : ports)
					portsVector.push_back(port);
				thisSwapPorts.push_back(portsVector);
			}

			int thisPermutations = numberOfPermutationsArray(thisSwapPorts);
			for (int i = 0; i < thisPermutations; i++)
			{
				permutateVectorToMapArray(currentCandidate, thisSwapPorts, i);

				if (checkPortmapCandidate(enumerationMatrix, needle, haystack, idx, currentCandidate))
					portmapCandidates.insert(currentCandidate);

				if (swapPermutations.count(needle.graph.nodes[idx].typeId) > 0)
					for (const auto &permutation : swapPermutations.at(needle.graph.nodes[idx].typeId)) {
						std::map<std::string, std::string> currentSubCandidate = currentCandidate;
						applyPermutation(currentSubCandidate, permutation);
						if (checkPortmapCandidate(enumerationMatrix, needle, haystack, idx, currentSubCandidate))
							portmapCandidates.insert(currentSubCandidate);
					}
			}
		}
	}

	bool prunePortmapCandidates(std::vector<std::set<std::map<std::string, std::string>>> &portmapCandidates, std::vector<std::set<int>> enumerationMatrix, const GraphData &needle, const GraphData &haystack)
	{
		bool didSomething = false;

		// strategy #1: prune impossible port mappings

		for (int i = 0; i < int(needle.graph.nodes.size()); i++)
		{
			assert(enumerationMatrix[i].size() == 1);
			int j = *enumerationMatrix[i].begin();

			std::set<std::map<std::string, std::string>> thisCandidates;
			portmapCandidates[i].swap(thisCandidates);

			for (const auto &testCandidate : thisCandidates)
			{
				for (const auto &it_needle : needle.adjMatrix.at(i))
				{
					int needleNeighbour = it_needle.first;
					int needleEdgeType = it_needle.second;

					assert(enumerationMatrix[needleNeighbour].size() == 1);
					int haystackNeighbour = *enumerationMatrix[needleNeighbour].begin();

					assert(haystack.adjMatrix.at(j).count(haystackNeighbour) > 0);
					int haystackEdgeType = haystack.adjMatrix.at(j).at(haystackNeighbour);

					std::set<std::map<std::string, std::string>> &candidates =
							i == needleNeighbour ? thisCandidates : portmapCandidates[needleNeighbour];

					for (const auto &otherCandidate : candidates) {
						if (diCache.compare(needleEdgeType, haystackEdgeType, testCandidate, otherCandidate))
							goto found_match;
					}

					didSomething = true;
					goto purgeCandidate;
				found_match:;
				}

				portmapCandidates[i].insert(testCandidate);
			purgeCandidate:;
			}

			if (portmapCandidates[i].size() == 0)
				return false;
		}

		if (didSomething)
			return true;

		// strategy #2: prune a single random port mapping

		for (int i = 0; i < int(needle.graph.nodes.size()); i++)
			if (portmapCandidates[i].size() > 1) {
				// remove last mapping. this keeps ports unswapped in don't-care situations
				portmapCandidates[i].erase(--portmapCandidates[i].end());
				return true;
			}

		return false;
	}

	void ullmannRecursion(std::vector<Solver::Result> &results, std::vector<std::set<int>> &enumerationMatrix, int iter, const GraphData &needle, GraphData &haystack, bool allowOverlap, int limitResults)
	{
		int i = -1;
		if (!pruneEnumerationMatrix(enumerationMatrix, needle, haystack, i, allowOverlap))
			return;

		if (i < 0)
		{
			Solver::Result result;
			result.needleGraphId = needle.graphId;
			result.haystackGraphId = haystack.graphId;

			std::vector<std::set<std::map<std::string, std::string>>> portmapCandidates;
			portmapCandidates.resize(enumerationMatrix.size());

			for (int j = 0; j < int(enumerationMatrix.size()); j++) {
				Solver::ResultNodeMapping mapping;
				mapping.needleNodeId = needle.graph.nodes[j].nodeId;
				mapping.needleUserData = needle.graph.nodes[j].userData;
				mapping.haystackNodeId = haystack.graph.nodes[*enumerationMatrix[j].begin()].nodeId;
				mapping.haystackUserData = haystack.graph.nodes[*enumerationMatrix[j].begin()].userData;
				generatePortmapCandidates(portmapCandidates[j], enumerationMatrix, needle, haystack, j);
				result.mappings[needle.graph.nodes[j].nodeId] = mapping;
			}

			while (prunePortmapCandidates(portmapCandidates, enumerationMatrix, needle, haystack)) { }

			if (verbose) {
				my_printf("\nPortmapper results:\n");
				for (int j = 0; j < int(enumerationMatrix.size()); j++) {
					my_printf("%5d: %s\n", j, needle.graph.nodes[j].nodeId.c_str());
					int variantCounter = 0;
					for (auto &i2 : portmapCandidates.at(j)) {
						my_printf("%*s variant %2d:", 6, "", variantCounter++);
						int mapCounter = 0;
						for (auto &i3 : i2)
							my_printf("%s %s -> %s", mapCounter++ ? "," : "", i3.first.c_str(), i3.second.c_str());
						my_printf("\n");
					}
				}
			}

			for (int j = 0; j < int(enumerationMatrix.size()); j++) {
				if (portmapCandidates[j].size() == 0) {
					if (verbose) {
						my_printf("\nSolution (rejected by portmapper):\n");
						printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
					}
					return;
				}
				result.mappings[needle.graph.nodes[j].nodeId].portMapping = *portmapCandidates[j].begin();
			}

			if (!userSolver->userCheckSolution(result)) {
				if (verbose) {
					my_printf("\nSolution (rejected by userCheckSolution):\n");
					printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
				}
				return;
			}

			for (int j = 0; j < int(enumerationMatrix.size()); j++)
				if (!haystack.graph.nodes[*enumerationMatrix[j].begin()].shared)
					haystack.usedNodes[*enumerationMatrix[j].begin()] = true;

			if (verbose) {
				my_printf("\nSolution:\n");
				printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
			}

			results.push_back(result);
			return;
		}

		if (verbose) {
			my_printf("\n");
			my_printf("Enumeration Matrix at recursion level %d (%d):\n", iter, i);
			printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
		}

		std::set<int> activeRow;
		enumerationMatrix[i].swap(activeRow);

		for (int j : activeRow)
		{
			// found enough?
			if (limitResults >= 0 && int(results.size()) >= limitResults)
				return;

			// already used by other solution -> try next
			if (!allowOverlap && haystack.usedNodes[j])
				continue;

			// create enumeration matrix for child in recursion tree
			std::vector<std::set<int>> nextEnumerationMatrix = enumerationMatrix;
			for (int k = 0; k < int(nextEnumerationMatrix.size()); k++)
				nextEnumerationMatrix[k].erase(j);
			nextEnumerationMatrix[i].insert(j);

			// recursion
			ullmannRecursion(results, nextEnumerationMatrix, iter+1, needle, haystack, allowOverlap, limitResults);

			// we just have found something -> unroll to top recursion level
			if (!allowOverlap && haystack.usedNodes[j] && iter > 0)
				return;
		}
	}

	// additional data structes and functions for mining

	struct NodeSet {
		std::string graphId;
		std::set<int> nodes;
		NodeSet(std::string graphId, int node1, int node2) {
			this->graphId = graphId;
			nodes.insert(node1);
			nodes.insert(node2);
		}
		NodeSet(std::string graphId, const std::vector<int> &nodes) {
			this->graphId = graphId;
			for (int node : nodes)
				this->nodes.insert(node);
		}
		void extend(const NodeSet &other) {
			assert(this->graphId == other.graphId);
			for (int node : other.nodes)
				nodes.insert(node);
		}
		int extendCandidate(const NodeSet &other) const {
			if (graphId != other.graphId)
				return 0;
			int newNodes = 0;
			bool intersect = false;
			for (int node : other.nodes)
				if (nodes.count(node) > 0)
					intersect = true;
				else
					newNodes++;
			return intersect ? newNodes : 0;
		}
		bool operator <(const NodeSet &other) const {
			if (graphId != other.graphId)
				return graphId < other.graphId;
			return nodes < other.nodes;
		}
		std::string to_string() const {
			std::string str = graphId + "(";
			bool first = true;
			for (int node : nodes) {
				str += my_stringf("%s%d", first ? "" : " ", node);
				first = false;
			}
			return str + ")";
		}
	};

	void solveForMining(std::vector<Solver::Result> &results, const GraphData &needle)
	{
		bool backupVerbose = verbose;
		verbose = false;

		for (auto &it : graphData)
		{
			GraphData &haystack = it.second;

			std::vector<std::set<int>> enumerationMatrix;
			std::map<std::string, std::set<std::string>> initialMappings;
			generateEnumerationMatrix(enumerationMatrix, needle, haystack, initialMappings);

			haystack.usedNodes.resize(haystack.graph.nodes.size());
			ullmannRecursion(results, enumerationMatrix, 0, needle, haystack, true, -1);
		}

		verbose = backupVerbose;
	}

	int testForMining(std::vector<Solver::MineResult> &results, std::set<NodeSet> &usedSets, std::set<NodeSet> &nextPool, NodeSet &testSet,
			const std::string &graphId, const Graph &graph, int minNodes, int minMatches, int limitMatchesPerGraph)
	{
		// my_printf("test: %s\n", testSet.to_string().c_str());

		GraphData needle;
		std::vector<std::string> needle_nodes;
		for (int nodeIdx : testSet.nodes)
			needle_nodes.push_back(graph.nodes[nodeIdx].nodeId);
		needle.graph = Graph(graph, needle_nodes);
		needle.graph.markAllExtern();
		diCache.add(needle.graph, needle.adjMatrix, graphId, userSolver);

		std::vector<Solver::Result> ullmannResults;
		solveForMining(ullmannResults, needle);

		int matches = 0;
		std::map<std::string, int> matchesPerGraph;
		std::set<NodeSet> thisNodeSetSet;

		for (auto &it : ullmannResults)
		{
			std::vector<int> resultNodes;
			for (auto &i2 : it.mappings)
				resultNodes.push_back(graphData[it.haystackGraphId].graph.nodeMap[i2.second.haystackNodeId]);
			NodeSet resultSet(it.haystackGraphId, resultNodes);

			// my_printf("match: %s%s\n", resultSet.to_string().c_str(), usedSets.count(resultSet) > 0 ? " (dup)" : "");

#if 0
			if (usedSets.count(resultSet) > 0) {
				// Because of shorted pins isomorphisim is not always bidirectional!
				//
				// This means that the following assert is not true in all cases and subgraph A might
				// show up in the matches for subgraph B but not vice versa... This also means that the
				// order in which subgraphs are processed has an impact on the results set.
				//
				assert(thisNodeSetSet.count(resultSet) > 0);
				continue;
			}
#else
			if (thisNodeSetSet.count(resultSet) > 0)
				continue;
#endif

			usedSets.insert(resultSet);
			thisNodeSetSet.insert(resultSet);

			matchesPerGraph[it.haystackGraphId]++;
			if (limitMatchesPerGraph < 0 || matchesPerGraph[it.haystackGraphId] < limitMatchesPerGraph)
				matches++;
		}

		if (matches < minMatches)
			return matches;

		if (minNodes <= int(testSet.nodes.size()))
		{
			Solver::MineResult result;
			result.graphId = graphId;
			result.totalMatchesAfterLimits = matches;
			result.matchesPerGraph = matchesPerGraph;
			for (int nodeIdx : testSet.nodes) {
				Solver::MineResultNode resultNode;
				resultNode.nodeId = graph.nodes[nodeIdx].nodeId;
				resultNode.userData = graph.nodes[nodeIdx].userData;
				result.nodes.push_back(resultNode);
			}
			results.push_back(result);
		}

		nextPool.insert(thisNodeSetSet.begin(), thisNodeSetSet.end());
		return matches;
	}

	void findNodePairs(std::vector<Solver::MineResult> &results, std::set<NodeSet> &nodePairs, int minNodes, int minMatches, int limitMatchesPerGraph)
	{
		int groupCounter = 0;
		std::set<NodeSet> usedPairs;
		nodePairs.clear();

		if (verbose)
			my_printf("\nMining for frequent node pairs:\n");

		for (auto &graph_it : graphData)
		for (int node1 = 0; node1 < int(graph_it.second.graph.nodes.size()); node1++)
		for (auto &adj_it : graph_it.second.adjMatrix.at(node1))
		{
			const std::string &graphId = graph_it.first;
			const auto &graph = graph_it.second.graph;
			int node2 = adj_it.first;

			if (node1 == node2)
				continue;

			NodeSet pair(graphId, node1, node2);

			if (usedPairs.count(pair) > 0)
				continue;

			int matches = testForMining(results, usedPairs, nodePairs, pair, graphId, graph, minNodes, minMatches, limitMatchesPerGraph);

			if (verbose)
				my_printf("Pair %s[%s,%s] -> %d%s\n", graphId.c_str(), graph.nodes[node1].nodeId.c_str(),
						graph.nodes[node2].nodeId.c_str(), matches, matches < minMatches ? "  *purge*" : "");

			if (minMatches <= matches)
				groupCounter++;
		}

		if (verbose)
			my_printf("Found a total of %d subgraphs in %d groups.\n", int(nodePairs.size()), groupCounter);
	}

	void findNextPool(std::vector<Solver::MineResult> &results, std::set<NodeSet> &pool,
			int oldSetSize, int increment, int minNodes, int minMatches, int limitMatchesPerGraph)
	{
		int groupCounter = 0;
		std::map<std::string, std::vector<const NodeSet*>> poolPerGraph;
		std::set<NodeSet> nextPool;

		for (auto &it : pool)
			poolPerGraph[it.graphId].push_back(&it);

		if (verbose)
			my_printf("\nMining for frequent subcircuits of size %d using increment %d:\n", oldSetSize+increment, increment);

		int count = 0;
		for (auto &it : poolPerGraph)
		{
			std::map<int, std::set<int>> node2sets;
			std::set<NodeSet> usedSets;

			for (int idx = 0; idx < int(it.second.size()); idx++) {
				for (int node : it.second[idx]->nodes)
					node2sets[node].insert(idx);
			}

			for (int idx1 = 0; idx1 < int(it.second.size()); idx1++, count++)
			{
				std::set<int> idx2set;

				for (int node : it.second[idx1]->nodes)
					for (int idx2 : node2sets[node])
						if (idx2 > idx1)
							idx2set.insert(idx2);

				for (int idx2 : idx2set)
				{
					if (it.second[idx1]->extendCandidate(*it.second[idx2]) != increment)
						continue;

					NodeSet mergedSet = *it.second[idx1];
					mergedSet.extend(*it.second[idx2]);

					if (usedSets.count(mergedSet) > 0)
						continue;

					const std::string &graphId = it.first;
					const auto &graph = graphData[it.first].graph;

					if (verbose) {
						my_printf("<%d%%/%d> Found %s[", int(100*count/pool.size()), oldSetSize+increment, graphId.c_str());
						bool first = true;
						for (int nodeIdx : mergedSet.nodes) {
							my_printf("%s%s", first ? "" : ",", graph.nodes[nodeIdx].nodeId.c_str());
							first = false;
						}
						my_printf("] ->");
					}

					int matches = testForMining(results, usedSets, nextPool, mergedSet, graphId, graph, minNodes, minMatches, limitMatchesPerGraph);

					if (verbose)
						my_printf(" %d%s\n", matches, matches < minMatches ? "  *purge*" : "");

					if (minMatches <= matches)
						groupCounter++;
				}
			}
		}

		pool.swap(nextPool);

		if (verbose)
			my_printf("Found a total of %d subgraphs in %d groups.\n", int(pool.size()), groupCounter);
	}

	// interface to the public solver class

protected:
	SolverWorker(Solver *userSolver) : userSolver(userSolver), verbose(false)
	{
	}

	void setVerbose()
	{
		verbose = true;
	}

	void addGraph(std::string graphId, const Graph &graph)
	{
		assert(graphData.count(graphId) == 0);

		GraphData &gd = graphData[graphId];
		gd.graphId = graphId;
		gd.graph = graph;
		diCache.add(gd.graph, gd.adjMatrix, graphId, userSolver);
	}

	void addCompatibleTypes(std::string needleTypeId, std::string haystackTypeId)
	{
		compatibleTypes[needleTypeId].insert(haystackTypeId);
	}

	void addCompatibleConstants(int needleConstant, int haystackConstant)
	{
		compatibleConstants[needleConstant].insert(haystackConstant);
	}

	void addSwappablePorts(std::string needleTypeId, const std::set<std::string> &ports)
	{
		swapPorts[needleTypeId].insert(ports);
		diCache.compareCache.clear();
	}

	void addSwappablePortsPermutation(std::string needleTypeId, const std::map<std::string, std::string> &portMapping)
	{
		swapPermutations[needleTypeId].insert(portMapping);
		diCache.compareCache.clear();
	}

	void solve(std::vector<Solver::Result> &results, std::string needleGraphId, std::string haystackGraphId,
			const std::map<std::string, std::set<std::string>> &initialMappings, bool allowOverlap, int maxSolutions)
	{
		assert(graphData.count(needleGraphId) > 0);
		assert(graphData.count(haystackGraphId) > 0);

		const GraphData &needle = graphData[needleGraphId];
		GraphData &haystack = graphData[haystackGraphId];

		std::vector<std::set<int>> enumerationMatrix;
		generateEnumerationMatrix(enumerationMatrix, needle, haystack, initialMappings);

		if (verbose)
		{
			my_printf("\n");
			my_printf("Needle nodes:\n");
			for (int i = 0; i < int(needle.graph.nodes.size()); i++)
				my_printf("%5d: %s (%s)\n", i, needle.graph.nodes[i].nodeId.c_str(), needle.graph.nodes[i].typeId.c_str());

			my_printf("\n");
			my_printf("Haystack nodes:\n");
			for (int i = 0; i < int(haystack.graph.nodes.size()); i++)
				my_printf("%5d: %s (%s)\n", i, haystack.graph.nodes[i].nodeId.c_str(), haystack.graph.nodes[i].typeId.c_str());

			my_printf("\n");
			my_printf("Needle Adjecency Matrix:\n");
			printAdjMatrix(needle.adjMatrix);

			my_printf("\n");
			my_printf("Haystack Adjecency Matrix:\n");
			printAdjMatrix(haystack.adjMatrix);

			my_printf("\n");
			my_printf("Edge Types:\n");
			diCache.printEdgeTypes();

			my_printf("\n");
			my_printf("Enumeration Matrix (haystack nodes at column indices):\n");
			printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
		}

		haystack.usedNodes.resize(haystack.graph.nodes.size());
		ullmannRecursion(results, enumerationMatrix, 0, needle, haystack, allowOverlap, maxSolutions > 0 ? results.size() + maxSolutions : -1);
	}

	void mine(std::vector<Solver::MineResult> &results, int minNodes, int maxNodes, int minMatches, int limitMatchesPerGraph)
	{
		int nodeSetSize = 2;
		std::set<NodeSet> pool;
		findNodePairs(results, pool, minNodes, minMatches, limitMatchesPerGraph);

		while ((maxNodes < 0 || nodeSetSize < maxNodes) && pool.size() > 0)
		{
			int increment = nodeSetSize - 1;
			if (nodeSetSize + increment >= minNodes)
				increment = minNodes - nodeSetSize;
			if (nodeSetSize >= minNodes)
				increment = 1;

			findNextPool(results, pool, nodeSetSize, increment, minNodes, minMatches, limitMatchesPerGraph);
			nodeSetSize += increment;
		}
	}

	void clearOverlapHistory()
	{
		for (auto &it : graphData)
			it.second.usedNodes.clear();
	}

	void clearConfig()
	{
		compatibleTypes.clear();
		compatibleConstants.clear();
		swapPorts.clear();
		swapPermutations.clear();
		diCache.compareCache.clear();
	}

	friend class Solver;
};

bool Solver::userCompareNodes(const std::string&, const std::string&, void*, const std::string&, const std::string&, void*, const std::map<std::string, std::string>&)
{
	return true;
}

std::string Solver::userAnnotateEdge(const std::string&, const std::string&, void*, const std::string&, void*)
{
	return std::string();
}

bool Solver::userCompareEdge(const std::string&, const std::string&, void*, const std::string&, void*, const std::string&, const std::string&, void*, const std::string&, void*)
{
	return true;
}

bool Solver::userCheckSolution(const Result&)
{
	return true;
}

SubCircuit::Solver::Solver()
{
	worker = new SolverWorker(this);
}

SubCircuit::Solver::~Solver()
{
	delete worker;
}

void SubCircuit::Solver::setVerbose()
{
	worker->setVerbose();
}

void SubCircuit::Solver::addGraph(std::string graphId, const Graph &graph)
{
	worker->addGraph(graphId, graph);
}

void SubCircuit::Solver::addCompatibleTypes(std::string needleTypeId, std::string haystackTypeId)
{
	worker->addCompatibleTypes(needleTypeId, haystackTypeId);
}

void SubCircuit::Solver::addCompatibleConstants(int needleConstant, int haystackConstant)
{
	worker->addCompatibleConstants(needleConstant, haystackConstant);
}

void SubCircuit::Solver::addSwappablePorts(std::string needleTypeId, std::string portId1, std::string portId2, std::string portId3, std::string portId4)
{
	std::set<std::string> ports;
	ports.insert(portId1);
	ports.insert(portId2);
	ports.insert(portId3);
	ports.insert(portId4);
	ports.erase(std::string());
	addSwappablePorts(needleTypeId, ports);
}

void SubCircuit::Solver::addSwappablePorts(std::string needleTypeId, std::set<std::string> ports)
{
	worker->addSwappablePorts(needleTypeId, ports);
}

void SubCircuit::Solver::addSwappablePortsPermutation(std::string needleTypeId, std::map<std::string, std::string> portMapping)
{
	worker->addSwappablePortsPermutation(needleTypeId, portMapping);
}

void SubCircuit::Solver::solve(std::vector<Result> &results, std::string needleGraphId, std::string haystackGraphId, bool allowOverlap, int maxSolutions)
{
	std::map<std::string, std::set<std::string>> emptyInitialMapping;
	worker->solve(results, needleGraphId, haystackGraphId, emptyInitialMapping, allowOverlap, maxSolutions);
}

void SubCircuit::Solver::solve(std::vector<Result> &results, std::string needleGraphId, std::string haystackGraphId,
		const std::map<std::string, std::set<std::string>> &initialMappings, bool allowOverlap, int maxSolutions)
{
	worker->solve(results, needleGraphId, haystackGraphId, initialMappings, allowOverlap, maxSolutions);
}

void SubCircuit::Solver::mine(std::vector<MineResult> &results, int minNodes, int maxNodes, int minMatches, int limitMatchesPerGraph)
{
	worker->mine(results, minNodes, maxNodes, minMatches, limitMatchesPerGraph);
}

void SubCircuit::Solver::clearOverlapHistory()
{
	worker->clearOverlapHistory();
}

void SubCircuit::Solver::clearConfig()
{
	worker->clearConfig();
}

