The SkyBlue Constraint Solver and Its Applications
Created on 2022-01-28T23:02:09-06:00
Basically you have a set of variables and a set of constraints. Constraints
Overview
Multi-way solver: cycles and conflicts are allowed if a function is registered to resolve the conflict.
Methods: takes input variables, applies some logic, supplies output variables.
Constraint: associates input and output variables to a set of methods.
mgraph: a directed graph of methods to call which solves the constraint system.
Enforced: when a constraint has a method selected.
Unenforced: a constraint which does not have a method.
Method conflict: when two methods would write to the same output variables.
Stay: a constraint that ensures a variable does not change.
Strength: an importance level of a constraint. Stronger constraints are allowed to bump weaker ones.
If an mgraph contains a method conflict then it is not valid.
If an mgraph exists and is acyclic: perform a topological sort. The result is your call chain.
If an mgraph contains cycles: the cycle must be excised and solved externally.
Algorithm
Place all constraints in to the unsolved set.
Walk the unsolved set and enforce each constraint. Select a method for each constraint that does not create a variable overlap with a stronger constraint. You are allowed to demote a weaker constraint by unenforcing it and returning that constraint to the unenforced set.
Convert the set of enforced constraints in to a set of methods to be called (creating the mgraph/mvine.)
Topologically sort the methods by variables to find the optimal order to call them.
Note that if the constraints are cyclic this will fail. SkyBlue allows cyclic dependencies but only by identifying the cycle and replacing it with another solver that operates out of band. For example cyclical parts of solving a GUI would have to be outsourced to Cassowary. On one hand you could just use Cassowary instead--although with SkyBlue the much slower solvers are only used when local propagation fails which could still end up being much faster for some problems.
Tricks
Once a method graph is solved you can reuse it (as long as constraints don't change.) So you only need to solve how to update the (x,y) coordinates of something once and re-use the graph while the user moves the same node.
TODO come back and implement this in nim