///|
fn run_recovery() -> Unit raise {
let solver = @cassowary.Solver::new()
let x = @cassowary.Variable::new("position")
let minimum = @cassowary.Constraint::new(
@cassowary.Expression::new([(x, 1.0)]),
@cassowary.Relation::GreaterEqual,
)
let maximum = @cassowary.Constraint::new(
@cassowary.Expression::new([(x, 1.0)], constant=-100.0),
@cassowary.Relation::LessEqual,
)
solver.add_constraint(minimum)
solver.add_constraint(maximum)
solver.add_edit_variable(x, @cassowary.strong())
solver.suggest_value(x, 40.0)
println("Before conflict: position=\{solver.value(x)}")
let conflict = @cassowary.Constraint::new(
@cassowary.Expression::new([(x, 1.0)], constant=10.0),
@cassowary.Relation::LessEqual,
)
let rejected = try {
solver.add_constraint(conflict)
false
} catch {
@cassowary.SolverError::UnsatisfiableConstraint => {
println(
"Caught UnsatisfiableConstraint: position <= -10 conflicts with position >= 0.",
)
true
}
error => raise error
}
assert_true(rejected)
assert_true(!solver.has_constraint(conflict))
assert_true(solver.has_constraint(minimum))
assert_true(solver.value(x) > 39.999999 && solver.value(x) < 40.000001)
solver.suggest_value(x, 80.0)
assert_true(solver.value(x) > 79.999999 && solver.value(x) < 80.000001)
println("Same solver, next edit: position=\{solver.value(x)}")
solver.remove_constraint(maximum)
solver.suggest_value(x, 140.0)
assert_true(solver.value(x) > 139.999999 && solver.value(x) < 140.000001)
assert_true(minimum.violation(solver) < 0.000001)
println("Removed upper bound, edited again: position=\{solver.value(x)}")
solver.remove_edit_variable(x)
solver.remove_constraint(minimum)
assert_true(!solver.has_edit_variable(x))
assert_true(!solver.has_constraint(minimum))
let stats = solver.statistics()
println(
"Cleaned up: constraints=\{stats.constraints}, edits=\{stats.edits}, pivots=\{stats.pivots}",
)
}
///|
fn main {
run_recovery() catch {
error => {
println("recovery failed: \{error}")
panic()
}
}
}