diff --git a/benchmarks/BoostMinSpanningTree.cpp b/benchmarks/BoostMinSpanningTree.cpp new file mode 100644 index 0000000..52e975f --- /dev/null +++ b/benchmarks/BoostMinSpanningTree.cpp @@ -0,0 +1,94 @@ +//===- BoostMinSpanningTree.cpp +//-------------------------------------------------------===// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +// +// This file implements the benchmark for Boost Minimum Spanning Tree. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include +#include + +#define VERTICES 10 +#define MAX_WEIGHT 1000 + +using namespace std; + +namespace { +typedef int t_weight; + +// define the graph type +typedef boost::property EdgeWeightProperty; +typedef boost::adjacency_list + Graph; +typedef boost::graph_traits::vertex_descriptor VerticesMap; + +Graph g; +} // namespace + +void initializeBoostMinSpanningTree() { + + const int vertices = VERTICES; + int num_edges = VERTICES * (VERTICES - 1) / 2; + + std::vector edges; + std::vector weight; + + graph::generateRandomGraph(edges, weight, vertices, MAX_WEIGHT); + + for (std::size_t k = 0; k < num_edges; ++k) { + boost::add_edge(edges[k * 2] - 1, edges[k * 2 + 1] - 1, weight[k], g); + } + + // set the parent vector to receive the minimum spanning tree output + std::vector p(num_vertices(g)); +} + +// Benchmarking function. +static void BoostMinSpanningTree(benchmark::State &state) { + + for (auto _ : state) { + // set the parent vector to receive the minimum spanning tree output + std::vector p(num_vertices(g)); + + for (int i = 0; i < state.range(0); ++i) { + boost::prim_minimum_spanning_tree(g, &p[0]); + } + } +} + +// Register benchmarking function. +BENCHMARK(BoostMinSpanningTree)->Arg(1); + +void generateResultBoostMinSpanningTree() { + initializeBoostMinSpanningTree(); + + // set the parent vector to receive the minimum spanning tree output + std::vector p(num_vertices(g)); + std::cout << "-------------------------------------------------------\n"; + std::cout << "[ Boost Minimum Spanning Tree Result Information ]\n"; + boost::prim_minimum_spanning_tree(g, &p[0]); + for (int i = 0; i < p.size(); i++) { + std::cout << "p[" << i << "] = " << p[i] << ", "; + } + std::cout << "Boost Minimum Spanning Tree operation finished!\n"; +} diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 40d5c69..6a16c6f 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -19,8 +19,7 @@ COMMAND ${GraphMLIR_BINARY_DIR}/graph-opt ${GraphMLIR_EXAMPLES_DIR}/graph.mlir -test-vector-multi-reduction-lowering-patterns -convert-vector-to-llvm -convert-memref-to-llvm - -llvm-request-c-wrappers - -convert-func-to-llvm + -convert-func-to-llvm='emit-c-wrappers=1' -reconcile-unrealized-casts | ${LLVM_MLIR_BINARY_DIR}/mlir-translate --mlir-to-llvmir | ${LLVM_MLIR_BINARY_DIR}/llc -mtriple=${GraphMLIR_OPT_TRIPLE} -mattr=${GraphMLIR_OPT_ATTR} @@ -39,8 +38,11 @@ add_executable(graph-processing-benchmark BoostFloydWarshall.cpp GraphMlirFloydWarshallBenchmark.cpp LemonBFS.cpp + MinSpanningTree.cpp + LemonMinSpanningTree.cpp + BoostMinSpanningTree.cpp + GraphMlirMinSpanningTree.cpp Main.cpp - ) diff --git a/benchmarks/GraphMlirMinSpanningTree.cpp b/benchmarks/GraphMlirMinSpanningTree.cpp new file mode 100644 index 0000000..2e16c93 --- /dev/null +++ b/benchmarks/GraphMlirMinSpanningTree.cpp @@ -0,0 +1,79 @@ +//===- GraphMlirMinSpanningTreeBenchmark.cpp +//----------------------------------===// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +// +// This file implements the benchmark for GraphMLIR Minimum Spanning Tree. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include + +#define VERTICES 10 +#define MAX_WEIGHT 1000 + +using namespace std; + +namespace { +Graph g(graph::detail::GRAPH_ADJ_MATRIX_UNDIRECTED_WEIGHTED, VERTICES); +MemRef *input; +intptr_t size[1]; +} // namespace + +void initializeGraphMlirMinSpanningTree() { + graph::generateRandomGraphI(&g, VERTICES); + input = &g.get_Memref(); + size[0] = VERTICES; + + MemRef cost = MemRef(size, MAX_WEIGHT); + MemRef visited = MemRef(size, 0); + MemRef output = MemRef(size, -1); +} + +// Benchmarking function. +static void GraphMlirMinSpanningTree(benchmark::State &state) { + for (auto _ : state) { + MemRef output = MemRef(size, -1); + MemRef visited = MemRef(size, 0); + MemRef cost = MemRef(size, MAX_WEIGHT); + for (int i = 0; i < state.range(0); ++i) { + graph::min_spanning_tree(input, &output, &visited, &cost); + } + } +} + +// Register benchmarking function. +BENCHMARK(GraphMlirMinSpanningTree)->Arg(1); + +void generateResultGraphMlirMinSpanningTree() { + initializeGraphMlirMinSpanningTree(); + MemRef output(size, -1); + MemRef visited(size, 0); + MemRef cost(size, MAX_WEIGHT); + + std::cout << "-------------------------------------------------------\n"; + std::cout << "[ GraphMLIR Minimum Spanning Tree Result Information ]\n"; + graph::min_spanning_tree(input, &output, &visited, &cost); + + auto parent = output.getData(); + for (int i = 0; i < VERTICES; i++) { + std::cout << "p[" << i << "] = " << parent[i] << ", "; + } + + std::cout << "GraphMLIR Minimum Spanning Tree operation finished!\n"; +} diff --git a/benchmarks/LemonMinSpanningTree.cpp b/benchmarks/LemonMinSpanningTree.cpp new file mode 100644 index 0000000..732818b --- /dev/null +++ b/benchmarks/LemonMinSpanningTree.cpp @@ -0,0 +1,105 @@ +//===- LemonMinSpanningTree.cpp --------------------------------------------------===// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +// +// This file implements the benchmark for LEMON Minimum Spanning Tree. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +using namespace std; +using namespace lemon; + +#define VERTICES 10 +#define MAX_WEIGHT 1000 + +typedef ListGraph::Node Node; +typedef ListGraph::Edge Edge; +typedef ListGraph::NodeIt NodeIt; +typedef ListGraph::EdgeIt EdgeIt; +typedef ListGraph::EdgeMap ECostMap; + +namespace { +ListGraph g; +ListGraph::Node nodes[VERTICES]; +ECostMap edge_cost_map(g); +} // namespace + +void initializeLemonMinSpanningTree() { + for (int i = 0; i < VERTICES; i++) { + nodes[i] = g.addNode(); + } + std::set> container; + std::set>::iterator it; + srand(time(NULL)); + + int edges = VERTICES * (VERTICES - 1) / 2; + for (int j = 1; j <= edges; j++) { + int a = rand() % VERTICES; + int b = rand() % VERTICES; + + std::pair p = std::make_pair(a, b); + std::pair reverse_p = std::make_pair(b, a); + + while (container.find(p) != container.end() || + container.find(reverse_p) != container.end() || a==b) { + a = rand() % VERTICES; + b = rand() % VERTICES; + p = std::make_pair(a, b); + reverse_p = std::make_pair(b, a); + } + + container.insert(p); + container.insert(reverse_p); + edge_cost_map.set(g.addEdge(nodes[a], nodes[b]), 1 + rand() % MAX_WEIGHT); + } +} + +// Benchmarking function. +static void LemonMinSpanningTree(benchmark::State &state) { + for (auto _ : state) { + vector tree_edge_vec; + for (int i = 0; i < state.range(0); ++i) { + kruskal(g, edge_cost_map, std::back_inserter(tree_edge_vec)); + } + } +} + +BENCHMARK(LemonMinSpanningTree)->Arg(1); + +void generateResultLemonMinSpanningTree() { + initializeLemonMinSpanningTree(); + cout << "-------------------------------------------------------\n"; + cout << "[ LEMON Kruskal Result Information ]\n"; + + vector tree_edge_vec; + std::cout << "The weight of the minimum spanning tree is " + << kruskal(g, edge_cost_map, std::back_inserter(tree_edge_vec)) + << std::endl; + + std::cout << "The edges of the tree are: "; + for (int i = tree_edge_vec.size() - 1; i >= 0; i--) + std::cout << g.id(tree_edge_vec[i]) << ";"; + std::cout << std::endl; + std::cout << "The size of the tree is: " << tree_edge_vec.size() + << std::endl; + + cout << "Lemon Kruskal Operation Completed!\n"; +} diff --git a/benchmarks/Main.cpp b/benchmarks/Main.cpp index 39cd8ed..0f17aea 100644 --- a/benchmarks/Main.cpp +++ b/benchmarks/Main.cpp @@ -24,11 +24,19 @@ void initializeGraphMLIRFloydWarshall(); void initializeFloydWarshall(); void initializeLemonBFS(); void initializeBoostFLoydWarshall(); +void initializeMinSpanningTree(); +void initializeBoostMinSpanningTree(); +void initializeLemonMinSpanningTree(); +void initializeGraphMlirMinSpanningTree(); void generateResultGraphMLIRFloydWarshall(); void generateResultFloydWarshall(); void generateResultLemonBFS(); void generateResultBoostFLoydWarshall(); +void generateResultMinSpanningTree(); +void generateResultBoostMinSpanningTree(); +void generateResultLemonMinSpanningTree(); +void generateResultGraphMlirMinSpanningTree(); int main(int argc, char **argv) { @@ -36,6 +44,10 @@ int main(int argc, char **argv) { initializeFloydWarshall(); initializeLemonBFS(); initializeBoostFLoydWarshall(); + initializeMinSpanningTree(); + initializeBoostMinSpanningTree(); + initializeLemonMinSpanningTree(); + initializeGraphMlirMinSpanningTree(); ::benchmark::Initialize(&argc, argv); ::benchmark::RunSpecifiedBenchmarks(); @@ -44,5 +56,10 @@ int main(int argc, char **argv) { generateResultFloydWarshall(); generateResultLemonBFS(); generateResultBoostFLoydWarshall(); + generateResultMinSpanningTree(); + generateResultBoostMinSpanningTree(); + generateResultLemonMinSpanningTree(); + generateResultGraphMlirMinSpanningTree(); + return 0; } diff --git a/benchmarks/MinSpanningTree.cpp b/benchmarks/MinSpanningTree.cpp new file mode 100644 index 0000000..a13c6ad --- /dev/null +++ b/benchmarks/MinSpanningTree.cpp @@ -0,0 +1,106 @@ +//===- MinSpanningTree.cpp --------------------------------------------------===// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===-----------------------------------------------------------------------------------===// +// +// This file implements the benchmark for the naive implementation of Minimum Spanning Tree. +// +//===-----------------------------------------------------------------------------------===// + +#include +#include +#include + +using namespace std; + +#define VERTICES 10 +# define INF 1000 + +namespace { +int input[VERTICES][VERTICES]; +int output[VERTICES]; +} // namespace + +void minSpanningTree(int graph[][VERTICES], int parent[VERTICES]) { + float key[VERTICES]; + bool visited[VERTICES]; + + for (int i = 0; i < VERTICES; i++) { + key[i] = INF; + visited[i] = false; + } + + key[0] = 0; + parent[0] = 0; + + for (int count = 0; count < VERTICES-1; count++) { + int min_index = -1; + float min_cost = INF; + int min_index_temp = -1; + for (int i = 0; i < VERTICES; i++) { + min_index_temp = min_index; + if (visited[i] == false && key[i] < min_cost) { + min_cost = key[i]; + min_index = i; + } + else { + min_index = min_index_temp; + } + } + visited[min_index] = true; + + for (int v = 0; v < VERTICES; v++) { + if (graph[min_index][v] && visited[v] == false && graph[min_index][v] < key[v]) { + parent[v] = min_index; + key[v] = graph[min_index][v]; + } + } + } +} + +void initializeMinSpanningTree() { + int MAX_EDGES = VERTICES * (VERTICES - 1) / 2; + for (int i = 0; i < MAX_EDGES; i++) { + int u = rand() % VERTICES; + int v = rand() % VERTICES; + int d = rand() % 1000; + input[u][v] = d; + } + memset(output, 0, sizeof(output)); +} + +// Benchmarking function. +static void MinSpanningTree(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + minSpanningTree(input, output); + } + } +} + +// Register benchmarking function. +BENCHMARK(MinSpanningTree)->Arg(1); + +void generateResultMinSpanningTree() { + initializeMinSpanningTree(); + std::cout << "-------------------------------------------------------\n"; + std::cout << "[Minimum Spanning Tree Result Information ]\n"; + + minSpanningTree(input, output); + + for (int i = 0; i < VERTICES; i++) { + std::cout << "p[" << i << "] = " << output[i] << ", "; + } + std::cout << "\nMinimum Spanning Tree operation finished!\n"; +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e22b345..bc265a9 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,11 +1,10 @@ add_custom_command(OUTPUT graph.o COMMAND ${GraphMLIR_BINARY_DIR}/graph-opt ${GraphMLIR_EXAMPLES_DIR}/graph.mlir - -lower-graph -lower-affine -convert-scf-to-cf + -lower-graph -lower-affine -convert-scf-to-cf -test-vector-multi-reduction-lowering-patterns -convert-vector-to-llvm - -convert-memref-to-llvm - -llvm-request-c-wrappers - -convert-func-to-llvm + -convert-memref-to-llvm + -convert-func-to-llvm='emit-c-wrappers=1' -reconcile-unrealized-casts | ${LLVM_MLIR_BINARY_DIR}/mlir-translate --mlir-to-llvmir @@ -28,3 +27,7 @@ target_link_libraries(bfsExample GRAPH) add_executable(floydWarshallExample floydWarshallExample.cpp) add_dependencies(floydWarshallExample graph-opt) target_link_libraries(floydWarshallExample GRAPH) + +add_executable(minSpanningTreeExample minSpanningTreeExample.cpp) +add_dependencies(minSpanningTreeExample graph-opt) +target_link_libraries(minSpanningTreeExample GRAPH) diff --git a/examples/graph.mlir b/examples/graph.mlir index d3ac578..1585a7a 100644 --- a/examples/graph.mlir +++ b/examples/graph.mlir @@ -11,3 +11,8 @@ func.func @floyd_warshall(%input : memref, %output : memref) return } +func.func @min_spanning_tree(%input : memref, %output : memref, %visited : memref, %cost : memref) +{ + graph.MinSpanningTree %input, %output, %visited, %cost : memref, memref, memref, memref + return +} diff --git a/examples/minSpanningTreeExample.cpp b/examples/minSpanningTreeExample.cpp new file mode 100644 index 0000000..f8263d0 --- /dev/null +++ b/examples/minSpanningTreeExample.cpp @@ -0,0 +1,73 @@ +//====- minSpanningTreeExample.cpp =============================================// +// +// The graph.bfs operation will be compiled into an object file with the +// graph-opt tool. +// This file will be linked with the object file to generate the executable +// file. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + + +int main() { + + int MAX_VERTICES = 5; + Graph sample_graph( + graph::detail::GRAPH_ADJ_MATRIX_UNDIRECTED_WEIGHTED, MAX_VERTICES); + + sample_graph.addEdge(0, 2, 1); + sample_graph.addEdge(1, 3, 1); + sample_graph.addEdge(1, 4, 2); + sample_graph.addEdge(2, 1, 6); + sample_graph.addEdge(2, 3, 3); + sample_graph.addEdge(3, 4, 1); + sample_graph.addEdge(4, 0, 1); + + std::cout << "Printing graph in format it was entered ( " + "GRAPH_ADJ_MARIX_UNDIRECTED_WEIGHTED )\n"; + sample_graph.printGraphOg(); + std::cout + << "Printing graph in form of 2d matrix after conversion to memref\n"; + sample_graph.printGraph(); + + int V = MAX_VERTICES; + intptr_t size[1]; + size[0] = V; + + MemRef output = MemRef(size, -1); + + // visited tracks vertices that have been visited so far. 0 for unvisited, 1 for visited + MemRef visited = MemRef(size, 0); + // // key tracks the minimum weighted edge corresponding to each vertex, initially infinity (1000) + MemRef cost = MemRef(size, 1000); + + // source vertex cost is set to 0 so that it is picked first + cost[0] = 0; + + auto x = sample_graph.get_Memref(); + graph::min_spanning_tree(&x, &output, &visited, &cost); + + auto parent = output.getData(); + auto y = visited.getData(); + auto z = cost.getData(); + + // expected output - [0 3 0 4 0] + std::cout<<"\nMinimum Spanning Tree\n"; + for(int i=0; i }]; } +def Graph_MinSpanningTreeOp: Graph_Op<"MinSpanningTree"> +{ + let summary = [{ + Minimum spanning tree (MST) is a subset of the edges of the graph that includes all vertices of the graph, + forming a tree such that it has the sum of edge weights is the minimum. + This implementation uses the Prim-Jarnik's algorithm for evaluating the MST. + }]; + + let arguments = (ins Arg:$memrefI, + Arg:$memrefO, + Arg:$memrefV, + Arg:$memrefC); + + let assemblyFormat = [{ + $memrefI `,` $memrefO `,` $memrefV `,` $memrefC attr-dict `:` type($memrefI) `,` type($memrefO) `,` type($memrefV) `,` type($memrefC) + }]; +} + #endif // Graph_GraphOPS_TD diff --git a/include/Interface/graph.h b/include/Interface/graph.h index 8d674a4..51e2f97 100644 --- a/include/Interface/graph.h +++ b/include/Interface/graph.h @@ -47,10 +47,8 @@ enum graph_type { extern "C" { void _mlir_ciface_bfs(MemRef graph1, MemRef graph2, MemRef graph3); -} - -extern "C" { void _mlir_ciface_floyd_warshall(MemRef *graph1, MemRef *graph2); +void _mlir_ciface_min_spanning_tree(MemRef *input, MemRef *output, MemRef *visited, MemRef *cost); } } // namespace detail @@ -63,6 +61,11 @@ void inline bfs(MemRef graph1, MemRef graph2, void inline floyd_warshall(MemRef *input, MemRef *output) { detail::_mlir_ciface_floyd_warshall(input, output); } + +void inline min_spanning_tree(MemRef *input, MemRef *output, MemRef *visited, MemRef *cost) { + detail::_mlir_ciface_min_spanning_tree(input, output, visited, cost); +} + } // namespace graph #endif diff --git a/lib/Conversion/LowerGraph/LowerGraphPass.cpp b/lib/Conversion/LowerGraph/LowerGraphPass.cpp index aa9fe85..a434cb7 100644 --- a/lib/Conversion/LowerGraph/LowerGraphPass.cpp +++ b/lib/Conversion/LowerGraph/LowerGraphPass.cpp @@ -26,6 +26,7 @@ #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Pass/Pass.h" +#include "mlir/IR/ImplicitLocOpBuilder.h" #include "Graph/GraphDialect.h" #include "Graph/GraphOps.h" @@ -162,12 +163,141 @@ class GraphFloydWarshallLowering : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + explicit GraphMinSpanningTreeLowering(MLIRContext *context, int64_t strideParam) + : OpRewritePattern(context) { + stride = strideParam; + } + + LogicalResult matchAndRewrite(graph::MinSpanningTreeOp op, + PatternRewriter &rewriter) const override { + auto loc = op->getLoc(); + auto ctx = op->getContext(); + + /* operands */ + Value input = op->getOperand(0); + Value output = op->getOperand(1); + Value visited = op->getOperand(2); + Value cost = op->getOperand(3); + + /* types */ + IndexType idx = IndexType::get(ctx); + IntegerType i32 = IntegerType::get(ctx, 32); + + /* constants */ + Value c0 = rewriter.create(loc, 0); + Value c1 = rewriter.create(loc, 1); + Value zeroI = rewriter.create(loc, int(0), i32); + Value oneI = rewriter.create(loc, int(1), i32); + Value minusOneI = rewriter.create(loc, int(-1), i32); + Value minusTwoI = rewriter.create(loc, int(-2), i32); + Value maxI = rewriter.create(loc, int(1001), i32); + + /* loop bounds */ + Value V = rewriter.create(loc, input, c0); + Value vAsInt = rewriter.create(loc, i32, V); + // since MST has V-1 edges + Value eAsInt = rewriter.create(loc, vAsInt, minusOneI); + Value E = rewriter.create(loc, rewriter.getIndexType(), eAsInt); + + /* initial condition */ + // parent of root is root itself + rewriter.create(loc, zeroI, output, c0); + + // loop through V-1 times since MST will have at least V-1 edges + rewriter.create( + loc, c0, E, c1, ValueRange{}, + [&](OpBuilder &builder, Location loc, Value inductionVar, ValueRange iterArgs) { + Value minCost = maxI; + Value minIndex = minusTwoI; + + // finding the minimum weighted edge + scf::ForOp forOp = builder.create( + loc, c0, V, c1, ValueRange{cost, visited, minIndex, minCost}, + [&](OpBuilder &builder, Location loc, Value iv, ValueRange args) { + Value cost = args[0]; + Value visited = args[1]; + Value minIndex = args[2]; + Value minCost = args[3]; + + Value costArg = builder.create(loc, cost, iv); + Value visitedArg = builder.create(loc, visited, iv); + + // if vertex is unvisited and cost is lesser than current minimum cost + Value visitedCondition = builder.create(loc, arith::CmpIPredicate::eq, visitedArg, zeroI); + Value costCondition = builder.create(loc, arith::CmpIPredicate::slt, costArg, minCost); + Value condition = builder.create(loc, visitedCondition, costCondition); + + scf::IfOp ifOp = builder.create(loc, TypeRange{i32, i32}, condition, + [&](OpBuilder &builder, Location loc) { + Value temp = builder.create(loc, i32, iv); + builder.create(loc, ValueRange{temp, costArg}); + }, + // else block + [&](OpBuilder &builder, Location loc) { + builder.create(loc, ValueRange{minIndex, minCost}); + }); + minIndex = ifOp.getResult(0); + minCost = ifOp.getResult(1); + + builder.create(loc, ValueRange{cost, visited, minIndex, minCost}); + }); + Value minIndexFoundAsInt = forOp.getResult(2); + Value minIndexFound = builder.create(loc, builder.getIndexType(), minIndexFoundAsInt); + + // mark vertex as visited + builder.create(loc, oneI, visited, minIndexFound); + + // adding the edge to output and updating weights + builder.create( + loc, c0, V, c1, ValueRange{cost, visited, minIndexFound}, + [&](OpBuilder &builder, Location loc, Value iv, ValueRange args) { + Value costVal = args[0]; + Value visited = args[1]; + Value minIndex = args[2]; + + Value costArg = builder.create(loc, cost, iv); + Value visitedArg = builder.create(loc, visited, iv); + Value weight = builder.create(loc, input, ValueRange{minIndex, iv}); + + // if vertex is unvisited, edge between current vertex and minIndex vertex exists, and edge weight is lesser than current cost for that vertex + Value visitedCondition = builder.create(loc, arith::CmpIPredicate::eq, visitedArg, zeroI); + Value costCondition = builder.create(loc, arith::CmpIPredicate::slt, weight, costArg); + Value existsCondition = builder.create(loc, arith::CmpIPredicate::ne, weight, zeroI); + Value condition = builder.create(loc, existsCondition, builder.create(loc, visitedCondition, costCondition)); + + builder.create(loc, condition, + [&](OpBuilder &builder, Location loc) { + Value minIndexAsInt = builder.create(loc, i32, minIndex); + builder.create(loc, minIndexAsInt, output, iv); + builder.create(loc, weight, cost, iv); + builder.create(loc); + }); + + builder.create(loc, ValueRange{cost, visited, minIndex}); + }); + + builder.create(loc); + }); + + rewriter.eraseOp(op); + return success(); + } + +private: + int64_t stride; +}; + } // end anonymous namespace void populateLowerGraphConversionPatterns(RewritePatternSet &patterns, int64_t stride) { patterns.add(patterns.getContext(), stride); patterns.add(patterns.getContext(), stride); + patterns.add(patterns.getContext(), stride); } //===----------------------------------------------------------------------===// diff --git a/lib/Utility/Utils.cpp b/lib/Utility/Utils.cpp index 100e34d..55197e9 100644 --- a/lib/Utility/Utils.cpp +++ b/lib/Utility/Utils.cpp @@ -51,7 +51,7 @@ void inline generateRandomGraph(Graph *graph, int vertices, int maxWei std::pair p = std::make_pair(a, b); std::pair reverse_p = std::make_pair(b, a); - while (container.find(p) != container.end() || container.find(reverse_p) != container.end()) + while (container.find(p) != container.end() || container.find(reverse_p) != container.end() || a==b) { a = rand() % NUM; b = rand() % NUM; @@ -73,6 +73,49 @@ void inline generateRandomGraph(Graph *graph, int vertices, int maxWei // } } +void inline generateRandomGraphI(Graph *graph, int vertices){ + // printf("Inside the function create_graph\n"); + std::set> container; + std::set>::iterator it; + // printf("Inside the function create_graph 1\n"); + srand(time(NULL)); + // printf("Inside the function create_graph 2\n"); + int NUM = vertices; // Number of Vertices + int MAX_EDGES = vertices * (vertices-1) /2; + int NUMEDGE = MAX_EDGES; // Number of Edges + + + // Then print the edges of the form (a b) + // where 'a' is connected to 'b' + for (int j=1; j<=NUMEDGE; j++) + { + int a = rand() % NUM; + int b = rand() % NUM; + std::pair p = std::make_pair(a, b); + std::pair reverse_p = std::make_pair(b, a); + + while (container.find(p) != container.end() || container.find(reverse_p) != container.end() || a==b) + { + a = rand() % NUM; + b = rand() % NUM; + p = std::make_pair(a, b); + reverse_p = std::make_pair(b,a); + } + + container.insert(p); + // int wt = 1 + rand() % MAXWEIGHT; + + graph->addEdge(a, b, 1 + rand() % 1000); + } + // for (it=container.begin(); it!=container.end(); ++it) + // printf("%d %d\n", it->first, it->second); + + container.clear(); + printf("\n"); +// return graph; + // } +} + void inline generateRandomGraph(std::vector &edge, std::vector &weight, int vertices, int maxWeight, int randomUpperLimit, int randomLowerLimit){ // printf("Inside the function create_graph\n"); std::set> container;