Skip to main content

Crate dotloom_constraints

Crate dotloom_constraints 

Source
Expand description

§dotloom-constraints

Constraint solving for Dotloom (ADR-0004).

  • Rules are rows of scalar Expr residuals with exact derivatives.
  • The problem is split into connected components. Purely linear components go to kasuari (a maintained Cassowary implementation); nonlinear/mixed components go to a damped Gauss–Newton backend that solves hard rules as exact equality constraints and preferences as least squares inside the hard-feasible set.
  • Results distinguish solved, underconstrained, conflicting (with evidence), notConverged (with or without a suspected conflict), cancelled and unsupported, and carry structured Diagnostics.
  • SolveJob runs in budgeted steps so hosts can cancel between steps.
  • LinearSession re-solves a linear problem incrementally while a drag moves its target (Cassowary edit variables), verified like a full solve.

This crate has no document, DOM or GPU dependency.

use dotloom_constraints::{Problem, Rule, Strength, Variable, Expr, rules, solve, SolveOptions, Status};

// Shelf: total = w1 + w2 + w3, w1 locked at 600 mm, w2 = w3 ≥ 400 mm.
let mut p = Problem::default();
let total = p.add_var(Variable::new(1800.0).scale(1000.0));
let w1 = p.add_var(Variable::new(600.0).scale(1000.0));
let w2 = p.add_var(Variable::new(600.0).scale(1000.0));
let w3 = p.add_var(Variable::new(600.0).scale(1000.0));
let v = |id| Expr::Var(id);
p.rules.push(Rule::new(1, rules::linear(&[(1.0, v(w1)), (1.0, v(w2)), (1.0, v(w3)), (-1.0, v(total))], rules::Cmp::Eq, 0.0, 1000.0), Strength::Required));
p.rules.push(Rule::new(2, rules::equal(v(w2), v(w3), 1000.0), Strength::Required));
p.rules.push(Rule::new(3, rules::at_least(v(w2), 400.0, 1000.0), Strength::Required));
p.rules.push(Rule::new(4, rules::at_least(v(w3), 400.0, 1000.0), Strength::Required));
p.rules.push(Rule::new(5, rules::fix(v(w1), 600.0, 1000.0), Strength::Required));
p.rules.push(Rule::new(6, rules::fix(v(total), 1600.0, 1000.0), Strength::Required));
let s = solve(&p, &SolveOptions::default());
assert!(s.accepted());
assert!((s.values[w2.index()] - 500.0).abs() < 1e-6);

Modules§

rules
Residual builders for the supported rule classes.

Structs§

Component
A connected component of free variables and the rules that couple them.
ComponentReport
Report of one solved component.
Diagnostic
A structured diagnostic.
Dual
Value plus sparse gradient, sorted by variable index.
LinearForm
Affine form Σ cᵢ·xᵢ + constant.
LinearSession
An incremental solve session for repeated solves of one linear problem whose constants change (see the module documentation).
PointExpr
A 2D point as a pair of expressions.
Problem
A complete solve request.
Row
One scalar residual of a rule.
Rule
A rule: one or more rows with shared metadata.
Solution
Complete solve result.
SolveJob
A resumable solve.
SolveOptions
Solver options.
Target
A desired value for a variable (drag target, typed preference). Targets are never hard; hard edits are expressed as Required rules.
VarId
Index of a solver variable within a crate::Problem.
Variable
A solver variable.

Enums§

Backend
Which backend handled a component.
Certainty
Certainty of a diagnostic.
DiagnosticKind
Diagnostic category.
Expr
A scalar expression.
Progress
Progress of a job after a step.
Relation
Relation of a row: expr = 0 or expr ≤ 0.
Status
Status of one component (or the aggregate solve).
Strength
Constraint strength. Required rules are hard: a solution violating them is never accepted. The others are preferences ordered by priority.

Constants§

STAY_WEIGHT
Weight of the implicit “stay near the previous valid value” preference. It is below every user strength so any explicit preference wins over staying put.

Functions§

components
Split a problem into independent components.
solve
Solve to completion.
stay_factor
Clamp a stay multiplier to the supported range.