| /* | |
| * 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. | |
| * | |
| */ | |
| #ifndef SUBCIRCUIT_H | |
| #define SUBCIRCUIT_H | |
| #include <string> | |
| #include <vector> | |
| #include <set> | |
| #include <map> | |
| namespace SubCircuit | |
| { | |
| class SolverWorker; | |
| class Graph | |
| { | |
| protected: | |
| struct BitRef { | |
| int nodeIdx, portIdx, bitIdx; | |
| BitRef(int nodeIdx = -1, int portIdx = -1, int bitIdx = -1) : nodeIdx(nodeIdx), portIdx(portIdx), bitIdx(bitIdx) { }; | |
| bool operator < (const BitRef &other) const; | |
| }; | |
| struct Edge { | |
| std::set<BitRef> portBits; | |
| int constValue; | |
| bool isExtern; | |
| Edge() : constValue(0), isExtern(false) { }; | |
| }; | |
| struct PortBit { | |
| int edgeIdx; | |
| PortBit() : edgeIdx(-1) { }; | |
| }; | |
| struct Port { | |
| std::string portId; | |
| int minWidth; | |
| std::vector<PortBit> bits; | |
| Port() : minWidth(-1) { }; | |
| }; | |
| struct Node { | |
| std::string nodeId, typeId; | |
| std::map<std::string, int> portMap; | |
| std::vector<Port> ports; | |
| void *userData; | |
| bool shared; | |
| Node() : userData(NULL), shared(false) { }; | |
| }; | |
| bool allExtern; | |
| std::map<std::string, int> nodeMap; | |
| std::vector<Node> nodes; | |
| std::vector<Edge> edges; | |
| public: | |
| Graph() : allExtern(false) { }; | |
| Graph(const Graph &other, const std::vector<std::string> &otherNodes); | |
| void createNode(std::string nodeId, std::string typeId, void *userData = NULL, bool shared = false); | |
| void createPort(std::string nodeId, std::string portId, int width = 1, int minWidth = -1); | |
| void createConnection(std::string fromNodeId, std::string fromPortId, int fromBit, std::string toNodeId, std::string toPortId, int toBit, int width = 1); | |
| void createConnection(std::string fromNodeId, std::string fromPortId, std::string toNodeId, std::string toPortId); | |
| void createConstant(std::string toNodeId, std::string toPortId, int toBit, int constValue); | |
| void createConstant(std::string toNodeId, std::string toPortId, int constValue); | |
| void markExtern(std::string nodeId, std::string portId, int bit = -1); | |
| void markAllExtern(); | |
| void print(); | |
| friend class SolverWorker; | |
| }; | |
| class Solver | |
| { | |
| public: | |
| struct ResultNodeMapping { | |
| std::string needleNodeId, haystackNodeId; | |
| void *needleUserData, *haystackUserData; | |
| std::map<std::string, std::string> portMapping; | |
| }; | |
| struct Result { | |
| std::string needleGraphId, haystackGraphId; | |
| std::map<std::string, ResultNodeMapping> mappings; | |
| }; | |
| struct MineResultNode { | |
| std::string nodeId; | |
| void *userData; | |
| }; | |
| struct MineResult { | |
| std::string graphId; | |
| int totalMatchesAfterLimits; | |
| std::map<std::string, int> matchesPerGraph; | |
| std::vector<MineResultNode> nodes; | |
| }; | |
| private: | |
| SolverWorker *worker; | |
| protected: | |
| virtual bool userCompareNodes(const std::string &needleGraphId, const std::string &needleNodeId, void *needleUserData, | |
| const std::string &haystackGraphId, const std::string &haystackNodeId, void *haystackUserData, const std::map<std::string, std::string> &portMapping); | |
| virtual std::string userAnnotateEdge(const std::string &graphId, const std::string &fromNodeId, void *fromUserData, const std::string &toNodeId, void *toUserData); | |
| virtual bool userCompareEdge(const std::string &needleGraphId, const std::string &needleFromNodeId, void *needleFromUserData, const std::string &needleToNodeId, void *needleToUserData, | |
| const std::string &haystackGraphId, const std::string &haystackFromNodeId, void *haystackFromUserData, const std::string &haystackToNodeId, void *haystackToUserData); | |
| virtual bool userCheckSolution(const Result &result); | |
| friend class SolverWorker; | |
| public: | |
| Solver(); | |
| virtual ~Solver(); | |
| void setVerbose(); | |
| void addGraph(std::string graphId, const Graph &graph); | |
| void addCompatibleTypes(std::string needleTypeId, std::string haystackTypeId); | |
| void addCompatibleConstants(int needleConstant, int haystackConstant); | |
| void addSwappablePorts(std::string needleTypeId, std::string portId1, std::string portId2, std::string portId3 = std::string(), std::string portId4 = std::string()); | |
| void addSwappablePorts(std::string needleTypeId, std::set<std::string> ports); | |
| void addSwappablePortsPermutation(std::string needleTypeId, std::map<std::string, std::string> portMapping); | |
| void solve(std::vector<Result> &results, std::string needleGraphId, std::string haystackGraphId, bool allowOverlap = true, int maxSolutions = -1); | |
| void solve(std::vector<Result> &results, std::string needleGraphId, std::string haystackGraphId, | |
| const std::map<std::string, std::set<std::string>> &initialMapping, bool allowOverlap = true, int maxSolutions = -1); | |
| void mine(std::vector<MineResult> &results, int minNodes, int maxNodes, int minMatches, int limitMatchesPerGraph = -1); | |
| void clearOverlapHistory(); | |
| void clearConfig(); | |
| }; | |
| } | |
| #endif /* SUBCIRCUIT_H */ |