├── _config.yml ├── src ├── Readme.md ├── transpose.h ├── dvector.h ├── graph.cpp ├── dfs.h ├── scc.h ├── bgaMain.cpp ├── heap.h ├── graph.h ├── mst.h └── shortestPath.h ├── test ├── dgraph1.txt ├── ugraph1.txt ├── README.md ├── ugraph2.txt ├── dgraph2.txt ├── dgraph5.txt ├── dgraph3.txt ├── dgraph8.txt ├── dgraph6.txt ├── dgraph7.txt ├── ugraph3.txt └── dgraph4.txt ├── graph.jpg ├── docs ├── graph.jpg ├── ExampleGraph.JPG ├── GraphFormat.md └── README.md ├── README.md └── LICENSE /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /src/Readme.md: -------------------------------------------------------------------------------- 1 | # Source Directory. 2 | -------------------------------------------------------------------------------- /test/dgraph1.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n1 n2 3 | n1 n3 4 | n2 n3 5 | n3 n1 6 | -------------------------------------------------------------------------------- /test/ugraph1.txt: -------------------------------------------------------------------------------- 1 | graph undirected 2 | n1 n2 3 | n1 n3 4 | n2 n3 5 | n3 n1 6 | -------------------------------------------------------------------------------- /graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srohit0/DataScienceGraphAlgorithms/HEAD/graph.jpg -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | #Description 2 | 3 | This dir contains graph files for unit testing. 4 | -------------------------------------------------------------------------------- /docs/graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srohit0/DataScienceGraphAlgorithms/HEAD/docs/graph.jpg -------------------------------------------------------------------------------- /docs/ExampleGraph.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srohit0/DataScienceGraphAlgorithms/HEAD/docs/ExampleGraph.JPG -------------------------------------------------------------------------------- /test/ugraph2.txt: -------------------------------------------------------------------------------- 1 | graph undirected 2 | A B 3 | A F 4 | A C 5 | A H 6 | B C 7 | B D 8 | B E 9 | B G 10 | D G 11 | E F 12 | -------------------------------------------------------------------------------- /test/dgraph2.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n6 n2 3 | n1 n2 4 | n1 n4 5 | n3 n4 6 | n3 n7 7 | n2 n5 8 | n2 n8 9 | n2 n7 10 | n4 n8 11 | -------------------------------------------------------------------------------- /test/dgraph5.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n1 n2 2 3 | n1 n3 4 4 | n2 n3 1 5 | n2 n4 4 6 | n2 n5 2 7 | n3 n5 3 8 | n4 n6 2 9 | n5 n4 3 10 | n5 n6 2 11 | -------------------------------------------------------------------------------- /test/dgraph3.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n6 n2 22 3 | n1 n2 19 4 | n1 n4 7 5 | n3 n4 29 6 | n3 n7 32 7 | n2 n5 63 8 | n2 n8 59 9 | n2 n7 4 10 | n4 n8 89 11 | -------------------------------------------------------------------------------- /test/dgraph8.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | A E 3 | A H 4 | B A 5 | B G 6 | C D 7 | D F 8 | E D 9 | E J 10 | F C 11 | F I 12 | G F 13 | H C 14 | H I 15 | I G 16 | J B 17 | J H 18 | -------------------------------------------------------------------------------- /test/dgraph6.txt: -------------------------------------------------------------------------------- 1 | graph undirected 2 | A B 1 3 | A C 3 4 | A F 10 5 | B C 1 6 | B D 7 7 | B E 5 8 | B G 2 9 | C D 9 10 | C E 3 11 | D E 2 12 | D F 1 13 | D G 12 14 | E F 2 15 | -------------------------------------------------------------------------------- /test/dgraph7.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n0 n1 30 3 | n0 n2 10 4 | n1 n3 25 5 | n1 n4 10 6 | n2 n4 9 7 | n2 n5 15 8 | n3 n6 27 9 | n4 n6 7 10 | n4 n7 16 11 | n4 n5 8 12 | n6 n7 5 13 | n5 n7 35 14 | -------------------------------------------------------------------------------- /test/ugraph3.txt: -------------------------------------------------------------------------------- 1 | graph undirected 2 | n1 n2 4 3 | n1 n3 6 4 | n1 n4 16 5 | n2 n6 24 6 | n3 n4 8 7 | n3 n5 5 8 | n3 n6 23 9 | n4 n5 10 10 | n4 n8 21 11 | n5 n6 18 12 | n5 n7 11 13 | n5 n8 14 14 | n6 n7 9 15 | n7 n8 7 16 | -------------------------------------------------------------------------------- /test/dgraph4.txt: -------------------------------------------------------------------------------- 1 | graph directed 2 | n0 n1 4 3 | n0 n7 8 4 | n1 n2 8 5 | n1 n7 11 6 | n2 n3 7 7 | n2 n8 2 8 | n2 n5 4 9 | n3 n4 9 10 | n3 n5 14 11 | n4 n5 10 12 | n5 n6 2 13 | n6 n7 1 14 | n6 n8 6 15 | n7 n8 7 16 | -------------------------------------------------------------------------------- /docs/GraphFormat.md: -------------------------------------------------------------------------------- 1 | ## Graph Format 2 | 3 | ``` 4 | # comment 5 | graph (un)directed` 6 | [edge-weight] 7 | ``` 8 | 9 | ***Example Graph File*** 10 | 11 | ![](https://github.com/srohit0/BasicGraphAlgorithmsCpp/blob/master/docs/ExampleGraph.JPG) 12 | 13 | 14 | 15 | ``` 16 | # Comment, ignored by graph reader 17 | graph directed 18 | n1 n2 2 19 | n1 n3 4 20 | n2 n3 1 21 | n2 n4 4 22 | n2 n5 2 23 | n3 n5 3 24 | n4 n6 2 25 | n5 n4 3 26 | n5 n6 2 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## How to Compile 2 | ``` 3 | cd src 4 | bgaMain.cpp -o bgaMain.exe 5 | ``` 6 | 7 | ## How to Run 8 | ``` bgaMain.exe ``` 9 | 10 | ## Example run 11 | 12 | 13 | $ src/bgaMain.exe test/dgraph5.txt 14 | ``` 15 | created graph with 6 nodes and 9 edges. 16 | type 'help' for more options 17 | ``` 18 | >> help 19 | ``` 20 | help 21 | print 22 | search 23 | sort 24 | mst [prim|kruskal] 25 | path 26 | quit 27 | ``` 28 | >> print 29 | ``` 30 | graph directed 31 | n2 n3 1 32 | n1 n2 2 33 | ... 34 | ``` 35 | >> path n1 36 | ``` 37 | nd dist_from_src edge 38 | == ============= ==== 39 | n1 0 [none n1 0] 40 | n2 2 [n1 n2 2] 41 | n3 3 [n2 n3 1] 42 | ``` 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/transpose.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | 7 | // Transpose: 8 | // The transpose, converse or reverse of a directed graph G is another 9 | // directed graph on the same set of vertices with all of the edges reversed 10 | // compared to the orientation of the corresponding edges in G. That is, 11 | // if G contains an edge (u,v) then the converse/transpose/reverse of G 12 | // contains an edge (v,u) and vice versa. 13 | // 14 | // Transpose of undirected graph is same graph with no change. 15 | 16 | // Reference: https://en.wikipedia.org/wiki/Transpose_graph 17 | 18 | #pragma once 19 | #ifndef GRAPH_TRANSPOSE_H 20 | #define GRAPH_TRANSPOSE_H 21 | 22 | #include "graph.h" 23 | 24 | using namespace std; 25 | 26 | class transpose { 27 | private: 28 | bool inplace_; // return a new graph or compute transpose in the same one. 29 | public: 30 | transpose(bool inplace) : inplace_(inplace) 31 | {} 32 | const basicGraph::bGraph* build(const basicGraph::bGraph* graph) 33 | { 34 | const basicGraph::bGraph* new_graph = graph; 35 | if (!inplace_) 36 | new_graph = new basicGraph::bGraph(*graph); 37 | 38 | if (!graph->directed()) 39 | { 40 | cerr << "Warning: transpose of undirected graph is the same graph.\n"; 41 | return new_graph; 42 | } 43 | 44 | // clear edge list of nodes. 45 | set::iterator niter; 46 | for (niter = new_graph->nodeBegin(); niter != new_graph->nodeEnd(); niter++) 47 | { 48 | const_cast(*niter)->clearEdgeList(); 49 | } 50 | 51 | set::iterator eiter; 52 | for (eiter = new_graph->edgeBegin(); eiter != new_graph->edgeEnd(); eiter++) 53 | { 54 | const_cast(*eiter)->swap_nodes(); 55 | const_cast((*eiter)->n1())->addEdge(*eiter); 56 | } 57 | return new_graph; 58 | } 59 | }; 60 | 61 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic Graph Algorithms for Data Scientists 2 | This live repo aims to cover basic graph algorithms implemented in C++ (for performance reasons) used in data science. It's meant for educational purposes and will continue to evole. 3 | 4 | ## Introduction 5 | 6 | This repo covers basic graph algorithms for directed and undirected graphs with/without weights on edges. Graph description is read from a file with ascii format. 7 | 8 | Base graph data structure is targeted for **sparse graphs** efficiency. For example, it maintains adjancy list and pointrs. Here are big-O time and space complexities. 9 | 10 | 11 | | | RAM | node-add | edge-add | node-remove | edge-remove | query | 12 | | --------------- |:---------:|:--------:|:--------:|:-----------:|:-----------:|:---------:| 13 | | Adjacency List | [n]+[e] | 1 | 1 | [n]+[e] | [e] | [e] | 14 | | Incident List | [n]+[e] | 1 | 1 | [e] | [e] | [e] | 15 | 16 | Legend: 17 | * Two vertices are called adjacent if they are connected by an edge. 18 | * Two edges are called incident, if they share a vertex. 19 | 20 | ## Basic Graph 21 | 22 | ![Graph Structure](docs/graph.jpg) 23 | 24 | ```cpp 25 | namespace basicGraph { 26 | ... 27 | class bNode { 28 | private: 29 | string name_; // node name 30 | set edgelist_; // incident list 31 | ... 32 | }/ 33 | class bEdge { 34 | private: 35 | const bNode* n1_; // from node for directd graphs 36 | const bNode* n2_; // to node for directed graphs 37 | ... 38 | }; 39 | ... 40 | class bGraph { 41 | private: 42 | bool isDirected_; 43 | set nodeset_; 44 | set edgeset_; 45 | ... 46 | }; 47 | } 48 | 49 | ``` 50 | For more details, refer to [graph.h](src/graph.h). 51 | 52 | ## Algorithms Covered 53 | 54 | * [DFS](src/dfs.h) 55 | * [Transpose](src/transpose.h) 56 | * [Topological Sort](src/dfs.h) 57 | * [Strongly Connected Components](src/scc.h) 58 | * [Prim's Mimimal Spanning Tree](src/mst.h) 59 | * [Kruskal's Mimimal Spanning Tree](src/mst.h) 60 | * [Dijkstra's Single Source Shortest Path to All Nodes](src/shortestPath.h) 61 | * [A* (aka Astar) Source-Destination Pair Shortest Path Finder Algorithm](src/shortestPath.h) 62 | 63 | ## Graph File Format 64 | 65 | ``` 66 | graph (un)directed` 67 | [edge-weight] 68 | ``` 69 | 70 | ***Example Graph File*** 71 | 72 | ![Example Graph](docs/ExampleGraph.JPG) 73 | 74 | ``` 75 | # Comment, ignored by the graph reader 76 | graph directed 77 | n1 n2 2 78 | n1 n3 4 79 | n2 n3 1 80 | n2 n4 4 81 | n2 n5 2 82 | n3 n5 3 83 | n4 n6 2 84 | n5 n4 3 85 | n5 n6 2 86 | ``` 87 | 88 | ## Application 89 | 90 | ### How to Compile 91 | ``` 92 | cd src 93 | *.cpp -o bgaMain.exe 94 | ``` 95 | 96 | ### How to Run 97 | ``` bgaMain.exe ``` 98 | 99 | ### Example run 100 | 101 | 102 | $ src/bgaMain.exe test/dgraph5.txt 103 | ``` 104 | created graph with 6 nodes and 9 edges. 105 | type 'help' for more options 106 | ``` 107 | >> help 108 | ``` 109 | help 110 | print 111 | search 112 | sort 113 | mst [prim|kruskal] 114 | path 115 | quit 116 | ``` 117 | >> print 118 | ``` 119 | graph directed 120 | n2 n3 1 121 | n1 n2 2 122 | ... 123 | ``` 124 | >> path n1 125 | ``` 126 | nd dist_from_src edge 127 | == ============= ==== 128 | n1 0 [none n1 0] 129 | n2 2 [n1 n2 2] 130 | n3 3 [n2 n3 1] 131 | ``` 132 | 133 | 134 | ## Disclaimer 135 | 136 | This is a quick and dirty code produced over weekends. Main objective behind this repository is purely educational. It has quite a bit of room for improvement. Feel free to reach out if you spot weakness, bug, enancement or simply a suggestion. 137 | 138 | -------------------------------------------------------------------------------- /src/dvector.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2019 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | // Generic dvector class for efficiency. 8 | 9 | #include 10 | #include /* malloc, free, rand */ 11 | 12 | #pragma once 13 | 14 | #define VECTOR_INIT_SIZE 12 15 | // Ref: https://stackoverflow.com/questions/5232198/about-vectors-growth 16 | #define VECTOR_GROWTH_FACTOR 1.5 17 | 18 | template 19 | class dvector { 20 | typedef size_t Index; 21 | protected: 22 | T* _m_data; 23 | size_t _sz; 24 | size_t _capacity; 25 | static T NULL_DATA; 26 | 27 | void stretch_capacity() 28 | { 29 | _capacity = static_cast(VECTOR_GROWTH_FACTOR * _capacity); 30 | _m_data = static_cast(realloc(_m_data, _capacity)); 31 | assert(_m_data); 32 | } 33 | // move data values from 'index' to end by n away from start. 34 | void move_right(Index index, size_t n) 35 | { 36 | if (index < 0 || index >= _sz) return; // bad index 37 | while (_sz + n >= _capacity) 38 | stretch_capacity(); 39 | for (Index i = _sz + n - 1; i > index + n - 1; i--) 40 | _m_data[i] = _m_data[i - 1]; 41 | _sz = _sz + n; 42 | } 43 | // move data values from 'index' to end by n towards start. 44 | void move_left(Index index, size_t n) 45 | { 46 | if (index < 0 || index >= _sz) return; // bad index 47 | if (index + n >= _sz) { 48 | _sz = index; 49 | return; 50 | } 51 | for (Index i = index; i < _sz; i++) 52 | _m_data[i] = _m_data[i + n]; 53 | _sz = _sz - n; 54 | } 55 | public: 56 | // These selected vector methods are inspired from STL C++ vector template 57 | // default constructor 58 | dvector(size_t max_sz = VECTOR_INIT_SIZE) 59 | { 60 | _sz = 0; 61 | _capacity = max_sz; 62 | if (_capacity > 0) { 63 | _m_data = static_cast(malloc(_capacity * sizeof(T))); 64 | assert(_m_data); 65 | } 66 | } 67 | 68 | // copy constructor 69 | dvector(const dvector& other) 70 | { 71 | _sz = other._sz; 72 | _capacity = other._capacity; 73 | _m_data = static_cast(malloc(_capacity * sizeof(T))); 74 | assert(_m_data); 75 | for (Index i = 0; i < _sz; i++) 76 | _m_data[i] = other._m_data[i]; 77 | } 78 | 79 | // assignment operator 80 | dvector& operator=(const dvector& other) 81 | { 82 | if (this != other) { 83 | if (_capacity < other._capacity) { 84 | _m_data = static_cast(realloc(_m_data, other._capacity)); 85 | assert(_m_data); 86 | _capacity = other._capacity; 87 | } 88 | for (Index i = 0; i < other._sz; i++) 89 | _m_data[i] = other._m_data[i]; 90 | _sz = other._sz; 91 | } 92 | return *this; 93 | } 94 | 95 | // destructor 96 | ~dvector() 97 | { 98 | if (_m_data) 99 | free(_m_data); 100 | } 101 | 102 | short dimension() 103 | { 104 | return 1; 105 | } 106 | 107 | // unsafe 108 | T& operator[](const Index& index) const 109 | { 110 | return _m_data[index]; 111 | } 112 | 113 | void clear() 114 | { 115 | _sz = 0; 116 | } 117 | 118 | size_t size() 119 | { 120 | return _sz; 121 | } 122 | 123 | bool empty() 124 | { 125 | return _sz == 0; 126 | } 127 | 128 | void push_back(const T& data) 129 | { 130 | if (_sz == _capacity) 131 | stretch_capacity(); 132 | _m_data[_sz++] = data; 133 | } 134 | 135 | void pop_back() 136 | { 137 | _sz = (_sz > 0) ? --_sz : _sz; 138 | } 139 | 140 | T& back() 141 | { 142 | if (_sz > 0) 143 | return _m_data[_sz - 1]; 144 | assert(false); 145 | return NULL_DATA; // return reference on stack? unsafe TODOs: use smart_ptrs 146 | } 147 | 148 | 149 | void insert(size_t index, const T& data) 150 | { 151 | move_right(index, 1); 152 | _m_data[index] = data; 153 | } 154 | 155 | // erase 'n' element starting from 'index' 156 | void erase(size_t index, size_t n) 157 | { 158 | move_left(index, n); 159 | } 160 | 161 | // linear search 162 | int find(const T& data) 163 | { 164 | for (Index i = 0; i < _sz; i++) 165 | if (_m_data[i] == data) 166 | return i; 167 | return -1; 168 | } 169 | 170 | bool exists(const T& data) 171 | { 172 | return (find(data) > 0); 173 | } 174 | }; 175 | -------------------------------------------------------------------------------- /src/graph.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | 8 | #include 9 | #include "graph.h" 10 | 11 | using namespace std; 12 | 13 | const long basicGraph::bEdge::INVALID_WEIGHT = LONG_MIN; 14 | 15 | bool basicGraph::nodeCompare::operator()(const bNode * n1, const bNode * n2) const 16 | { 17 | return n1->name() < n2->name(); 18 | } 19 | 20 | bool basicGraph::edgeCompare::operator()(const bEdge * e1, const bEdge * e2) const 21 | { 22 | size_t w1 = 0, w2 = 0; 23 | if (e1->hasWeight() && e2->hasWeight()) 24 | { 25 | w1 = dynamic_cast(e1)->weight(); 26 | w2 = dynamic_cast(e2)->weight(); 27 | } 28 | 29 | return w1 == w2 ? e1->name() < e2->name() : w1 < w2; 30 | 31 | } 32 | 33 | void basicGraph::tokenizeLine(char* line, std::vector &tokens) 34 | { 35 | stringstream stokens(line); 36 | string token; 37 | 38 | // Tokenizing w.r.t. space ' ' 39 | while (getline(stokens, token, ' ')) 40 | { 41 | tokens.push_back(token); 42 | } 43 | } 44 | 45 | basicGraph::bGraph::bGraph(const basicGraph::bGraph& other_graph) 46 | { 47 | isDirected_ = other_graph.directed(); 48 | set::iterator eiter; 49 | for (eiter = other_graph.edgeBegin(); eiter != other_graph.edgeEnd(); eiter++) 50 | { 51 | size_t wt = (*eiter)->hasWeight() ? 52 | dynamic_cast(*eiter)->weight() : 53 | basicGraph::bEdge::INVALID_WEIGHT; 54 | addNodesAndEdge((*eiter)->n1()->name(), (*eiter)->n2()->name(), wt); 55 | } 56 | return; 57 | } 58 | 59 | void basicGraph::bGraph::addNodesAndEdge(string n1, string n2, size_t weight) 60 | { 61 | basicGraph::bNode* node1 = addNode(n1); 62 | basicGraph::bNode* node2 = addNode(n2); 63 | 64 | const basicGraph::bEdge* edge = addEdge(node1, node2, weight); 65 | node1->addEdge(edge); 66 | if (!directed()) 67 | node2->addEdge(edge); 68 | 69 | return; 70 | } 71 | 72 | void 73 | basicGraph::bGraph::print() const 74 | { 75 | cout << "graph " << (isDirected_ ? "directed" : "undirected") << endl; 76 | set::iterator eiter = edgeset_.begin(); 77 | for (; eiter != edgeset_.end(); eiter++) 78 | (*eiter)->print(); 79 | } 80 | 81 | basicGraph::bGraph *basicGraph::bGraph::readBasicGraph(string filename) 82 | { 83 | const unsigned int BUFFER_SIZE = 1024; 84 | char line[BUFFER_SIZE]; 85 | 86 | filebuf buf; 87 | buf.open(filename.c_str(), ios::in); 88 | if (!buf.is_open()) { 89 | cerr << "could not open file" << filename << endl; 90 | return nullptr; 91 | } 92 | bGraph* new_graph = new bGraph(); 93 | 94 | istream graph_stream(&buf); 95 | while (!graph_stream.eof() ) { 96 | graph_stream.getline(line, BUFFER_SIZE); 97 | 98 | vector tokens; 99 | tokenizeLine(line, tokens); 100 | 101 | if (tokens.size() == 0 || tokens[0][0] == '#') { 102 | continue; 103 | } 104 | if (tokens.size() < 2) 105 | { 106 | cerr << "invlid input line in graph " << line << endl; 107 | continue; 108 | } 109 | 110 | 111 | if (tokens[0] == "graph") { 112 | if (tokens[1] == "undirected") 113 | new_graph->setDirected(false); 114 | else if (tokens[1] == "directed") 115 | new_graph->setDirected(true); 116 | else 117 | cerr << "Error: invalid keyword after \'graph\' : " << tokens[1]; 118 | } 119 | else { 120 | size_t weight = basicGraph::bEdge::INVALID_WEIGHT; 121 | if (tokens.size() > 2) 122 | { 123 | weight = stol(tokens[2]); 124 | if (weight < 0) 125 | cerr << "Warning: negative weight for the edge " << line << ".\n"; 126 | } 127 | 128 | new_graph->addNodesAndEdge(tokens[0], tokens[1], weight); 129 | } 130 | } 131 | buf.close(); 132 | 133 | return new_graph; 134 | } 135 | 136 | basicGraph::bGraph::~bGraph() { 137 | set::iterator niter = nodeset_.begin(); 138 | for (; niter != nodeset_.end(); niter++) 139 | delete (*niter); 140 | 141 | set::iterator eiter = edgeset_.begin(); 142 | for (; eiter != edgeset_.end(); eiter++) 143 | delete(*eiter); 144 | } -------------------------------------------------------------------------------- /src/dfs.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | // Depth First Search Algorithms 8 | // 1. Build DFS Tree 9 | // 2. Topologica Sorting 10 | 11 | #ifndef GRAPH_DFS_H 12 | #define GRAPH_DFS_H 13 | 14 | #include "graph.h" 15 | #include 16 | 17 | class DFS { 18 | private: 19 | map nodeMarks_; 20 | basicGraph::bGraph* graph_; 21 | 22 | string tabs(unsigned int level) { 23 | string tab_str = ""; 24 | for (unsigned int i = 0; i < level; i++) tab_str += " "; 25 | return tab_str; 26 | } 27 | 28 | void resetMarks() { 29 | set::iterator niter = graph_->nodeBegin(); 30 | for (; niter != graph_->nodeEnd(); niter++) { 31 | const basicGraph::bNode* node = *niter; 32 | DFS::nodeMarks_[node] = basicGraph::NOT_VISITED; 33 | } 34 | return; 35 | } 36 | 37 | void search_int(const basicGraph::bNode* src, unsigned int level = 0) 38 | { 39 | cout << tabs(level++) << src->name() << " visiting" << endl; 40 | DFS::nodeMarks_[src] = basicGraph::VISITING; 41 | 42 | set::iterator niter = src->edgeBegin(); 43 | for (; niter != src->edgeEnd(); niter++) { 44 | const basicGraph::bNode* nextNode = (*niter)->otherNode(src); 45 | if (DFS::nodeMarks_[nextNode] == basicGraph::NOT_VISITED) 46 | search_int(nextNode); 47 | } 48 | 49 | DFS::nodeMarks_[src] = basicGraph::VISITED; 50 | cout << tabs(level--) << src->name() << " visited." << endl; 51 | } 52 | 53 | void ts_visit(const basicGraph::bNode* src, vector>& container, unsigned int level=0) 54 | { 55 | if (DFS::nodeMarks_[src] == basicGraph::VISITED) 56 | return; 57 | 58 | if (DFS::nodeMarks_[src] == basicGraph::VISITING) 59 | { 60 | cerr << "Error: cycle deteceted at node " << src->name() << ". Topological sorting abandoned.\n"; 61 | return; 62 | } 63 | 64 | DFS::nodeMarks_[src] = basicGraph::VISITING; 65 | 66 | set::iterator niter = src->edgeBegin(); 67 | for (; niter != src->edgeEnd(); niter++) { 68 | const basicGraph::bNode* nextNode = (*niter)->otherNode(src); 69 | ts_visit(nextNode, container, level+1); 70 | } 71 | 72 | DFS::nodeMarks_[src] = basicGraph::VISITED; 73 | container[level].push_back(src); 74 | 75 | return; 76 | } 77 | public: 78 | 79 | DFS(basicGraph::bGraph* graph) : graph_(graph) {} 80 | 81 | void search(const basicGraph::bNode* src) 82 | { 83 | if (!src || !graph_) { 84 | if (!src) cerr << "Error: source node not in the graph."; 85 | if (!graph_) cerr << "Error: graph not found."; 86 | return; 87 | } 88 | 89 | resetMarks(); 90 | 91 | search_int(src); 92 | 93 | return; 94 | } 95 | 96 | // input : a directed acyclic graph with input node. 97 | // output : levelized queues sorted by dependency. 98 | // algorithm: reverse order of DFS's finishing times. 99 | void topological_sort() 100 | { 101 | if ( !graph_) { 102 | if (!graph_) cerr << "Error: graph not found."; 103 | return; 104 | } 105 | // works only on DAGs 106 | if (!graph_->directed()) { 107 | cerr << "Error: topological sort works only on directed graphs.\n"; 108 | return; 109 | } 110 | 111 | const unsigned int MAX_LEVEL = graph_->nNodes(); 112 | vector> levelized_container(MAX_LEVEL); 113 | set::iterator niter = graph_->nodeBegin(); 114 | for (; niter != graph_->nodeEnd(); niter++) 115 | { 116 | const basicGraph::bNode* src = *niter; 117 | if (DFS::nodeMarks_[src] != basicGraph::VISITED) 118 | ts_visit(src, levelized_container); 119 | } 120 | 121 | // print levelized queues. 122 | for (size_t level = 0; level < MAX_LEVEL; level++) { 123 | if (levelized_container[level].size() == 0) 124 | continue; 125 | 126 | cout << "level " << level + 1 << " : "; 127 | for (size_t i = 0; i < levelized_container[level].size(); i++) 128 | { 129 | cout << levelized_container[level][i]->name() << " "; 130 | } 131 | cout << "\n"; 132 | } 133 | 134 | return; 135 | } 136 | }; 137 | 138 | #endif -------------------------------------------------------------------------------- /src/scc.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | 7 | // Strongly Connected Components: 8 | // A graph is said to be strongly connected or diconnected if every vertex 9 | // is reachable from every other vertex. 10 | // 11 | // Reference: https://en.wikipedia.org/wiki/Strongly_connected_component 12 | // https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm 13 | 14 | #ifndef GRAPH_SCC_H 15 | #define GRAPH_SCC_H 16 | 17 | #pragma once 18 | #include "transpose.h" 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | 24 | namespace SCC { 25 | map nodeMarks_; 26 | void resetMarks(const basicGraph::bGraph* graph) { 27 | set::iterator niter = graph->nodeBegin(); 28 | for (; niter != graph->nodeEnd(); niter++) { 29 | const basicGraph::bNode* node = *niter; 30 | SCC::nodeMarks_[node] = basicGraph::NOT_VISITED; 31 | } 32 | return; 33 | } 34 | 35 | // Algorithm: 36 | // 1. For each vertex u of the graph, mark u as unvisited.Let stack_ be empty. 37 | // 2. For each vertex u of the graph do Visit(u), where Visit(u) is the recursive subroutine : 38 | // If u is unvisited then : 39 | // 1. Mark u as visited. 40 | // 2. For each out - neighbour v of u, do Visit(v). 41 | // 3. Prepend u to stack_. 42 | // 3. Transpose graph. 43 | // 4. For each element u of stack_ in order, 44 | // If u has not been assigned to a component then : 45 | // 1. explore all vertices connected to u with DFS and assign them to SCC group. 46 | // 47 | 48 | class kosaraju { 49 | private: 50 | const basicGraph::bGraph* graph_; 51 | vector < vector > listSCC_; 52 | stack stack_; 53 | 54 | // fill up the stack in the reverse order or finishing time. 55 | void first_dfs_pass(const basicGraph::bNode* src) 56 | { 57 | if (SCC::nodeMarks_[src] == basicGraph::VISITED) 58 | return; 59 | if (SCC::nodeMarks_[src] == basicGraph::VISITING) // detected cycle. 60 | return; 61 | SCC::nodeMarks_[src] = basicGraph::VISITING; 62 | 63 | set::iterator niter = src->edgeBegin(); 64 | for (; niter != src->edgeEnd(); niter++) { 65 | const basicGraph::bNode* nextNode = (*niter)->otherNode(src); 66 | if (SCC::nodeMarks_[nextNode] == basicGraph::NOT_VISITED) 67 | first_dfs_pass(nextNode); 68 | } 69 | 70 | SCC::nodeMarks_[src] = basicGraph::VISITED; 71 | stack_.push(src); 72 | } 73 | 74 | 75 | bool second_dfs_pass(const basicGraph::bNode* src, vector& sccGroup) 76 | { 77 | if (SCC::nodeMarks_[src] == basicGraph::VISITED) 78 | return false; 79 | if (SCC::nodeMarks_[src] == basicGraph::VISITING) // detected cycle. 80 | return false; 81 | SCC::nodeMarks_[src] = basicGraph::VISITING; 82 | 83 | set::iterator niter = src->edgeBegin(); 84 | for (; niter != src->edgeEnd(); niter++) { 85 | const basicGraph::bNode* nextNode = (*niter)->otherNode(src); 86 | if (SCC::nodeMarks_[nextNode] == basicGraph::NOT_VISITED) 87 | second_dfs_pass(nextNode, sccGroup); 88 | } 89 | 90 | SCC::nodeMarks_[src] = basicGraph::VISITED; 91 | sccGroup.push_back(src); 92 | 93 | return true; // found SCC 94 | } 95 | 96 | void build_dfs_stack() 97 | { 98 | set::iterator niter = graph_->nodeBegin(); 99 | for (; niter != graph_->nodeEnd(); niter++) 100 | { 101 | first_dfs_pass(*niter); 102 | } 103 | return; 104 | } 105 | 106 | void build_scc_list() 107 | { 108 | size_t scc_index = 0; 109 | while (!stack_.empty()) 110 | { 111 | if ( second_dfs_pass(stack_.top(), listSCC_[scc_index]) ) 112 | scc_index++; 113 | stack_.pop(); 114 | } 115 | return; 116 | } 117 | public: 118 | kosaraju(const basicGraph::bGraph* graph) : graph_(graph), listSCC_(graph->nNodes()) 119 | {} 120 | void build() 121 | { 122 | if (!graph_->directed()) 123 | { 124 | cerr << "Error: Strongly connected can not be determined for undirected graph.\n"; 125 | return; 126 | } 127 | 128 | resetMarks(graph_); 129 | build_dfs_stack(); 130 | 131 | transpose reverse(true); 132 | reverse.build(graph_); 133 | 134 | resetMarks(graph_); 135 | build_scc_list(); 136 | 137 | // fix directed graph before leaving. 138 | reverse.build(graph_); 139 | return; 140 | } 141 | void print() 142 | { 143 | for (size_t i = 0; i < listSCC_.size(); i++) 144 | { 145 | if (listSCC_[i].size() == 0) 146 | continue; 147 | 148 | cout << "SCC Group " << i << " : "; 149 | for (size_t j = 0; j < listSCC_[i].size(); j++) 150 | { 151 | cout << listSCC_[i][j]->name() << " "; 152 | } 153 | cout << "\n"; 154 | } 155 | return; 156 | } 157 | }; 158 | }; 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /src/bgaMain.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | // basic Graph Algorithms 8 | // This file contains the 'main' function to start the execution 9 | // with a basic text user interface for all algorithms. 10 | // 11 | 12 | #include "dvector.h" 13 | #include "scc.h" 14 | #include "dfs.h" 15 | #include "mst.h" 16 | #include "shortestPath.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | template 23 | T dvector::NULL_DATA = 0; 24 | 25 | using namespace std; 26 | 27 | int main(int argc, char** argv) 28 | { 29 | if (argc < 2) { 30 | cerr << "Error: no input graph given.\n"; 31 | return 1; 32 | } 33 | basicGraph::bGraph* graph = basicGraph::bGraph::readBasicGraph(argv[1]); 34 | if (!graph) { 35 | cerr << "Error: graph could not be built.\n"; 36 | return 1; 37 | } 38 | cout << "created graph with " << graph->nNodes() << " nodes and " << graph->nEdges() << " edges.\n"; 39 | cout << "type \'help' for more options\n"; 40 | 41 | while (true) { 42 | string line, token; 43 | cout << ">> "; 44 | getline(cin, line); 45 | 46 | vector tokens; 47 | stringstream stokens(line); 48 | 49 | if (line.empty()) continue; 50 | 51 | // Tokenizing w.r.t. space ' ' 52 | while (getline(stokens, token, ' ')) tokens.push_back(token); 53 | 54 | string choice = tokens[0]; 55 | 56 | transform(choice.begin(), choice.end(), choice.begin(), ::tolower); 57 | if (choice == "help" ) 58 | { 59 | cout << " help\n"; 60 | cout << " print\n"; 61 | cout << " transpose\n"; 62 | cout << " scc []\n"; 63 | cout << " search \n"; // dfs search tree 64 | cout << " sort \n"; // levelize or topological sort 65 | cout << " mst [prim|kruskal]\n"; // minimal spanning tree 66 | cout << " path []\n"; // Path from source to one or all vertices 67 | cout << " quit\n"; 68 | } 69 | else if (choice == "print") 70 | { 71 | graph->print(); 72 | cout << "\n"; 73 | } 74 | else if (choice == "transpose") 75 | { 76 | transpose reverse(false); 77 | const basicGraph::bGraph* new_graph = reverse.build(graph); 78 | new_graph->print(); 79 | delete new_graph; 80 | } 81 | else if (choice == "scc") 82 | { 83 | SCC::kosaraju sccBuilder(graph); 84 | sccBuilder.build(); 85 | sccBuilder.print(); 86 | } 87 | else if (choice == "search") 88 | { 89 | if (tokens.size() < 2) { 90 | cerr << "Error: supply search node and try again.\n"; 91 | continue; 92 | } 93 | string node = tokens[1]; 94 | const basicGraph::bNode* src = graph->findNode(node); 95 | if (!src) { 96 | cerr << "Error: node " << node << "not found in the graph.\n"; 97 | } 98 | else { 99 | DFS traverse(graph); 100 | traverse.search(src); 101 | } 102 | } 103 | else if (choice == "sort") 104 | { 105 | DFS traverse(graph); 106 | traverse.topological_sort(); 107 | } 108 | else if (choice == "mst") 109 | { 110 | string algo = tokens.size() < 2 ? "kruskal" : tokens[1]; 111 | if (algo == "kruskal") 112 | { 113 | MST::kruskal mst(graph); 114 | mst.build(); 115 | mst.print(); 116 | } 117 | else if (algo == "prim") 118 | { 119 | MST::prim mst(graph); 120 | mst.build(); 121 | mst.print(); 122 | } 123 | else { 124 | cerr << "Error: invalid option " << algo << ". Options are\n"; 125 | cerr << " prim.\n"; 126 | cerr << " kruskal.\n"; 127 | } 128 | } 129 | else if (choice == "path") 130 | { 131 | if (tokens.size() < 2) { 132 | cerr << "Error: supply search node and try again.\n"; 133 | continue; 134 | } 135 | string node1 = tokens[1]; 136 | string node2 = tokens.size() > 2 ? tokens[2] : "" ; 137 | const basicGraph::bNode* src = graph->findNode(node1); 138 | if (!src) 139 | { 140 | cerr << "Error: node " << node1 << "not found in the graph.\n"; 141 | continue; 142 | } 143 | const basicGraph::bNode* dst = node2.length() ? graph->findNode(node2) : nullptr; 144 | if (node2.size() && !dst) 145 | { 146 | cerr << "Error: node " << node2 << "not found in the graph.\n"; 147 | cerr << " will use single source path algorithm.\n"; 148 | } 149 | 150 | if ( dst == nullptr ) 151 | { 152 | // path to all nodes from source 153 | short_paths::dijkstra single_source_path(src, graph); 154 | single_source_path.build(); 155 | single_source_path.print(); 156 | } 157 | else 158 | { 159 | // a_star search for source and destination. 160 | short_paths::aStar src_dst_path(src, graph); 161 | src_dst_path.build(dst); 162 | src_dst_path.print(dst); 163 | } 164 | } 165 | else if (choice == "quit" || choice == "exit") 166 | { 167 | cout << ".. good bye.\n"; 168 | break; 169 | } 170 | else 171 | { 172 | cerr << "Error: option " << choice << " not recognized.\n"; 173 | } 174 | } 175 | 176 | delete graph; 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /src/heap.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2006 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | // 6 | // Description: This is a simple heap container missing in STL. 7 | // Two simple classes have (MinHeap and MaxHeap) have 8 | // been provided. Interface is simple- push and pop. 9 | // this container can be inherited to create more 10 | // complex container like Treap. 11 | // This container support all vector interface except push_back 12 | // pop_back, insert, erase and resize, which (if allowed) destroy 13 | // the heap property. 14 | // Example: 15 | // MinHeap test_heap; 16 | // test_heap.push(2.0); 17 | // std::cout << test_heap.pop(); 18 | // 19 | // NOTE:It requires assignment operator and comparision operator 20 | // (used in functional header) for more comples classes. 21 | /////////////////////////////////////////////////////////////////// 22 | 23 | #ifndef _HEAP_H 24 | #define _HEAP_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | //using namespace std; 32 | 33 | template 34 | class Heap : public std::vector { 35 | #define STD_ITER std::iterator 36 | typedef typename std::vector::size_type size_type; 37 | protected: 38 | COMPARE _compare; 39 | private: 40 | inline void swap(size_t i, size_t j); 41 | void heapify_up(size_t index); 42 | void heapify_down(size_t index); 43 | 44 | // invalid vector public functions, which can destroy heap property. 45 | void push_back(const T&) { assert("method push_back is not supported.\n"); } 46 | void pop_back() { assert("method pop_back is not supported.\n"); } 47 | STD_ITER insert(STD_ITER, const T&) { assert("method insert is not supported.\n"); } 48 | template void 49 | insert(STD_ITER, InputIterator, InputIterator) { assert("method insert is not supported.\n"); } 50 | void insert(STD_ITER, size_type, const T&) { assert("method insert is not supported.\n"); } 51 | STD_ITER erase(STD_ITER) { assert("method erase is not supported.\n"); } 52 | STD_ITER erase(STD_ITER, STD_ITER) { assert("method erase is not supported.\n"); } 53 | void resize(size_type) { assert("method resize is not supported.\n"); } 54 | void resize(size_type, const T&) { assert("method resize is not supported.\n"); } 55 | public: 56 | Heap() {} 57 | void push(const T& element); 58 | bool pop(T&); 59 | bool erase(T&); 60 | bool exists(T&); 61 | bool index(T&, size_t&); 62 | inline size_t parent_index(size_t i) { return (i - 1) >> 1; } 63 | inline size_t left_index(size_t i) { return (i << 1) + 1; } 64 | inline size_t right_index(size_t i) { return (i << 1) + 2; } 65 | void debug(); 66 | }; 67 | 68 | template 69 | inline void 70 | Heap::swap(size_t i, size_t j) 71 | { 72 | assert(i != j && i < this->size() && j < this->size()); 73 | T tmp = (*this)[i]; //requires assignement operator. 74 | (*this)[i] = (*this)[j]; 75 | (*this)[j] = tmp; 76 | } 77 | 78 | template 79 | inline void 80 | Heap::heapify_up(size_t child) 81 | { 82 | size_t prnt = parent_index(child); 83 | while (child && _compare((*this)[child], (*this)[prnt])) { 84 | swap(child, prnt); 85 | child = prnt; 86 | prnt = parent_index(child); 87 | } 88 | } 89 | 90 | template 91 | inline void 92 | Heap::heapify_down(size_t prnt) 93 | { 94 | if (!this->size()) 95 | return; 96 | size_t lchild = left_index(prnt); 97 | size_t rchild = right_index(prnt); 98 | 99 | size_t new_prnt = prnt; 100 | if (lchild < this->size() && _compare((*this)[lchild], (*this)[prnt])) 101 | new_prnt = lchild; 102 | if (rchild < this->size() && _compare((*this)[rchild], (*this)[new_prnt])) 103 | new_prnt = rchild; 104 | if (new_prnt != prnt) { 105 | swap(new_prnt, prnt); 106 | heapify_down(new_prnt); 107 | } 108 | } 109 | 110 | template 111 | void 112 | Heap::push(const T& element) { 113 | size_t n = this->size(); 114 | ((std::vector*)this)->push_back(element); 115 | heapify_up(n); 116 | } 117 | 118 | template 119 | bool 120 | Heap::pop(T& popped) { 121 | if (!this->size()) return false; 122 | 123 | popped = (*this)[0]; 124 | (*this)[0] = (*this)[this->size() - 1]; 125 | ((std::vector*)this)->pop_back(); 126 | heapify_down(0); 127 | return true; 128 | } 129 | 130 | template 131 | bool 132 | Heap::index(T& element, size_t& idx) { 133 | 134 | for (size_t i = 0; i < this->size(); i++) 135 | { 136 | if ((*this)[i] == element) 137 | { 138 | idx = i; 139 | return true; 140 | } 141 | } 142 | return false; 143 | 144 | } 145 | 146 | template 147 | bool 148 | Heap::erase(T& element) { 149 | if (!this->size()) return false; 150 | 151 | size_t idx; 152 | if (index(element, idx)) 153 | { 154 | (*this)[idx] = (*this)[this->size() - 1]; 155 | ((std::vector*)this)->pop_back(); 156 | heapify_down(idx); 157 | return true; 158 | } 159 | return false; 160 | } 161 | 162 | template 163 | bool 164 | Heap::exists(T& element) { 165 | if (!this->size()) return false; 166 | 167 | return (std::find(this->begin(), this->end(), element) != this->end()); 168 | } 169 | 170 | template 171 | class MinHeap : public Heap > {}; 172 | 173 | template 174 | class MaxHeap : public Heap > {}; 175 | 176 | #endif -------------------------------------------------------------------------------- /src/graph.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | // Reference: Introduction to Algorithms 8 | // by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein 9 | 10 | #ifndef BASIC_GRAPH_H 11 | #define BASIC_GRAPH_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | namespace basicGraph { 22 | typedef enum { NOT_VISITED = 1, VISITING = 2, VISITED = 3 } NODE_MARKS; 23 | class bNode; 24 | class bEdge; 25 | 26 | static struct nodeCompare 27 | { 28 | bool operator() (const bNode* n1, const bNode* n2) const; 29 | } nodeCmp; 30 | 31 | static struct edgeCompare 32 | { 33 | bool operator() (const bEdge* d1, const bEdge* d2) const; 34 | } edgeCmp; 35 | 36 | void tokenizeLine(char* line, std::vector &tokens); 37 | 38 | class bNode { 39 | private: 40 | string name_; 41 | set edgelist_; 42 | public: 43 | bNode(string name) : name_(name) {} 44 | string name() const { return name_; } 45 | bool addEdge(const bEdge* e) { 46 | if (!e || edgelist_.find(e) != edgelist_.end()) 47 | return false; 48 | edgelist_.insert(e); 49 | return true; 50 | } 51 | void clearEdgeList() { edgelist_.clear(); } 52 | set::iterator edgeBegin() const { return edgelist_.begin(); } 53 | set::iterator edgeEnd() const { return edgelist_.end(); } 54 | }; 55 | 56 | class bEdge { 57 | private: 58 | const bNode* n1_; // from node for directd graphs 59 | const bNode* n2_; // to node for directed graphs 60 | public: 61 | static const long INVALID_WEIGHT; 62 | bEdge(const bNode* n1 = 0x0, const bNode* n2 = 0x0) 63 | : n1_(n1), n2_(n2) 64 | {} 65 | string name() const 66 | { 67 | if (n1_ && n2_) 68 | return n1_->name() + " " + n2_->name(); 69 | else if (n1_) 70 | return n1_->name(); 71 | else if (n2_) 72 | return n2_->name(); 73 | else 74 | return " "; 75 | } 76 | const bNode* n1() const { return n1_; } 77 | const bNode* n2() const { return n2_; } 78 | virtual bool hasWeight() const {return false; } 79 | void swap_nodes() // used to compute transpose of graph 80 | { 81 | const bNode* tmp = n1_; 82 | n1_ = n2_; 83 | n2_ = tmp; 84 | } 85 | const bNode* otherNode(const bNode* n) const 86 | { 87 | if (n1_ == n) 88 | return n2_; 89 | else if (n2_ == n) 90 | return n1_; 91 | else 92 | return nullptr; 93 | } 94 | virtual void print() const 95 | { 96 | cout << name() << "\n"; 97 | } 98 | virtual ~bEdge() {} 99 | }; 100 | class bWeightedEdge : public bEdge { 101 | private: 102 | const size_t weight_; // weight of the edge. 103 | public: 104 | bWeightedEdge(const bNode* n1=0x0, const bNode* n2=0x0, const size_t w=INVALID_WEIGHT) 105 | : bEdge(n1, n2), weight_(w) 106 | {} 107 | virtual bool hasWeight() const { return true; } 108 | const size_t weight() const { return weight_; } 109 | virtual void print() const 110 | { 111 | stringstream wt; 112 | if (weight_ != INVALID_WEIGHT) 113 | wt << " " << weight_; 114 | 115 | cout << name() << wt.str() << "\n"; 116 | } 117 | virtual ~bWeightedEdge() {} 118 | }; 119 | 120 | class bGraph { 121 | private: 122 | bool isDirected_; 123 | set nodeset_; 124 | set edgeset_; 125 | public: 126 | bGraph(bool directed=false) : isDirected_(directed) {} 127 | bGraph(const bGraph& other); 128 | void setDirected(bool directed) { isDirected_ = directed; } 129 | bool directed() const { return isDirected_; } 130 | const bNode* findNode(string name) { 131 | if (name.empty()) 132 | return nullptr; 133 | 134 | bNode nd(name); 135 | set::iterator iter = nodeset_.find(&nd); 136 | return (iter != nodeset_.end() ? *iter : nullptr); 137 | } 138 | bNode* addNode(string name) { 139 | const bNode* n = findNode(name); 140 | if (!n) { 141 | n = new bNode(name); 142 | nodeset_.insert(n); 143 | } 144 | return const_cast(n); 145 | } 146 | const bEdge* findEdge(const bNode* n1, const bNode* n2) { 147 | if (!n1 || !n2) 148 | return nullptr; 149 | 150 | bEdge edge12(n1, n2); 151 | set::iterator iter = edgeset_.find(&edge12); 152 | if (!isDirected_ && iter == edgeset_.end()) { 153 | bEdge edge21(n2, n1); 154 | iter = edgeset_.find(&edge21); 155 | } 156 | return (iter != edgeset_.end() ? *iter : nullptr); 157 | } 158 | const bEdge* addEdge(const bNode* n1, const bNode* n2, size_t weight=bEdge::INVALID_WEIGHT) { 159 | if (!n1 || !n2) 160 | return nullptr; 161 | 162 | const bEdge* e = findEdge(n1, n2); 163 | if (!e) { 164 | e = weight == bEdge::INVALID_WEIGHT ? 165 | new bEdge(n1, n2) : 166 | new bWeightedEdge(n1, n2, weight); 167 | edgeset_.insert(e); 168 | } 169 | return e; 170 | } 171 | void addNodesAndEdge(string, string, size_t); 172 | size_t nNodes() const { return nodeset_.size(); } 173 | size_t nEdges() const { return edgeset_.size(); } 174 | 175 | // graph access methods 176 | set::iterator nodeBegin() const { return nodeset_.begin(); } 177 | set::iterator nodeEnd() const { return nodeset_.end(); } 178 | set::iterator edgeBegin() const { return edgeset_.begin(); } 179 | set::iterator edgeEnd() const { return edgeset_.end(); } 180 | 181 | void print() const; 182 | static bGraph* readBasicGraph(string filename); 183 | ~bGraph(); 184 | 185 | }; 186 | } 187 | 188 | #endif //BASIC_GRAPH_H 189 | -------------------------------------------------------------------------------- /src/mst.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | // 7 | // 8 | // Minimal Spanning Trees argorithms. 9 | // 10 | 11 | #ifndef GRAPH_MST_H 12 | #define GRAPH_MST_H 13 | 14 | #include 15 | #include "graph.h" 16 | #include "heap.h" 17 | 18 | using namespace std; 19 | 20 | namespace MST { 21 | 22 | struct treeNode { 23 | public: 24 | const basicGraph::bNode* node_; // to node in graph node 25 | treeNode* parent_; // from node in graph node 26 | size_t iset_; // index of set 27 | size_t weight_; // weight of the edge from parent to this node. 28 | treeNode(const basicGraph::bNode* node, size_t i = 0, size_t wt = 0) : 29 | node_(node), parent_(nullptr), iset_(i), weight_(wt) 30 | {} 31 | void setParent(treeNode* other, size_t wt) { 32 | other->parent_ = this; 33 | other->weight_ = wt; 34 | } 35 | }; 36 | struct treeNodeCompare 37 | { 38 | bool operator() (const treeNode* tn1, const treeNode* tn2) const 39 | { 40 | return basicGraph::nodeCmp.operator()(tn1->node_, tn2->node_); 41 | } 42 | }; 43 | 44 | class minTree { 45 | public: 46 | set tree_; 47 | virtual void build() = 0; 48 | bool nodePartOfMST(const basicGraph::bNode* gnode) 49 | { 50 | treeNode tmpTreeNode = treeNode(gnode); 51 | return tree_.find(&tmpTreeNode) != tree_.end(); 52 | } 53 | treeNode* getTreeNode(const basicGraph::bNode* gnode) 54 | { 55 | treeNode tmpTreeNode = treeNode(gnode); 56 | set::iterator niter = tree_.find(&tmpTreeNode); 57 | return niter == tree_.end() ? nullptr : *niter; 58 | } 59 | void print(bool edges_only=false) 60 | { 61 | set::iterator niter = tree_.begin(); 62 | for (; niter != tree_.end(); niter++) 63 | { 64 | treeNode* tnode = (*niter); 65 | if (!edges_only || tnode->parent_) 66 | { 67 | cout << (tnode->parent_ ? tnode->parent_->node_->name() : "root") << " " 68 | << tnode->node_->name() << " " 69 | << tnode->weight_; 70 | // cout << " (set " << tnode->iset_ << ")"; 71 | cout << "\n"; 72 | } 73 | } 74 | } 75 | ~minTree() 76 | { 77 | set::iterator niter = tree_.begin(); 78 | for (; niter != tree_.end(); niter++) 79 | delete (*niter); 80 | tree_.clear(); 81 | } 82 | }; 83 | 84 | // #################### 85 | // Kruskal's algorithm 86 | // #################### 87 | // Kruskal's algorithm is a minimum-spanning-tree algorithm which finds an edge 88 | // of the least possible weight that connects any two trees in the forest. It 89 | // is a greedy algorithm in graph theory as it finds a minimum spanning tree 90 | // for a connected weighted graph adding increasing cost arcs at each step. 91 | // 92 | // Note: This only works for undirected graphs. 93 | 94 | // Pseudo Code: 95 | // KRUSKAL-MST(G, w) 96 | // T: = Ø 97 | // for each vertex u in V 98 | // MAKE - SET(tree_, u) 99 | // end for 100 | // for each edge(u, v) in E (sortedEdges) in order of nondecreasing weight 101 | // if FIND - SET(tree_, u) != FIND - SET(tree_, v) 102 | // UNION - SET(tree_, u, v) 103 | // T : = T U{ (u,v) } 104 | // end for 105 | // return T 106 | 107 | class kruskal : public minTree { 108 | private: 109 | const basicGraph::bGraph* graph_; 110 | 111 | // unionSet is used to combine two trees to one by adding an 112 | // edge between two trees with nodes in two disjoint sets. 113 | // TODO: complexity is linear. Can be reduced to logarithmic 114 | void unionSet(treeNode* u, treeNode* v, size_t wt, bool directed) 115 | { 116 | size_t v_iset = v->iset_; 117 | set::iterator niter = tree_.begin(); 118 | for (; niter != tree_.end(); niter++) 119 | { 120 | treeNode* tnode = *niter; 121 | if (tnode->iset_ == v_iset) 122 | { 123 | tnode->iset_ = u->iset_; 124 | } 125 | } 126 | // change v's parent-child relationship for undirected graphs. 127 | if (!directed && v->parent_ != nullptr) 128 | { 129 | v->parent_->parent_ = v; 130 | v->parent_->weight_ = v->weight_; 131 | } 132 | 133 | // set v's parent to u. 134 | u->setParent(v, wt); 135 | 136 | return; 137 | } 138 | public: 139 | kruskal(const basicGraph::bGraph* graph) : minTree(), graph_(graph) 140 | {} 141 | ~kruskal() 142 | {} 143 | 144 | // build MST. 145 | void build() 146 | { 147 | if (!graph_) 148 | { 149 | cerr << "Error: graph not found."; 150 | return; 151 | } if (graph_->nNodes() == 0) 152 | { 153 | cerr << "Error: no nodes found in the graph."; 154 | return; 155 | } 156 | 157 | if (graph_->directed()) 158 | cerr << "Warning: Kruskal's algorithm may produce invalid tree or \n" 159 | << " more than one spanning multitree on directed graphs.\n"; 160 | 161 | 162 | // create an empty tree node and add it to set. 163 | size_t set_index = 1; 164 | set::iterator niter; 165 | for (niter = graph_->nodeBegin(); niter != graph_->nodeEnd(); niter++) 166 | { 167 | tree_.insert(new treeNode(*niter, set_index++)); 168 | } 169 | 170 | vector sortedEdges; 171 | set::iterator eiter; 172 | for (eiter = graph_->edgeBegin(); eiter != graph_->edgeEnd(); eiter++) 173 | { 174 | sortedEdges.push_back(*eiter); 175 | } 176 | sort(sortedEdges.begin(), sortedEdges.end(), basicGraph::edgeCmp); 177 | 178 | for (size_t i = 0; i < sortedEdges.size(); i++) 179 | { 180 | const basicGraph::bNode* u = sortedEdges[i]->n1(); 181 | const basicGraph::bNode* v = sortedEdges[i]->n2(); 182 | treeNode tmpUNode = treeNode(u); 183 | treeNode tmpVNode = treeNode(v); 184 | auto uset = tree_.find(&tmpUNode); 185 | auto vset = tree_.find(&tmpVNode); 186 | if (uset != tree_.end() && vset != tree_.end() && 187 | (*uset)->iset_ != (*vset)->iset_ ) 188 | { 189 | treeNode* tuset = *uset; 190 | treeNode* tvset = *vset; 191 | unionSet(tuset, tvset, dynamic_cast(sortedEdges[i])->weight(), graph_->directed()); 192 | } 193 | } 194 | } 195 | }; 196 | 197 | 198 | // ################# 199 | // Prim's Algorithm 200 | // ################# 201 | // procedure prim(G,W) 202 | // for i = 1 to n do 203 | // MinHeap[i] ← i 204 | // WhereInHeap[i] ← i 205 | // d[i] ← ∞ 206 | // outside[i] ← true 207 | // π[i] ← NIL 208 | // end for 209 | // d[1] ← 0 210 | // for i = n downto 1 do 211 | // u ← MinHeap[1] 212 | // MinHeap[1] ← MinHeap(n) 213 | // WhereInHeap[MinHeap[1]] ← SiftDown(MinHeap, 1, n - 1, d) 214 | // for each v ∈ adj[u] do 215 | // if v ∈ outside and W[u, v] < d[v] then 216 | // d[v] ← W[u, v] 217 | // π[v] ← u 218 | // WhereInHeap[v] ← SiftUp(MinHeap, WhereInHeap[v], d) 219 | // end if 220 | // end for 221 | // end for 222 | // end procedure 223 | 224 | class prim : public minTree { 225 | private: 226 | const basicGraph::bGraph* graph_; 227 | 228 | bool nodeNotInMST(treeNode* tn) 229 | { 230 | return tree_.find(tn) == tree_.end(); 231 | } 232 | void addEdgesToHeap(const basicGraph::bNode* node, 233 | Heap& minEdgeHeap) 234 | { 235 | set::iterator eiter = node->edgeBegin(); 236 | for (; eiter != node->edgeEnd(); eiter++) { 237 | if (! nodePartOfMST((*eiter)->n1()) || !nodePartOfMST((*eiter)->n2()) ) 238 | minEdgeHeap.push(dynamic_cast(*eiter)); 239 | } 240 | } 241 | public: 242 | prim(const basicGraph::bGraph* graph) : minTree(), graph_(graph) 243 | {} 244 | // build MST. 245 | void build() 246 | { 247 | if (!graph_) 248 | { 249 | cerr << "Error: graph not found."; 250 | return; 251 | } 252 | if (graph_->nNodes() == 0) 253 | { 254 | cerr << "Error: no nodes found in the graph."; 255 | return; 256 | } 257 | if (graph_->directed()) 258 | { 259 | cerr << "Warning: Prim's algorithm may produce invalid tree or \n" 260 | << " more than one spanning multitree on directed graphs.\n"; 261 | } 262 | 263 | Heap minEdgeHeap; 264 | 265 | // Initialize a tree with a single vertex, chosen arbitrrily from the graph. 266 | set::iterator niter = graph_->nodeBegin(); 267 | const basicGraph::bNode* node = *niter; 268 | tree_.insert(new treeNode(node, 0)); 269 | 270 | // Grow the tree by one edge : of the edges that connect the tree 271 | // to vertices not yet in the tree, find the minimum - weight edge, 272 | // and transfer it to the tree. 273 | 274 | addEdgesToHeap(node, minEdgeHeap); 275 | const basicGraph::bWeightedEdge* minEdge = nullptr; 276 | while (minEdgeHeap.pop(minEdge)) 277 | { 278 | // get the node, not in MST 279 | MST::treeNode* tn1 = getTreeNode(minEdge->n1()); 280 | MST::treeNode* tn2 = getTreeNode(minEdge->n2()); 281 | if (tn1 && tn2==nullptr) 282 | { 283 | tn2 = new treeNode(minEdge->n2()); 284 | tree_.insert(tn2); 285 | tn1->setParent(tn2, minEdge->weight()); 286 | addEdgesToHeap(tn2->node_, minEdgeHeap); 287 | } 288 | else if (tn1==nullptr && tn2) 289 | { 290 | tn1 = new treeNode(minEdge->n1()); 291 | tree_.insert(tn1); 292 | tn2->setParent(tn1, minEdge->weight()); 293 | addEdgesToHeap(tn1->node_, minEdgeHeap); 294 | } 295 | else 296 | { 297 | continue; 298 | } 299 | } 300 | } 301 | }; 302 | } 303 | 304 | #endif 305 | 306 | -------------------------------------------------------------------------------- /src/shortestPath.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2018 Rohit Sharma. All rights reserved. 3 | // This program is free software; you can redistribute it and/or 4 | // modify it under the terms as GNU General Public License. 5 | /////////////////////////////////////////////////////////////////// 6 | 7 | // Dijkstra's algorithm 8 | // given source node in the graph, the algorithm finds the shortest path between that 9 | // node and every other node in the graph. 10 | // It is a single node shortest path and works on both directional and bi-directional path. 11 | // Reference: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm 12 | // 13 | // A-star algorithm 14 | // given source and destination node in the graph, the algorithm finds the shortest path 15 | // between them with exploring as fewer nodes as possible. 16 | // It relied on a heuristic to provide estimation of distance from every node to destination. 17 | // This estimate is used to guide the search (using priority Q) and terminate search. 18 | // It is a single node shortest path and works on both directional and bi-directional path. 19 | // Reference: https://en.wikipedia.org/wiki/A*_search_algorithm 20 | 21 | 22 | #ifndef GRAPH_PATH_H 23 | #define GRAPH_PATH_H 24 | 25 | #pragma once 26 | #include 27 | #include 28 | #include "graph.h" 29 | #include "heap.h" 30 | 31 | using namespace std; 32 | 33 | namespace short_paths { 34 | struct pathNode { 35 | public: 36 | const basicGraph::bNode* node_; // to node in graph node 37 | pathNode* prev_node_; // from node in graph node 38 | size_t dist_; // weight of the edge from parent to this node. 39 | size_t root_dist_; // sum of all dist_ from this node to root. 40 | pathNode(const basicGraph::bNode* node, size_t wt = 0) : 41 | node_(node), prev_node_(nullptr), dist_(wt), root_dist_(LONG_MAX) 42 | {} 43 | void setParent(pathNode* other, size_t dist, size_t root_dist) { 44 | other->prev_node_ = this; 45 | other->dist_ = dist; 46 | other->root_dist_ = root_dist; 47 | } 48 | }; 49 | struct pathNodeCompare 50 | { 51 | bool operator() (const pathNode* tn1, const pathNode* tn2) const 52 | { 53 | return basicGraph::nodeCmp.operator()(tn1->node_, tn2->node_); 54 | } 55 | }; 56 | 57 | class path { 58 | private: 59 | pathNode* src_; // source for the path. 60 | set tree_; // path 61 | 62 | public: 63 | path(pathNode* src) : src_(src) 64 | { 65 | tree_.insert(src); 66 | src->root_dist_ = 0; 67 | } 68 | pathNode* src() { return src_; } 69 | pathNode* retrievePathNode(const basicGraph::bNode* gnode) 70 | { 71 | pathNode tmpNode = pathNode(gnode); 72 | set::iterator niter = tree_.find(&tmpNode); 73 | return niter == tree_.end() ? nullptr : *niter; 74 | } 75 | pathNode* retrieveOrAddPathNode(const basicGraph::bNode* gnode) 76 | { 77 | pathNode* pnode = retrievePathNode(gnode); 78 | if (pnode == nullptr) 79 | { 80 | pnode = new pathNode(gnode); 81 | tree_.insert(pnode); 82 | } 83 | return pnode; 84 | } 85 | void print_all_paths() 86 | { 87 | 88 | cout << "nd dist_from_src edge\n"; 89 | cout << "== ============= ====\n"; 90 | set::iterator niter = tree_.begin(); 91 | for (; niter != tree_.end(); niter++) 92 | { 93 | pathNode* tnode = (*niter); 94 | cout << tnode->node_->name() << " " << tnode->root_dist_ 95 | << " [" << (tnode->prev_node_ ? tnode->prev_node_->node_->name() : "none") 96 | << " " << tnode->node_->name() << " " << tnode->dist_ << "]\n"; 97 | } 98 | } 99 | 100 | void print_path(const basicGraph::bNode* dst) 101 | { 102 | pathNode* tnode = retrievePathNode(dst); 103 | 104 | vector src_2_dst; 105 | for (; tnode != src_ ; tnode = tnode->prev_node_) 106 | { 107 | if (tnode == nullptr) 108 | { 109 | cout << "no path found.\n"; 110 | return; 111 | } 112 | src_2_dst.push_back(tnode); 113 | } 114 | src_2_dst.push_back(src_); 115 | 116 | cout << "start"; 117 | for (int i=src_2_dst.size()-1; i>=0; i--) 118 | cout << " --(" << src_2_dst[i]->dist_ << ")--> " << src_2_dst[i]->node_->name() ; 119 | cout << " ...done.\n"; 120 | cout << "distance covered is " << src_2_dst[0]->root_dist_ << ".\n"; 121 | } 122 | ~path() 123 | { 124 | set::iterator niter = tree_.begin(); 125 | for (; niter != tree_.end(); niter++) 126 | delete (*niter); 127 | tree_.clear(); 128 | } 129 | }; 130 | 131 | struct pqNode { 132 | public: 133 | const basicGraph::bNode* node_; 134 | size_t min_dist_; 135 | 136 | pqNode() : node_(nullptr), min_dist_(LONG_MAX) 137 | {} 138 | pqNode(const basicGraph::bNode* node, size_t dist=LONG_MAX) : node_(node), min_dist_(dist) 139 | { 140 | assert(node); 141 | } 142 | bool operator==(const pqNode& other) 143 | { 144 | return other.node_ == node_; 145 | } 146 | }; 147 | class pqNodeCompare { 148 | public: 149 | bool operator() (const pqNode& tn1, const pqNode& tn2) const 150 | { 151 | return tn1.min_dist_ < tn2.min_dist_; 152 | } 153 | }; 154 | 155 | //function Dijkstra(Graph, source) : 156 | // create vertex set PQ 157 | // for each vertex v in Graph : // Initialization 158 | // dist[v] ← INFINITY // Unknown distance from source to v 159 | // prev[v] ← UNDEFINED // Previous node in optimal path from source 160 | // 161 | // dist[source] ← 0 // Distance from source to source 162 | // add source to PQ 163 | // while PQ is not empty: 164 | // u ← vertex in PQ with min dist[u] // Node with the least distance 165 | // // will be selected first 166 | // remove u from PQ 167 | // 168 | // for each neighbor v of u : 169 | // alt ← dist[u] + length(u, v) 170 | // if alt < dist[v] : // A shorter path to v has been found 171 | // dist[v] ← alt 172 | // prev[v] ← u 173 | // add v to PQ 174 | // 175 | // return dist[], prev[] 176 | 177 | 178 | class dijkstra { 179 | private: 180 | const basicGraph::bGraph* graph_; 181 | path shortest_path_; 182 | 183 | size_t node_min_edge(const basicGraph::bNode* node) 184 | { 185 | set::iterator eiter = node->edgeBegin(); 186 | return eiter != node->edgeEnd() ? 187 | dynamic_cast(*eiter)->weight() : 188 | 0; 189 | } 190 | public: 191 | dijkstra(const basicGraph::bNode* src, const basicGraph::bGraph* graph) : 192 | graph_(graph), shortest_path_(new pathNode(src)) 193 | {} 194 | void build() 195 | { 196 | Heap PQ; // priority queue 197 | 198 | set::iterator niter; 199 | for (niter = graph_->nodeBegin(); niter != graph_->nodeEnd(); niter++) 200 | { 201 | shortest_path_.retrieveOrAddPathNode(*niter); 202 | } 203 | 204 | 205 | pqNode qnode(shortest_path_.src()->node_, 0); // node in priority queue 206 | PQ.push(qnode); 207 | 208 | while (PQ.pop(qnode)) 209 | { 210 | pathNode* pnode = shortest_path_.retrievePathNode(qnode.node_); 211 | assert(pnode); 212 | 213 | set::iterator eiter; 214 | for (eiter = pnode->node_->edgeBegin(); eiter != pnode->node_->edgeEnd(); eiter++) 215 | { 216 | const basicGraph::bNode* other_gnode = (*eiter)->otherNode(pnode->node_); 217 | size_t dist = dynamic_cast(*eiter)->weight(); 218 | pathNode* other_pnode = shortest_path_.retrievePathNode(other_gnode); 219 | 220 | size_t alt_root_dist = pnode->root_dist_ + dist; 221 | if (alt_root_dist < other_pnode->root_dist_) 222 | { 223 | pnode->setParent(other_pnode, dist, alt_root_dist); 224 | pqNode qnode_next(other_gnode, node_min_edge(other_gnode)); 225 | if ( PQ.exists(qnode_next) == false ) 226 | PQ.push(qnode_next); 227 | } 228 | } 229 | } 230 | return; 231 | } 232 | void print() 233 | { 234 | shortest_path_.print_all_paths(); 235 | } 236 | }; 237 | 238 | 239 | //function aStar (Graph, source, destination) : 240 | // call heuristic h_x to compute estimation of node-destination distance. 241 | // 242 | // create vertex set in Path 243 | // for each vertex v in Graph : // Initialization 244 | // dist[v] ← INFINITY // Unknown distance from source to v 245 | // prev[v] ← UNDEFINED // Previous node in optimal path from source 246 | // compute h_x[v, destimation] // distance estimation from v to destination 247 | // 248 | // dst_dist[source, destimation] ← h_x // Distance from source to dst 249 | // src_dist[source] ← 0 // Distance from source to source 250 | // priority[source] ← src_dist[source] + dst_dist[source, destination] 251 | // add source to PQ 252 | // while PQ is not empty: 253 | // u ← vertex in PQ with min dist[u] // Node with the least distance 254 | // // will be selected first 255 | // remove u from PQ 256 | // 257 | // for each neighbor v of u : 258 | // alt ← src_dist[u] + length(u, v) 259 | // if alt < src_dist[v] : // A shorter path to v has been found 260 | // src_dist[v] ← alt 261 | // prev[v] ← u 262 | // 263 | // alt_priority[v] ← src_dist[v] + dst_dist[v, destination] 264 | // if v in PQ 265 | // if alt_priority[v] < priority[v] 266 | // priority[v] ← = alt_priority[v] 267 | // else 268 | // add v to PQ 269 | // 270 | // terminate if priority(PQ[0]) >= src_dist[destination] 271 | // 272 | // return dist[], prev[] 273 | 274 | class aStar { 275 | private: 276 | const basicGraph::bGraph* graph_; 277 | path shortest_path_; 278 | map 279 | h_x; 280 | 281 | // this returns estimated distance of node to destination node. 282 | size_t estimate_distance(const basicGraph::bNode* node, const basicGraph::bNode* dst) 283 | { 284 | size_t estimate = 285 | (h_x.find(node) != h_x.end() && h_x.find(dst) != h_x.end()) ? 286 | h_x[dst] - h_x[node] : 0; 287 | return estimate > 0 ? estimate : 0; 288 | } 289 | // heuristic is aadmissible if it never overestimates the cost of reaching the goal. 290 | // Algorithm: 291 | // Compute the minimum weight of all graph nodes starting from src. 292 | // Complexity: 293 | // O(V) + O(E) 294 | void heuristic(const basicGraph::bNode* src) 295 | { 296 | const basicGraph::bNode* node; 297 | queue nodeq; 298 | set visited; 299 | 300 | nodeq.push(src); 301 | h_x[src] = 0; 302 | 303 | while (!nodeq.empty()) 304 | { 305 | node = nodeq.front(); 306 | nodeq.pop(); 307 | 308 | // calculate min arrival wt of every node starting from src. 309 | set::iterator eiter; 310 | for (eiter = node->edgeBegin(); eiter != node->edgeEnd(); eiter++) 311 | { 312 | // avoid cycles 313 | if (visited.find(*eiter) != visited.end()) 314 | continue; 315 | visited.insert(*eiter); 316 | 317 | const basicGraph::bNode* next_node = (*eiter)->otherNode(node); 318 | size_t wt = dynamic_cast(*eiter)->weight(); 319 | size_t next_node_wt = h_x[node] + wt; 320 | if (h_x.find(next_node) != h_x.end()) 321 | { 322 | h_x[next_node] = next_node_wt < h_x[next_node] ? next_node_wt : h_x[next_node]; 323 | } 324 | else 325 | { 326 | h_x[next_node] = next_node_wt; 327 | } 328 | nodeq.push(next_node); 329 | } 330 | } 331 | 332 | return; 333 | } 334 | public: 335 | aStar(const basicGraph::bNode* src, const basicGraph::bGraph* graph) : 336 | graph_(graph), shortest_path_(new pathNode(src)) 337 | { 338 | heuristic(src); 339 | } 340 | void build(const basicGraph::bNode* dst) 341 | { 342 | Heap PQ; // priority queue, i.e. open set 343 | pathNode* dstPNode = nullptr; 344 | 345 | set::iterator niter; 346 | for (niter = graph_->nodeBegin(); niter != graph_->nodeEnd(); niter++) 347 | { 348 | pathNode* pNode = shortest_path_.retrieveOrAddPathNode(*niter); 349 | if (*niter == dst) 350 | dstPNode = pNode; 351 | } 352 | 353 | pqNode qnode(shortest_path_.src()->node_, 0); 354 | PQ.push(qnode); // first node in priority queue 355 | 356 | while (PQ.pop(qnode)) 357 | { 358 | //cout << qnode.node_->name() << "(" << qnode.min_dist_ << ") -> "; 359 | 360 | pathNode* pnode = shortest_path_.retrievePathNode(qnode.node_); 361 | assert(pnode); 362 | 363 | set::iterator eiter; 364 | for (eiter = pnode->node_->edgeBegin(); eiter != pnode->node_->edgeEnd(); eiter++) 365 | { 366 | const basicGraph::bNode* other_gnode = (*eiter)->otherNode(pnode->node_); 367 | size_t dist = dynamic_cast(*eiter)->weight(); 368 | pathNode* other_pnode = shortest_path_.retrievePathNode(other_gnode); 369 | 370 | size_t estimate = estimate_distance(other_gnode, dst); 371 | size_t alt_root_dist = pnode->root_dist_ + dist; 372 | size_t src2dst_estimate = alt_root_dist + estimate; 373 | 374 | if ( alt_root_dist < other_pnode->root_dist_ ) 375 | pnode->setParent(other_pnode, dist, alt_root_dist); 376 | 377 | pqNode qnode_next(other_gnode, src2dst_estimate); 378 | 379 | size_t idx; 380 | if (PQ.index(qnode_next, idx) ) 381 | { 382 | if (PQ[idx].min_dist_ > src2dst_estimate) 383 | { 384 | PQ.erase(qnode_next); // erase old element with wrong priority 385 | PQ.push(qnode_next); // add new element 386 | } 387 | } 388 | else 389 | { 390 | PQ.push(qnode_next); 391 | } 392 | } 393 | 394 | // terminate early, if all nodes in q have distance estimate greater than 395 | // the destination found distance. 396 | if (PQ.size() && PQ[0].min_dist_ >= dstPNode->root_dist_) 397 | break; 398 | } 399 | return; 400 | } 401 | void print(const basicGraph::bNode* dst) 402 | { 403 | shortest_path_.print_path(dst); 404 | } 405 | 406 | }; 407 | } 408 | 409 | #endif 410 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------