Skip to content

Instantly share code, notes, and snippets.

@d4tocchini
Created April 3, 2012 01:18
Show Gist options
  • Save d4tocchini/2288542 to your computer and use it in GitHub Desktop.
Save d4tocchini/2288542 to your computer and use it in GitHub Desktop.
Overconstrained Mailing List

I've already communicated this with you, Greg & Alex, but I thought I'd shoot the mailing list a summary...

Heads-up: code snippets are coffeescript

My focus has been on high-level declaration of constraints, not so much solver API. My API goals thus far:

  • Chain-able, ie. 100 <= w <= 1000 <= w2...
  • Close-as-possible resemblance to natural forms of equality and inequality equations. This also makes the Ometa language parsing pretty straightforward.
  • Higher-ordered constraint objects that contain constraint primitives. Maybe current c.Constraint should be c.ConstraintPrimitive? A chained constraint equation would contain many constraint primitives. This would also allow subclassing of constraints that internally setup many constraint primitives.
  • Convention & hooks for subclassing core Constraint object for implementing custom relationships such as "inside", "left-of", etc... I imagine a plugin-like eco-system, where the API can expand to include W3C's grid-layout templates and Apples Visual Format Language for ASCII style configuration.
  • Normalize API for c.Variable & c.LinearExpression so linear expressions can be treated just like variables... ie. linearExpression.value()
  • "Retained-mode" where state of system can be more intuitively inspected. Naturally as I begin hacking Cassowary, I encapsulated much of its API with my own helpers.

So, to express: 100 <= box3.width <= 1000

My first crack looked like:

c.leq(100, box3.width, c.strong)

c.leq(box3.width, 1000, c.strong)

I wanted a single declaration, so tried method chaining like so:

c(100)['<='](box3.width)['<='](100).strength('strong')

But, method names like <= was too weird and I lost the data interpabality inherent with JSON, so I moved to a JSON API like:

# returns single constraint

Constraint.create
  id: 'box3WidthMinMax'
  c: [100, '<=', box3.width, '<=', 1000]
  strength: c.strong


# returns array of constraints

Constraint.create [
    id: 'box3WidthMinMax'
    c: [100, '<=', box3.width, '<=', 1000]
  ,
    id: 'box2WidthMinMax'
    c: [50, '<=', box2.width, '<=', box3.width]
]

I prefer a pure JSON configuration, seems more authentically JS, but I'm not satisfied with the c key for the constraint configuration. And, as Alex points out, the strengths always stick out like a wart. Using an Array for the constraint configuration seems like the right way to accommodate chain-able operators and for configuring Apple-style ASCII layout. For example:

button1.right + 100 == button2.left !strong
menu.left + 10 == button1.left !strong
button2.right + 10 == menu.right  !strong

In Apple's VFL, is equivalent to strongly requiring, inside menu:

h: |-[button1]-100-[button2]-|

Which could be configured w/ JSON like so:

{
  h: ['|','-',[button1],100,[button2],'-','|']
  inside: menu
  offset: 10
  weight: strong
 }

ConstraintCSS is the best API simply b/c we can write the (in)equality statements in their natural form. Likewise, the best JS API would be something like a CoffeeScript extension that allows the constraint statements to be written in their unaltered form...

This message's Markdown source: gist.github.com/2288542

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment