|
1 | 1 | # Compile Time Graph Library  |
2 | | -The Compile Time Graph Library (CTGL) is a C++ header-only library that implements `constexpr` graph algorithms and data structures. Simply include `ctgl.h` and you're set! |
| 2 | +The *Compile Time Graph Library* (CTGL) is a C++ header-only library that implements `constexpr` graph algorithms. |
| 3 | + |
| 4 | +## Setup |
| 5 | +To integrate CTGL with your project, add the files in the [header](src/h) directory to your include path. Then, include [`ctgl.h`](src/h/ctgl.h) in the source files of your choice! |
| 6 | + |
| 7 | +**Note:** This library uses C++17 features. |
3 | 8 |
|
4 | 9 | ## Examples |
5 | 10 | The first example finds the shortest distance between two nodes in a graph. |
6 | 11 | ```C++ |
7 | | -// Create Nodes with IDs 1, 2, and 3. |
| 12 | +// The nodes of a CTGL graph are ctgl::Node<> types with unique ID parameters. |
8 | 13 | using n1 = ctgl::Node<1>; |
9 | 14 | using n2 = ctgl::Node<2>; |
10 | 15 | using n3 = ctgl::Node<3>; |
11 | 16 | using nodes = ctgl::List<n1, n2, n3>; |
12 | 17 |
|
13 | | -// Create Edges that connect some of the Nodes. |
14 | | -// (1) --4--> (2) --4--> (3) |
15 | | -// `----------9----------^ |
| 18 | +// The directed, weighted edges of a CTGL graph are ctgl::Edge<> types. |
| 19 | +// 1 --(4)--> 2 --(4)--> 3 |
| 20 | +// '---------(9)---------^ |
16 | 21 | using e12 = ctgl::Edge<n1, n2, 4>; |
17 | 22 | using e13 = ctgl::Edge<n1, n3, 9>; |
18 | 23 | using e23 = ctgl::Edge<n2, n3, 4>; |
19 | 24 | using edges = ctgl::List<e12, e13, e23>; |
20 | 25 |
|
21 | | -// Compose the Nodes and Edges to form a Graph. |
| 26 | +// By definition, a Graph is a composition of Nodes and Edges. |
22 | 27 | using graph = ctgl::Graph<nodes, edges>; |
23 | 28 |
|
24 | | -// Find the distance between Node 1 and Node 3 (i.e., 8). |
25 | | -constexpr int dist = ctgl::algorithm::findDistance(graph{}, n1{}, n3{}); |
| 29 | +// |distance| represents the (shortest) distance between Node 1 and Node 3. |
| 30 | +// In this case, the value of |distance| will be 8. |
| 31 | +constexpr int distance = ctgl::algorithm::findDistance(graph{}, n1{}, n3{}); |
26 | 32 | ``` |
27 | 33 |
|
28 | | -The second example solves the [TSP](https://en.wikipedia.org/wiki/Travelling_salesman_problem) in O(1) running time. |
| 34 | +The second example solves the [Travelling Salesman Problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) in O(1) running time. |
29 | 35 | ```C++ |
30 | | -// Create Nodes with IDs 1, 2, 3, and 4. |
31 | | -using n1 = ctgl::Node<1>; |
32 | | -using n2 = ctgl::Node<2>; |
33 | | -using n3 = ctgl::Node<3>; |
34 | | -using n4 = ctgl::Node<4>; |
35 | | -using nodes = ctgl::List<n1, n2, n3, n4>; |
| 36 | +// Nodes represent cities in the TSP instance. |
| 37 | +using dubai = ctgl::Node<1>; |
| 38 | +using miami = ctgl::Node<2>; |
| 39 | +using paris = ctgl::Node<3>; |
| 40 | +using tokyo = ctgl::Node<4>; |
| 41 | +using cities = ctgl::List<dubai, miami, paris, tokyo>; |
36 | 42 |
|
37 | | -// Create Edges that form multiple circuits across the Nodes. |
38 | | -// .----------1----------v |
39 | | -// (1) --1--> (2) --2--> (3) --1--> (4) --. |
40 | | -// ^ ^---------3---------' ^---4-----' | |
41 | | -// '----------------3---------------------' |
42 | | -using e12 = ctgl::Edge<n1, n2, 1>; |
43 | | -using e23 = ctgl::Edge<n2, n3, 2>; |
44 | | -using e24 = ctgl::Edge<n2, n4, 1>; |
45 | | -using e31 = ctgl::Edge<n3, n1, 3>; |
46 | | -using e34 = ctgl::Edge<n3, n4, 1>; |
47 | | -using e41 = ctgl::Edge<n4, n1, 3>; |
48 | | -using e43 = ctgl::Edge<n4, n3, 4>; |
49 | | -using edges = ctgl::List<e12, e23, e24, e31, e34, e41, e43>; |
| 43 | +// Edges represent unidirectional routes between cities. |
| 44 | +// .-------------(1)-------------v |
| 45 | +// Dubai --(1)--> Miami --(2)--> Paris --(1)--> Tokyo |
| 46 | +// ^ ^-----------(3)-----------' ^---(4)----' | |
| 47 | +// '----------------------(3)-----------------------' |
| 48 | +using routes = ctgl::List<ctgl::Edge<dubai, miami, 1>, |
| 49 | + ctgl::Edge<miami, paris, 2>, |
| 50 | + ctgl::Edge<miami, tokyo, 1>, |
| 51 | + ctgl::Edge<paris, dubai, 3>, |
| 52 | + ctgl::Edge<paris, tokyo, 1>, |
| 53 | + ctgl::Edge<tokyo, dubai, 3>, |
| 54 | + ctgl::Edge<tokyo, paris, 4>>; |
50 | 55 |
|
51 | | -// Compose the Nodes and Edges to form a Graph. |
52 | | -using graph = ctgl::Graph<nodes, edges>; |
| 56 | +// |circuit| represents an optimal solution to the TSP instance from Dubai. |
| 57 | +// The type of |circuit| will express Dubai --> Miami --> Paris --> Tokyo --> Dubai. |
| 58 | +using world = ctgl::Graph<cities, routes>; |
| 59 | +constexpr auto circuit = ctgl::algorithm::findShortestRoute(world{}, dubai{}, cities{}); |
| 60 | +``` |
| 61 | + |
| 62 | +The third example detects opportunities for arbitrage in a foreign exchange market. |
| 63 | +```C++ |
| 64 | +// Nodes represent currencies in the foreign exchange market. |
| 65 | +using aud = ctgl::Node<1>; |
| 66 | +using cad = ctgl::Node<2>; |
| 67 | +using nzd = ctgl::Node<3>; |
| 68 | +using usd = ctgl::Node<4>; |
| 69 | +using currencies = ctgl::List<aud, cad, nzd, usd>; |
| 70 | + |
| 71 | +// Edges represent logarithmic exchange rates between currencies. Why? If the |
| 72 | +// product of the exchange rates along a cycle is less than one, then the sum |
| 73 | +// of the logarithmic exchanges rates along that cycle must be less than zero. |
| 74 | +// v----------(-2)----------. |
| 75 | +// NZD --(1)--> AUD --(-3)--> CAD --(3)--> USD |
| 76 | +using log_rates = ctgl::List<ctgl::Edge<nzd, aud, 1>, |
| 77 | + ctgl::Edge<aud, cad, -3>, |
| 78 | + ctgl::Edge<cad, usd, 3>, |
| 79 | + ctgl::Edge<usd, aud, -2>>; |
53 | 80 |
|
54 | | -// Find an optimal solution to the TSP. |
55 | | -constexpr auto tsp = ctgl::algorithm::findShortestRoute(graph{}, n1{}, nodes{}); |
| 81 | +// |arbitrage| represents the possibility of arbitrage in the currency market. |
| 82 | +// Here, |arbitrage| will be set to true because AUD --> CAD --> USD --> AUD |
| 83 | +// forms a negative cycle. |
| 84 | +using market = ctgl::Graph<currencies, log_rates>; |
| 85 | +constexpr bool arbitrage = ctgl::graph::hasNegativeCycle(market{}); |
56 | 86 | ``` |
57 | 87 |
|
58 | | -## Build Instructions |
59 | | -| Command | Objective | |
60 | | -|--- |--- | |
61 | | -| `make all` | Build the CTGL and run the examples. | |
62 | | -| `make test` | Build the CTGL and run the test suite. | |
63 | | -| `make clean` | Clean the current directory. | |
| 88 | +## Development |
| 89 | +| Command | Description | |
| 90 | +|--- |--- | |
| 91 | +| `make all` | Build and run the CTGL examples. | |
| 92 | +| `make test` | Build and run the CTGL test suite. | |
| 93 | +| `make clean` | Clean the current directory. | |
64 | 94 |
|
65 | | -**Note:** You can specify a compiler flag to any of the build commands to select a different compiler target. For example, to build the test suite using Clang, run `make test COMPILER=clang++`. |
| 95 | +You can provide a `COMPILER` or `FLAGS` argument to any of the build commands to select a different compiler or add custom flags to a compiler invocation. For example, to build the test suite using Clang, use `make test COMPILER=clang++`. |
0 commit comments