///|
pub fn order_cross_count(g : Graph, layering : Array[Array[String]]) -> Double {
let mut cc = 0.0
for i = 1; i < layering.length(); i = i + 1 {
cc = cc + order_two_layer_cross_count(g, layering[i - 1], layering[i])
}
cc
}
///|
fn order_two_layer_cross_count(
g : Graph,
north_layer : Array[String],
south_layer : Array[String],
) -> Double {
let south_pos : Map[String, Int] = Map::new()
for i = 0; i < south_layer.length(); i = i + 1 {
let v = south_layer[i]
if !order_cross_is_layer_hole(v) {
south_pos.set(v, i)
}
}
let south_entries : Array[(Int, Double)] = []
for v in north_layer {
if order_cross_is_layer_hole(v) {
continue
}
let entries : Array[(Int, Double)] = []
for e in g.out_edges(v) {
if south_pos.get(e.w) is Some(pos) {
entries.push((pos, order_cross_weight(g.edge_obj(e))))
}
}
entries.sort_by((a, b) => a.0 - b.0)
for entry in entries {
south_entries.push(entry)
}
}
let mut first_index = 1
while first_index < south_layer.length() {
first_index = first_index << 1
}
let tree_size = 2 * first_index - 1
first_index = first_index - 1
let tree : Array[Double] = []
for _ in 0.. 0 {
if index % 2 == 1 {
weight_sum = weight_sum + tree[index + 1]
}
index = (index - 1) >> 1
tree[index] = tree[index] + entry.1
}
cc = cc + entry.1 * weight_sum
}
cc
}
///|
fn order_cross_weight(label : Value?) -> Double {
if value_as_attrs(label) is Some(attrs) {
attrs.get_float_or("weight", 1.0)
} else if value_as_int(label) is Some(v) {
v.to_double()
} else if value_as_float(label) is Some(v) {
v
} else {
1.0
}
}
///|
fn order_cross_is_layer_hole(v : String) -> Bool {
v == ""
}