1 /** 2 Copyright: Copyright (c) 2018, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 Port of the rust implementation in graspan1. 7 The dataset is downloaded from [graspan dataset](https://drive.google.com/drive/folders/0B8bQanV_QfNkbDJsOWc2WWk4SkE). 8 9 The dataformat is: [EDGE SOURCE] [EDGE DESTINATION] [EDGE VALUE]. 10 An edge-list format. 11 12 To run this test the file http_df has to be put in the build directory. 13 Then execute the test with: dub test -- -s -d "shall calculate the dataflow from http_df" 14 */ 15 module datacat_test.graspan1; 16 17 import std.algorithm : filter, map, splitter; 18 import std.array : appender, empty, array; 19 import std.conv : to; 20 import std.datetime.stopwatch : StopWatch; 21 import std.file : thisExePath; 22 import std.path : buildPath, baseName; 23 import std.range : takeExactly; 24 import std.stdio : writeln, writefln, File; 25 import std.typecons : Yes; 26 import std.ascii : isWhite; 27 28 import datacat; 29 30 int main(string[] args) { 31 if (args.length < 2) { 32 writefln("Usage: %s DATA_FILE", thisExePath.baseName); 33 return 1; 34 } 35 writeln("Shall calculate the dataflow from the provided file"); 36 37 auto timer = StopWatch(Yes.autoStart); 38 const datafile = args[1]; 39 40 // Make space for input data. 41 auto nodes = appender!(KVTuple!(uint, uint)[])(); 42 auto edges = appender!(KVTuple!(uint, uint)[])(); 43 44 // Read input data from a handy file. 45 foreach (line; File(buildPath(datafile)).byLine.filter!(a => !a.empty && a[0] != '#')) { 46 auto elts = line.splitter.filter!"!a.empty".takeExactly(3); 47 auto src = elts.myPopFront.to!uint; 48 auto dst = elts.myPopFront.to!uint; 49 auto ty = elts.myPopFront; 50 switch (ty) { 51 case "n": 52 nodes.put(kvTuple(dst, src)); 53 break; 54 case "e": 55 edges.put(kvTuple(src, dst)); 56 break; 57 default: 58 assert(0, "should not happen. Unknown type: " ~ ty); 59 } 60 } 61 62 writefln("%s: Data loaded", timer.peek); 63 timer.reset; 64 65 // Create a new iteration context, ... 66 Iteration iter; 67 68 // .. some variables, .. 69 auto variable1 = iter.variable!(uint, uint)("nodes"); 70 auto variable2 = iter.variable!(uint, uint)("edges"); 71 72 // .. load them with some initial values, .. 73 variable1.insert(nodes.data); 74 variable2.insert(edges.data); 75 76 // .. and then start iterating rules! 77 while (iter.changed) { 78 // N(a,c) <- N(a,b), E(b,c) 79 static auto helper(T0, T1, T2)(T0 b, T1 a, T2 c) { 80 return kvTuple(c, a); 81 } 82 83 variable1.fromJoin!helper(variable1, variable2); 84 } 85 86 auto reachable = variable1.complete; 87 88 timer.stop; 89 writefln("%s: Computation complete (nodes_final: %s", timer.peek, reachable.length); 90 91 return 0; 92 } 93 94 auto myPopFront(RT)(ref RT r) { 95 auto v = r.front; 96 r.popFront; 97 return v; 98 }