package scientific.matplot
import std.math.*
import std.unittest.*
import std.unittest.testmacro.*
import scientific.numbers.*
import scientific.linear.*
import scientific.stats.random.*
import scientific.stats.normal.*
/* Type for weights, x_data, y_data, z_data, line_widths: Float64
Type for edges: Int64 */
foreign func c_graph(edges: CPointer<Unit>, row: Int64, col: Int64, line_spec: CString): CPointer<Unit>
foreign func c_digraph(edges: CPointer<Unit>, row: Int64, col: Int64, line_spec: CString): CPointer<Unit>
foreign func c_show_labels(netw: CPointer<Unit>, b: Bool): Unit
foreign func c_edge_labels(netw: CPointer<Unit>, weights: CPointer<Unit>, len: Int64): Unit
foreign func c_edge_labels_str(netw: CPointer<Unit>, edge_labels: CPointer<CString>, len: Int64): Unit
foreign func c_node_labels(netw: CPointer<Unit>, node_labels: CPointer<CString>, len: Int64): Unit
foreign func c_x_data(netw: CPointer<Unit>, x_data: CPointer<Unit>, len: Int64): Unit
foreign func c_y_data(netw: CPointer<Unit>, y_data: CPointer<Unit>, len: Int64): Unit
foreign func c_z_data(netw: CPointer<Unit>, z_data: CPointer<Unit>, len: Int64): Unit
foreign func c_line_widths(netw: CPointer<Unit>, line_widths: CPointer<Unit>, len: Int64): Unit
public func graph(edges: Matrix<Int64>, line_spec!: String = "-o") {
if (edges.getCols() != 2) {
throw IllegalArgumentException("graph: input must be a matrix with 2 columns.")
}
var cstr_line_spec = unsafe { LibC.mallocCString(line_spec) }
let handle = unsafe { c_graph(edges.ptr, edges.getRows(), edges.getCols(), cstr_line_spec) }
unsafe { LibC.free(cstr_line_spec) }
return Network(handle)
}
public func digraph(edges: Matrix<Int64>, line_spec!: String = "-o"): Network {
if (edges.getCols() != 2) {
throw IllegalArgumentException("digraph: input must be a matrix with 2 columns.")
}
var cstr_line_spec = unsafe { LibC.mallocCString(line_spec) }
let handle = unsafe { c_digraph(edges.ptr, edges.getRows(), edges.getCols(), cstr_line_spec) }
unsafe { LibC.free(cstr_line_spec) }
return Network(handle)
}
public class Network {
var ptr: CPointer<Unit>
/* Input is a pointer to matplot::network. */
init(ptr: CPointer<Unit>) {
this.ptr = ptr
}
public func show_labels(b: Bool): Unit {
unsafe { c_show_labels(this.ptr, b) }
}
public func x_data(x_data: Vector<Float64>): Unit {
unsafe { c_x_data(this.ptr, x_data.ptr, x_data.size()) }
}
public func y_data(y_data: Vector<Float64>): Unit {
unsafe { c_y_data(this.ptr, y_data.ptr, y_data.size()) }
}
public func z_data(z_data: Vector<Float64>): Unit {
unsafe { c_z_data(this.ptr, z_data.ptr, z_data.size()) }
}
public func edge_labels(weights: Vector<Float64>): Unit {
unsafe { c_edge_labels(this.ptr, weights.ptr, weights.size()) }
}
public func edge_labels(edge_labels: Array<String>): Unit {
let size = edge_labels.size
var a = unsafe { malloc(UIntNative(8 * size)) }
var labels_ptr = CPointer<CString>(a)
for (i in 0..size) {
var cstr_edge_label = unsafe { LibC.mallocCString(edge_labels[i]) }
unsafe { labels_ptr.write(i, cstr_edge_label) }
unsafe { LibC.free(cstr_edge_label) }
}
unsafe { c_edge_labels_str(this.ptr, labels_ptr, size) }
}
public func node_labels(node_labels: Array<String>): Unit {
let size = node_labels.size
var a = unsafe { malloc(UIntNative(8 * size)) }
var labels_ptr = CPointer<CString>(a)
for (i in 0..size) {
var cstr_node_label = unsafe { LibC.mallocCString(node_labels[i]) }
unsafe { labels_ptr.write(i, cstr_node_label) }
unsafe { LibC.free(cstr_node_label) }
}
unsafe { c_node_labels(this.ptr, labels_ptr, size) }
}
public func line_widths(line_widths: Vector<Float64>): Unit {
unsafe { c_line_widths(this.ptr, line_widths.ptr, line_widths.size()) }
}
}
public func testGraph1() {
let edges = matrix<Int64>([
[0, 0], [1, 0], [5, 0], [0, 1], [1, 1], [2, 1], [6, 1],
[1, 2], [2, 2], [3, 2], [7, 2], [2, 3], [3, 3], [4, 3],
[8, 3], [3, 4], [4, 4], [9, 4], [0, 5], [5, 5], [6, 5],
[10, 5], [1, 6], [5, 6], [6, 6], [7, 6], [11, 6], [2, 7],
[6, 7], [7, 7], [8, 7], [12, 7], [3, 8], [7, 8], [8, 8],
[9, 8], [13, 8], [4, 9], [8, 9], [9, 9], [14, 9], [5, 10],
[10, 10], [11, 10], [15, 10], [6, 11], [10, 11], [11, 11], [12, 11],
[16, 11], [7, 12], [11, 12], [12, 12], [13, 12], [17, 12], [8, 13],
[12, 13], [13, 13], [14, 13], [18, 13], [9, 14], [13, 14], [14, 14],
[19, 14], [10, 15], [15, 15], [16, 15], [20, 15], [11, 16], [15, 16],
[16, 16], [17, 16], [21, 16], [12, 17], [16, 17], [17, 17], [18, 17],
[22, 17], [13, 18], [17, 18], [18, 18], [19, 18], [23, 18], [14, 19],
[18, 19], [19, 19], [24, 19], [15, 20], [20, 20], [21, 20], [25, 20],
[16, 21], [20, 21], [21, 21], [22, 21], [26, 21], [17, 22], [21, 22],
[22, 22], [23, 22], [27, 22], [18, 23], [22, 23], [23, 23], [24, 23],
[28, 23], [19, 24], [23, 24], [24, 24], [29, 24], [20, 25], [25, 25],
[26, 25], [35, 25], [21, 26], [25, 26], [26, 26], [27, 26], [36, 26],
[22, 27], [26, 27], [27, 27], [28, 27], [37, 27], [23, 28], [27, 28],
[28, 28], [29, 28], [38, 28], [24, 29], [28, 29], [29, 29], [30, 29],
[39, 29], [29, 30], [30, 30], [31, 30], [40, 30], [30, 31], [31, 31],
[32, 31], [41, 31], [31, 32], [32, 32], [33, 32], [42, 32], [32, 33],
[33, 33], [34, 33], [43, 33], [33, 34], [34, 34], [44, 34], [25, 35],
[35, 35], [36, 35], [45, 35], [26, 36], [35, 36], [36, 36], [37, 36],
[46, 36], [27, 37], [36, 37], [37, 37], [38, 37], [47, 37], [28, 38],
[37, 38], [38, 38], [39, 38], [48, 38], [29, 39], [38, 39], [39, 39],
[40, 39], [49, 39], [30, 40], [39, 40], [40, 40], [41, 40], [50, 40],
[31, 41], [40, 41], [41, 41], [42, 41], [51, 41], [32, 42], [41, 42],
[42, 42], [43, 42], [52, 42], [33, 43], [42, 43], [43, 43], [44, 43],
[53, 43], [34, 44], [43, 44], [44, 44], [54, 44], [35, 45], [45, 45],
[46, 45], [55, 45], [36, 46], [45, 46], [46, 46], [47, 46], [56, 46],
[37, 47], [46, 47], [47, 47], [48, 47], [57, 47], [38, 48], [47, 48],
[48, 48], [49, 48], [58, 48], [39, 49], [48, 49], [49, 49], [50, 49],
[59, 49], [40, 50], [49, 50], [50, 50], [51, 50], [60, 50], [41, 51],
[50, 51], [51, 51], [52, 51], [61, 51], [42, 52], [51, 52], [52, 52],
[53, 52], [62, 52], [43, 53], [52, 53], [53, 53], [54, 53], [63, 53],
[44, 54], [53, 54], [54, 54], [64, 54], [45, 55], [55, 55], [56, 55],
[65, 55], [46, 56], [55, 56], [56, 56], [57, 56], [66, 56], [47, 57],
[56, 57], [57, 57], [58, 57], [67, 57], [48, 58], [57, 58], [58, 58],
[59, 58], [68, 58], [49, 59], [58, 59], [59, 59], [60, 59], [69, 59],
[50, 60], [59, 60], [60, 60], [61, 60], [70, 60], [51, 61], [60, 61],
[61, 61], [62, 61], [71, 61], [52, 62], [61, 62], [62, 62], [63, 62],
[72, 62], [53, 63], [62, 63], [63, 63], [64, 63], [73, 63], [54, 64],
[63, 64], [64, 64], [74, 64], [55, 65], [65, 65], [66, 65], [56, 66],
[65, 66], [66, 66], [67, 66], [57, 67], [66, 67], [67, 67], [68, 67],
[58, 68], [67, 68], [68, 68], [69, 68], [59, 69], [68, 69], [69, 69],
[70, 69], [60, 70], [69, 70], [70, 70], [71, 70], [61, 71], [70, 71],
[71, 71], [72, 71], [62, 72], [71, 72], [72, 72], [73, 72], [63, 73],
[72, 73], [73, 73], [74, 73], [64, 74], [73, 74], [74, 74]
])
graph(edges)
save("./tests/imgs/graph/graph1.png", "png")
clear()
}
public func testGraph2() {
let edges = matrix<Int64>([
[0, 1], [0, 4], [0, 5], [1, 2], [1, 10], [2, 3], [2, 15],
[3, 4], [3, 20], [4, 25], [5, 6], [5, 9], [6, 7], [6, 29],
[7, 8], [7, 41], [8, 9], [8, 37], [9, 11], [10, 11], [10, 14],
[11, 12], [12, 13], [12, 36], [13, 14], [13, 32], [14, 16], [15, 16],
[15, 19], [16, 17], [17, 18], [17, 31], [18, 19], [18, 52], [19, 21],
[20, 21], [20, 24], [21, 22], [22, 23], [22, 51], [23, 24], [23, 47],
[24, 26], [25, 26], [25, 29], [26, 27], [27, 28], [27, 46], [28, 29],
[28, 42], [30, 31], [30, 34], [30, 53], [31, 32], [32, 33], [33, 34],
[33, 35], [34, 55], [35, 36], [35, 39], [36, 37], [37, 38], [38, 39],
[38, 40], [39, 56], [40, 41], [40, 44], [41, 42], [42, 43], [43, 44],
[43, 45], [44, 57], [45, 46], [45, 49], [46, 47], [47, 48], [48, 49],
[48, 50], [49, 58], [50, 51], [50, 54], [51, 52], [52, 53], [53, 54],
[54, 59], [55, 56], [55, 59], [56, 57], [57, 58], [58, 59]
])
graph(edges, line_spec: "-.dr").show_labels(false)
save("./tests/imgs/graph/graph2.png", "png")
clear()
}
public func testGraph3() {
let edges = matrix<Int64>([
[0, 1], [0, 2], [0, 3], [0, 4], [0, 6], [0, 9], [1, 5],
[1, 6], [2, 5], [2, 9], [3, 7], [3, 9], [4, 6], [4, 7],
[5, 8], [5, 10], [6, 8], [7, 8], [7, 10], [9, 10]
])
let weights = vector<Float64>([
1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 2.0, 4.0, 1.0, 6.0,
2.0, 8.0, 8.0, 9.0, 3.0, 2.0, 10.0, 12.0, 15.0, 16.0
])
var g = graph(edges)
g.x_data(vector<Float64>([0.0, 0.5, -0.5, -0.5, 0.5, 0.0, 1.5, 0.0, 2.0, -1.5, -2.0]))
g.y_data(vector<Float64>([0.0, 0.5, 0.5, -0.5, -0.5, 2.0, 0.0, -2.0, 0.0, 0.0, 0.0]))
g.z_data(vector<Float64>([5.0, 3.0, 3.0, 3.0, 3.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0]))
g.edge_labels(weights)
view(2)
save("./tests/imgs/graph/graph3.png", "png")
clear()
}
public func testGraph4() {
let edges = matrix<Int64>([
[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 5],
[2, 5], [3, 4], [3, 6], [4, 6], [5, 6]
])
let weights = vector<Float64>([
50.0, 10.0, 20.0, 80.0, 90.0, 90.0, 30.0, 20.0, 100.0, 40.0, 60.0])
var g = graph(edges)
g.edge_labels(weights)
let m_weight = max(weights)
var line_widths = weights.apply({w: Float64 => 5.0 * w / m_weight})
g.line_widths(line_widths)
save("./tests/imgs/graph/graph4.svg", "svg")
clear()
}
public func testDiGraph1() {
let edges = matrix<Int64>([
[0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [1, 6], [1, 7],
[1, 8], [1, 9], [1, 10], [1, 11], [1, 12], [1, 13], [1, 14],
[14, 15], [14, 16], [14, 17], [14, 18], [14, 19]
])
digraph(edges)
save("./tests/imgs/graph/digraph1.png", "png")
clear()
}
public func testDiGraph2() {
let edges = matrix<Int64>([
[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 4],
[2, 6], [3, 5], [3, 6], [4, 7], [5, 7], [6, 7]
])
var g = digraph(edges)
g.edge_labels(["x", "y", "z", "y", "z", "x", "z", "x", "y", "z", "y", "x"])
g.node_labels(["{0}", "{x}", "{y}", "{z}", "{x,y}", "{x,z}", "{y,z}", "{x,y,z}"])
save("./tests/imgs/graph/digraph2.png", "png")
clear()
}
public func testGraph() {
testGraph1()
testGraph2()
testGraph3()
testGraph4()
testDiGraph1()
testDiGraph2()
}