98 lines
2.6 KiB
Plaintext
98 lines
2.6 KiB
Plaintext
import vec:*
|
|
import queue:*
|
|
import map:*
|
|
import set:*
|
|
import util:*
|
|
|
|
fun poset<T>(): poset<T> {
|
|
var to_ret.construct(): poset<T>
|
|
return to_ret
|
|
}
|
|
|
|
obj poset<T> (Object) {
|
|
var open_deps: map<T, set<T>>
|
|
var close_deps: map<T, set<T>>
|
|
var opened: set<T>
|
|
var closed: set<T>
|
|
fun construct(): *poset<T> {
|
|
open_deps.construct()
|
|
close_deps.construct()
|
|
opened.construct()
|
|
closed.construct()
|
|
return this
|
|
}
|
|
fun copy_construct(old: *poset<T>) {
|
|
open_deps.copy_construct(&old->open_deps)
|
|
close_deps.copy_construct(&old->close_deps)
|
|
opened.copy_construct(&old->opened)
|
|
closed.copy_construct(&old->closed)
|
|
}
|
|
fun operator=(other: ref poset<T>) {
|
|
destruct()
|
|
copy_construct(&other)
|
|
}
|
|
fun destruct() {
|
|
open_deps.destruct()
|
|
close_deps.destruct()
|
|
opened.destruct()
|
|
closed.destruct()
|
|
}
|
|
fun size(): int {
|
|
return open_deps.size()
|
|
}
|
|
fun add_open_dep(first: T, second: T) {
|
|
add_job(first)
|
|
add_job(second)
|
|
open_deps[first].add(second)
|
|
}
|
|
fun add_close_dep(first: T, second: T) {
|
|
add_job(first)
|
|
add_job(second)
|
|
close_deps[first].add(second)
|
|
}
|
|
fun add_job(vertex: T) {
|
|
if (open_deps.contains_key(vertex))
|
|
return;
|
|
open_deps.set(vertex, set<T>())
|
|
close_deps.set(vertex, set<T>())
|
|
}
|
|
fun done(job: T): bool {
|
|
return closed.contains(job)
|
|
}
|
|
fun run(f: fun(T): void) {
|
|
opened = set<T>()
|
|
closed = set<T>()
|
|
while closed.size() != size() {
|
|
var changed = false
|
|
// intentionally not refs, as it can change out from under us
|
|
open_deps.for_each(fun(v: T, ods: set<T>) {
|
|
if !closed.contains(v) && closed.contains(ods) {
|
|
if !opened.contains(v) {
|
|
changed = true
|
|
f(v)
|
|
if closed.contains(open_deps[v]) {
|
|
opened.add(v)
|
|
}
|
|
}
|
|
if closed.contains(open_deps[v]) && closed.contains(close_deps[v]) {
|
|
changed = true
|
|
closed.add(v)
|
|
}
|
|
}
|
|
})
|
|
if (changed == false) {
|
|
error("Poset has not changed!")
|
|
}
|
|
}
|
|
}
|
|
fun get_sorted(): vec<T> {
|
|
var to_ret = vec<T>()
|
|
run(fun(i: T) {
|
|
to_ret.add(i)
|
|
})
|
|
return to_ret
|
|
}
|
|
}
|
|
|
|
|