| #include "subcircuit.h" |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| std::vector<std::string> readLine() |
| { |
| char buffer[4096]; |
| std::vector<std::string> tokenList; |
| |
| while (tokenList.size() == 0 && fgets(buffer, sizeof(buffer), stdin) != NULL) { |
| for (char *p = buffer; char *tok = strtok(p, " \t\r\n"); p = NULL) { |
| if (p != NULL && tok[0] == '#') |
| break; |
| tokenList.push_back(tok); |
| } |
| } |
| |
| return tokenList; |
| } |
| |
| int main() |
| { |
| std::string graphId; |
| SubCircuit::Graph *graph = NULL; |
| SubCircuit::Solver solver; |
| std::map<std::string, std::set<std::string>> initialMappings; |
| std::vector<SubCircuit::Solver::Result> results; |
| std::vector<SubCircuit::Solver::MineResult> mineResults; |
| std::vector<std::string> cmdBuffer; |
| bool lastCommandExpect = false; |
| |
| while (1) |
| { |
| cmdBuffer = readLine(); |
| if (cmdBuffer.empty()) |
| break; |
| |
| printf(graph == NULL || cmdBuffer[0] == "endgraph" ? ">" : "> "); |
| for (const auto &tok : cmdBuffer) |
| printf(" %s", tok.c_str()); |
| printf("\n"); |
| |
| lastCommandExpect = false; |
| |
| if (graph != NULL) |
| { |
| if (cmdBuffer[0] == "node" && cmdBuffer.size() >= 3) { |
| graph->createNode(cmdBuffer[1], cmdBuffer[2]); |
| for (int i = 3; i < int(cmdBuffer.size()); i++) { |
| std::string portId = cmdBuffer[i]; |
| int width = 1, minWidth = -1; |
| if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9') |
| width = atoi(cmdBuffer[++i].c_str()); |
| if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9') |
| minWidth = atoi(cmdBuffer[++i].c_str()); |
| graph->createPort(cmdBuffer[1], portId, width, minWidth); |
| } |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 5) { |
| graph->createConnection(cmdBuffer[1], cmdBuffer[2], cmdBuffer[3], cmdBuffer[4]); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 7) { |
| graph->createConnection(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), cmdBuffer[4], cmdBuffer[5], atoi(cmdBuffer[6].c_str())); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 8) { |
| graph->createConnection(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), cmdBuffer[4], cmdBuffer[5], atoi(cmdBuffer[6].c_str()), atoi(cmdBuffer[7].c_str())); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 5) { |
| int constValue = cmdBuffer[4].size() > 1 && cmdBuffer[4][0] == '#' ? atoi(cmdBuffer[4].c_str()+1) : cmdBuffer[4][0]; |
| graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), constValue); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 4) { |
| graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str())); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "extern" && cmdBuffer.size() >= 3) { |
| for (int i = 2; i < int(cmdBuffer.size()); i++) { |
| std::string portId = cmdBuffer[i]; |
| int bit = -1; |
| if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9') |
| bit = atoi(cmdBuffer[++i].c_str()); |
| graph->markExtern(cmdBuffer[1], portId, bit); |
| } |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "allextern" && cmdBuffer.size() == 1) { |
| graph->markAllExtern(); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "endgraph" && cmdBuffer.size() == 1) { |
| solver.addGraph(graphId, *graph); |
| delete graph; |
| graph = NULL; |
| continue; |
| } |
| } |
| else |
| { |
| if (cmdBuffer[0] == "graph" && cmdBuffer.size() == 2) { |
| graph = new SubCircuit::Graph; |
| graphId = cmdBuffer[1]; |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "compatible" && cmdBuffer.size() == 3) { |
| solver.addCompatibleTypes(cmdBuffer[1], cmdBuffer[2]); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "constcompat" && cmdBuffer.size() == 3) { |
| int needleConstValue = cmdBuffer[1].size() > 1 && cmdBuffer[1][0] == '#' ? atoi(cmdBuffer[1].c_str()+1) : cmdBuffer[1][0]; |
| int haystackConstValue = cmdBuffer[2].size() > 1 && cmdBuffer[2][0] == '#' ? atoi(cmdBuffer[2].c_str()+1) : cmdBuffer[2][0]; |
| solver.addCompatibleConstants(needleConstValue, haystackConstValue); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "swapgroup" && cmdBuffer.size() >= 4) { |
| std::set<std::string> ports; |
| for (int i = 2; i < int(cmdBuffer.size()); i++) |
| ports.insert(cmdBuffer[i]); |
| solver.addSwappablePorts(cmdBuffer[1], ports); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "swapperm" && cmdBuffer.size() >= 4 && cmdBuffer.size() % 2 == 1 && cmdBuffer[cmdBuffer.size()/2 + 1] == ":") { |
| std::map<std::string, std::string> portMapping; |
| int n = (cmdBuffer.size()-3) / 2; |
| for (int i = 0; i < n; i++) |
| portMapping[cmdBuffer[i+2]] = cmdBuffer[i+3+n]; |
| solver.addSwappablePortsPermutation(cmdBuffer[1], portMapping); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "initmap" && cmdBuffer.size() >= 4) { |
| for (int i = 2; i < int(cmdBuffer.size()); i++) |
| initialMappings[cmdBuffer[1]].insert(cmdBuffer[i]); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "solve" && 3 <= cmdBuffer.size() && cmdBuffer.size() <= 5) { |
| bool allowOverlap = true; |
| int maxSolutions = -1; |
| if (cmdBuffer.size() >= 4) |
| allowOverlap = cmdBuffer[3] == "true" || atoi(cmdBuffer[3].c_str()) ? true : false; |
| if (cmdBuffer.size() >= 5) |
| maxSolutions = atoi(cmdBuffer[4].c_str()); |
| solver.solve(results, cmdBuffer[1], cmdBuffer[2], initialMappings, allowOverlap, maxSolutions); |
| initialMappings.clear(); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "mine" && 4 <= cmdBuffer.size() && cmdBuffer.size() <= 5) { |
| solver.mine(mineResults, atoi(cmdBuffer[1].c_str()), atoi(cmdBuffer[2].c_str()), |
| atoi(cmdBuffer[3].c_str()), cmdBuffer.size() == 5 ? atoi(cmdBuffer[4].c_str()) : -1); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "clearoverlap" && cmdBuffer.size() == 1) { |
| solver.clearOverlapHistory(); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "clearconfig" && cmdBuffer.size() == 1) { |
| solver.clearConfig(); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "verbose" && cmdBuffer.size() == 1) { |
| solver.setVerbose(); |
| continue; |
| } |
| |
| if (cmdBuffer[0] == "expect" && cmdBuffer.size() == 2) { |
| int expected = atoi(cmdBuffer[1].c_str()); |
| printf("\n-- Expected %d, Got %d --\n", expected, int(results.size()) + int(mineResults.size())); |
| for (int i = 0; i < int(results.size()); i++) { |
| printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str()); |
| for (const auto &it : results[i].mappings) { |
| printf(" %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str()); |
| for (const auto &it2 : it.second.portMapping) |
| printf(" %s:%s", it2.first.c_str(), it2.second.c_str()); |
| printf("\n"); |
| } |
| } |
| for (auto &result : mineResults) { |
| printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); |
| printf(" primary match in %s:", result.graphId.c_str()); |
| for (auto &node : result.nodes) |
| printf(" %s", node.nodeId.c_str()); |
| printf("\n"); |
| for (auto &it : result.matchesPerGraph) |
| printf(" matches in %s: %d\n", it.first.c_str(), it.second); |
| } |
| printf("\n"); |
| if (expected != int(results.size()) + int(mineResults.size())) { |
| printf("^^ expected %d, Got %d ^^\n\n", expected, int(results.size()) + int(mineResults.size())); |
| printf(" +----------------+\n"); |
| printf(" | \\|/ ____ \\|/ |\n"); |
| printf(" | \"@'/ ,. \\`@\" |\n"); |
| printf(" | /_| \\__/ |_\\ |\n"); |
| printf(" | \\__U_/ |\n"); |
| printf(" | | | |\n"); |
| printf(" +----------------+\n\n"); |
| return 1; |
| } |
| results.clear(); |
| mineResults.clear(); |
| lastCommandExpect = true; |
| continue; |
| } |
| } |
| |
| printf("Invalid input command!\n"); |
| return 1; |
| } |
| |
| if (graph) |
| delete graph; |
| |
| if (!lastCommandExpect) { |
| printf("\n-- Got %d --\n", int(results.size()) + int(mineResults.size())); |
| for (int i = 0; i < int(results.size()); i++) { |
| printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str()); |
| for (const auto &it : results[i].mappings) { |
| printf(" %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str()); |
| for (const auto &it2 : it.second.portMapping) |
| printf(" %s:%s", it2.first.c_str(), it2.second.c_str()); |
| printf("\n"); |
| } |
| } |
| for (auto &result : mineResults) { |
| printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); |
| printf(" primary match in %s:", result.graphId.c_str()); |
| for (auto &node : result.nodes) |
| printf(" %s", node.nodeId.c_str()); |
| printf("\n"); |
| for (auto &it : result.matchesPerGraph) |
| printf(" matches in %s: %d\n", it.first.c_str(), it.second); |
| } |
| } else |
| printf("PASSED.\n"); |
| |
| printf("\n"); |
| |
| return 0; |
| } |
| |