Quick syntax tutorial

Choose an example, edit its requirements, and select Solve. A solution is an object graph. Class names start uppercase; role names start lowercase. Statements end with ;, and // starts a comment.

Objects and classes

Facts name existing objects and connections. Class requirements constrain every member; a class declaration alone does not create any objects.

PC(myPC);
CPU(processor);
hasPart(myPC, processor);
Complete(myPC);
disjoint PC, Component;
class Component {}
class CPU extends Component {
    cost = 100;
}
class PC {
    hasPart one CPU provided Complete;
    hasPart only Component;
    cost = sum(hasPart[Component].cost);
    cost <= 300;
}
minimize sum(PC.cost);

Try this complete example with Bound 2 and Step 1: its minimum cost is 100. extends adds requirements; it does not supply overridable defaults. Multiple parents can be separated by commas.

Relationships and counts

Write the role first, then the requirement and the class of matching neighbors:

hasPart some CPU;
At least one CPU neighbor.
hasPart one CPU;
Exactly one CPU neighbor; other kinds of parts are allowed.
hasPart optional GPU;
Zero or one GPU neighbor.
hasPart only Component;
All parts must be components; this does not require any parts to exist.
hasPart at least 2 RAM;
Also supported: at most 4 and exactly 2.

Omit the neighbor class to count all neighbors. Use ^- for the inverse direction:

class Component {
    hasPart^- optional; // at most one owner of any class
}
class ExpandablePC extends PC {
    hasPart at least 2 RAM;
    hasPart at most 4 RAM;
}

Numbers, sums, and conditions

Inside a class, write comparisons directly: capacity = 5; or power <= capacity;. Numbers can be signed integers, decimals, or fractions. Feature values must be multiples of Step.

sum(hasPart[Component].cost) sums costs of matching parts. sum(hasPart.cost) sums costs of all parts. sum(hostedOn^-[Service].cpuRequest) sums requests from services hosted on the current object.

Add provided C to make any requirement conditional on membership in C. It does not make the object belong to C. For example, only complete PCs need a CPU in the first example. Numeric constraints are simultaneous requirements, not assignments executed in order.

Closed catalogues and optimization

closed PC, CPU, hasPart;

Closing a class or role fixes it to exactly its explicit facts. With no facts, it is empty. Leave selection roles open when the solver should choose connections. Different names identify distinct objects; unused catalogue objects still count toward Bound.

Use one objective: minimize sum(PC.cost); or maximize sum(PC.performance);. A global sum counts all members of its class, so sum selected or used objects rather than the entire catalogue.

The original forms still work: A sub B;, subrole r sub s;, and numeric concepts in brackets. Bare concept requirements are allowed inside classes, though descriptive forms are preferred.

Choose an example, edit the knowledge base, then solve it. Bound limits the number of objects; step sets the numeric granularity.

Choose an action.