as3: wip implement push-relabel algorithm

This commit is contained in:
2026-03-26 10:07:03 +01:00
parent 044e0ac52e
commit e3333549e0

View File

@@ -0,0 +1,116 @@
package main
import "core:fmt"
import "core:math"
import "core:slice"
// the graph starts with a source s and ends with a sink t, hence the 1s.
// then there is a stack of n nodes, then a chain of k nodes, then another stack of m nodes.
// all edges have weight 1, except the chain of k nodes, which all have weight c.
// ```
// an bm
// / \ c c / \
// s - .. - r1 - .. - rk - .. - t
// \ / \ /
// a1 b1
// ```
// we create and return an adjacency matrix representing the graphs.
create_graph :: proc($n, $m, $k: int, c: int) -> (res: [1 + n + k + m + 1][1 + n + k + m + 1]int) {
// source to n nodes
for i in 1 ..= n do res[0][i] = 1
// n nodes to r1
r1 := n + 1
for i in 1 ..= n do res[i][r1] = 1
// r1 through rk
rk := r1 + k
for i in r1 ..< rk - 1 do res[i][i + 1] = c
// rk to m nodes
for i in rk ..< rk + m do res[rk - 1][i] = 1
// m nodes to sink
for i in rk ..< rk + m do res[i][rk + m] = 1
res += transpose_graph(res)
return
}
transpose_graph :: proc(g: [$row][$col]$T) -> (res: [col][row]T) {
for i in 0 ..< row {
for j in i ..< col {
res[i][j], res[j][i] = g[j][i], g[i][j]
}
}
return
}
print_graph :: proc(g: [$row][$col]$T, elem_sep := " ", line_sep := "\n") {
// column markers
fmt.print(" ")
fmt.print(elem_sep)
for i in 0 ..< row {
fmt.print(rune('a' + i))
fmt.print(elem_sep)
}
// body
fmt.print(line_sep)
for i in 0 ..< row {
fmt.print(rune('a' + i)) // row markers
fmt.print(elem_sep)
for j in 0 ..< col {
fmt.print(g[i][j])
fmt.print(elem_sep)
}
fmt.print(line_sep)
}
}
find_node_with_excess :: proc(excesses: []int) -> (u: int, ok: bool) {
for e, idx in excesses do if e > 0 do return idx, true
return -1, false
}
find_admissible_edge :: proc(u: int, residuals, heights: []int) -> (v: int, ok: bool) {
if len(residuals) != len(heights) do return -1, false
for r, idx in residuals {
if r > 0 && heights[u] == heights[idx] + 1 {
return idx, true
}
}
return -1, false
}
push :: proc(u, v: int, residuals, excesses: []int) -> (res: []int, ok: bool) {
if len(residuals) != excesses
}
push_relabel :: proc(graph: [$n][n]int) -> (flow: [n][n]int) {
heights: [n]int
heights[0] = n
flow[0] += graph[0]
excesses: [n]int
excesses[0] = -math.sum(flow[0][:])
excesses += flow[0]
for {
u := find_node_with_excess(excesses[1:n - 1]) or_break
u += 1
residuals := graph[u] - flow[u]
if v, ok := find_admissible_edge(u, residuals[:], heights[:]); ok {
flow[u] = push(u, v, residuals[:], excesses[:])
} else {
// relabel(u, v, graph, flow)
}
}
return
}
main :: proc() {
graph := create_graph(3, 3, 3, 3)
print_graph(graph, elem_sep = " ")
fmt.println()
print_graph(push_relabel(graph))
}