Spatial layout constraints
Spatial layout constraints
LAYOUT computes bounded numerical rectangle placements. Validated profiles
include finite resizing, quarter-turn choices, indexed families, coupled
components, preferences and scoped checking and investigation.
The bound value is an ordinary calculation result, evaluated through Grid's
existing LP/MIP solver functions when resolved. It starts no job and changes no
other cells.
floorplan = LAYOUT
RECTANGLE kitchen SIZE 4 BY 3
RECTANGLE dining SIZE 5 BY 4
REQUIRE kitchen LEFT OF dining
REQUIRE kitchen TOUCHES dining
END
placement_status = floorplan.status
kitchen_x = floorplan.rectangles.kitchen.x
dining_x = floorplan.rectangles.dining.xLAYOUT floorplan … END is an equivalent declaration spelling. Formatting
preserves the authored header. A source-free owning artifact retains rectangle
declarations and requirements and can render them back to source.
Reusable definitions
Parentheses select an inert definition. Definitions can appear in modules, lexical DO blocks and function bodies. Calling one computes a placement through the ordinary callable and compiled path:
office = LAYOUT(width, depth)
COORDINATES local IN m
RECTANGLE room SIZE width BY depth
END
input room_width = 400cm
west = office(3m AS depth, room_width AS width)
east = office(6m, 4m)LAYOUT office(width, depth) … END is equivalent. LAYOUT() declares a
zero-argument definition. An unused definition performs no solve, including
when its body would require the optional integer solver. Independent calls
have independent inputs and results. Forward calls, named arguments using
value AS parameter, and explicit partial application such as office(_, 3m)
use the declared parameter order. Unknown or duplicate argument names refuse.
Consume a partial in expression scope, for example 400cm >> office(_, 3m).
The ordinary rule against storing callable values in workbook cells also applies
to layout definitions.
This profile accepts at most 64 scalar formals. In a unitless layout every
formal requires a finite untagged number; in a length-valued frame every formal
requires a compatible length, except an explicit dimensionless COEFFICIENT
formal in the affine profile below. Validation includes unused formals. Shapes and
entity structure remain fixed at admission. Local preceding immutable numeric
values may be captured; inputs, state, default values, cells and rule-written
values must be passed as explicit arguments. Mutable dependencies through
aliases also refuse.
Definitions can be imported with ordinary USE aliases or exposures. Immutable
module values and transitive pure helpers retain their defining bindings,
including through re-exports. Module lookup uses the completed declarations;
local initializers retain the bindings visible where they were written. A later
local binding cannot change an earlier helper's capture.
Pure DEFINE, LAMBDA and arrow helpers can compute dimensions, pins, bounds and relation operands. They accept immutable finite numeric or length captures and fixed-shape arrays. Every captured array element is checked, including unread elements and values canceled by arithmetic. Immutable helper captures are shared within each operation; solve, CHECK and QUERY each capture their own current inputs. Expansion retains the 64-level, 10,000-capture-entry and 1,000,000-work limits.
A factory can also accept an ordinary pure numeric callback and capture it in a unitless layout. The callback requires an admitted callable declaration with numeric arguments, a numeric result and finite numeric captures. Its actual callable and capture identities participate in the input contract, including when a changed callback produces equal geometry. This callback profile supports numeric arithmetic, numeric local bindings and its admitted scalar math functions. Unsupported bodies or captures refuse at operation ingress; conditional, array-valued, length-valued and higher-order callback contracts are outside this profile.
Return or partially apply closures in expression scope. A returned wrapper can retain both a layout call and its CHECK companion, as the composed office example shows. Bind QUERY's literal name and mode before transporting a query closure. ARGS, BODY and FUNCTION inspect local declaration metadata without solving.
Reusable composition has completed its correctness and performance checks.
Shaped formal parameters and coupled components use the bounded profile below.
Owning templates rename the definition, its formals and named-call arguments
together. Results retain grid.layout.v1 unless validation is explicitly selected below.
Validated definitions can declare numerical questions.
See the
reusable layout example.
Shaped parameters and coupled components
This bounded profile is implemented.
Declare an array formal's fixed shape before using ordinary INDEX reads:
input A20 = [2, 3]
room = LAYOUT(widths)
PARAMETER widths SHAPE 1 BY 2
VALIDATE EXACT
BOUNDS (0, 0) TO (20, 20)
RECTANGLE desk SIZE INDEX(widths, 1, 1) BY 2
END
placement = room(A20)
checked = room.CHECK(placement, A20)Every entry must satisfy the declared shape and numeric contract, including unread entries. In a length-valued frame the entries are compatible lengths; an explicit COEFFICIENT formal instead carries untagged factors. Coefficient entries have magnitude at most 1,000,000. Shapes use positive literal row and column counts, with at most 10,000 declared entries in one definition. They provide numeric data, never structural entity keys. Immutable key aliases retain the bindings visible in their initializers; a same-spelled numeric formal cannot borrow a module key domain. CHECK and QUERY reserve their own argument names for array formals as well as scalar ones. Reusable module definitions require explicit live arguments for arrays and scalars.
A reusable layout with finite BOUNDS can expose named region or anchor
interfaces with EXPOSE desk AS work and EXPOSE door.LEFT AS entry.
Instantiate it inside a parent with COMPONENT west USING office(2) AT 0, 0 ROTATE 90. Translation uses the parent's coordinate dimension. Rotation is
fixed at 0, 90, 180 or 270 degrees counterclockwise about the local origin.
Both declarations use the same coordinate unit and validation policy: EXACT
throughout, or the identical authored constant absolute allowance with zero
relative allowance. This profile refuses dynamic allowances, nonzero relative
allowances and differently authored unit literals even when they are equivalent.
All instances participate in one coupled solve. Their rectangles, pins, child
bounds and hard constraints remain mandatory. Use west.work.RIGHT to refer
to an exposed region's world anchor, or west.entry for a named anchor.
After rotation, named edge/center interfaces identify the corresponding world
axis and width/height interfaces identify the corresponding world extent.
Private entity names cannot substitute for exposed interfaces. Source value
rename preserves the separate rectangle, component and interface namespaces.
Imports and ordinary lexical aliases retain their defining blueprints.
The coupled office example
combines two independent instances and an aisle between them.
Coupled results use grid.layout.v5. Their components vector retains each
ordered path, blueprint identity, transform to its immediate parent, entity
handles and declared interfaces. Transforms use VECTOR(x, y, rotation_degrees)
in the stated working unit. Entity geometry is in the coupled root frame.
CHECK rejects altered published component metadata; an explicit
grid.layout.candidate.v2 may supply geometry without presentation metadata.
QUERY uses the complete coupled hard set and retains its existing evidence
rules. Composition does not solve children or export executable blueprints.
Existing rectangle, requirement, row, variable, capture and work limits apply to the complete expansion. This profile additionally bounds the combined instance tree to 128 instances, depth 64, 128-byte paths and 10,000 membership/interface entries. Structural changes require readmission; numeric edits reuse the admitted structure.
Indexed rectangles
An indexed declaration expands one immutable typed domain at admission:
people = [1, 2]
deskWidths = [2, 3]
office = LAYOUT(extraWidth)
VALIDATE ABSOLUTE 0.000001 RELATIVE 0
BOUNDS (0, 0) TO (20, 20)
RECTANGLE desk[person IN people] SIZE INDEX(deskWidths, 1, person) + extraWidth BY 2
REQUIRE aisle: desk[1] LEFT OF desk[2] GAP AT LEAST 1
END
placed = office(0)
checked = office.CHECK(placed, 0)The first profile supports one axis per family. Domains are nonempty constant rows or columns containing unique exact integer, text or symbol keys of one kind, in authored order. Text and symbol keys cannot contain control characters. Keys are limited to 128 bytes; integer magnitude is at most 9,007,199,254,740,991. The binder applies only inside that rectangle's operands and cannot shadow an entity or an active formal. Numeric operands retain the existing scalar, length and fixed-shape array contracts. Entity references select constant typed keys; missing, wrong-kind and dynamic keys refuse.
Indexed layouts require VALIDATE and return grid.layout.v3. Each entity adds
family and key, whose kind is number, text or symbol and whose value
retains the actual key. Numeric owner-local id remains the coverage handle.
CHECK verifies the admitted family/key mapping as well as identities and
geometry. Explicit indexed candidates and QUERY witnesses use
grid.layout.candidate.v2; validation origins and QUERY domains retain keyed
metadata. Unindexed v1/v2 contracts remain unchanged.
Numeric dimension edits reuse the admitted structure. Changed membership or domain order requires source/owning readmission and changes definition/frame identity even at equal cardinality and geometry. Input overrides do not expand families. Input, mutable and dynamic Frame domains refuse; a new finite immutable key snapshot requires readmission. The 128-rectangle limit counts all expanded families and scalar rectangles together. CHECK and QUERY use that same expansion. See the indexed metric example.
Typed anchors and affine requirements
Validated layouts with explicit finite BOUNDS also accept scalar equations and inequalities over their declared rectangles:
office = LAYOUT(clearance, alignmentScale)
COORDINATES local IN m
COEFFICIENT alignmentScale
VALIDATE ABSOLUTE 0.000001m RELATIVE 0
BOUNDS (-10m, -10m) TO (20m, 20m)
RECTANGLE first SIZE 2m BY 2m
RECTANGLE second SIZE 3m BY 4m
REQUIRE level: first.CENTER_Y = alignmentScale * second.CENTER_Y
REQUIRE passage: first.RIGHT + clearance <= second.LEFT
REQUIRE maximum: second.LEFT - first.RIGHT <= 3m
END
placed = office(100cm, 1)
checked = office.CHECK(placed, 1m, 1)LEFT, RIGHT, BOTTOM, TOP, CENTER_X, CENTER_Y, WIDTH and HEIGHT are length-valued
anchors in a dimensioned frame. Constant typed keys also select indexed anchors,
for example desk[1].RIGHT. They refer to the owning declaration's actual
entities; ordinary records and same-spelled values cannot impersonate them.
Ordinary value and formal renames preserve entity references. Entity renaming
retains the closed-key refusal of the preceding profiles.
COEFFICIENT name explicitly selects a declared formal's dimensionless numeric
contract. Other formals retain their length contract, including unused inputs.
Coefficients and constants must be finite with magnitude at most 1,000,000.
Compatible quantities normalize before arithmetic. Incompatible dimensions,
products of unknown anchors, anchor denominators, nonlinear anchor functions,
strict comparisons and chained comparisons refuse. Requirements support =,
<= and >= and share the named SOLVE affine arithmetic rules. A fixed dimension
used as a coefficient must be supplied separately as a numeric parameter.
The selected result is grid.layout.v4. Entities retain their owner-local id,
name and geometry, plus the v3 family/key fields (blank for scalar entities).
CHECK accepts the v4 result or grid.layout.candidate.v2 with the same metadata.
Older result contracts remain unchanged for layouts without affine requirements.
CHECK evaluates exact binary-rational residuals from the admitted coefficients, constants and actual geometry independently of the solver's rounded fixed-size row folding. A positive tolerated residual remains visible. Directional QUERY uses every hard affine requirement; its certificates use outward bounds, and uncertain evidence remains explicit. An affine equality is not a new QUERY predicate. The existing 1,000-requirement limit combines relation and affine clauses; each affine requirement has at most 512 anchor terms. All expansion, row, variable, coefficient and capture limits still apply.
See the affine example for independent CHECK and a necessary aisle query.
Validated placements and CHECK
Add VALIDATE EXACT, or VALIDATE ABSOLUTE length RELATIVE fraction, to
select grid.layout.v2. Both tolerance operands are required. The absolute
allowance uses the layout's working unit; the relative allowance is
dimensionless. Omit the clause to preserve the existing v1 result.
office = LAYOUT(width)
COORDINATES local IN m
VALIDATE ABSOLUTE 0.000001m RELATIVE 0
RECTANGLE room SIZE width BY 3m
END
placement = office(400cm)
checked = office.CHECK(placement, 4m)The v2 result includes definition_id, input_id, frame, an entities vector,
validation, and the original solver report and status. Each entity has a
stable declaration-order integer id, its display name, and tagged x, y,
width and height. entities replaces v1's name-keyed rectangles record.
An independently invalid candidate appears only in diagnostic_candidate;
entities is blank. Infeasibility has no usable placement. Validation never
changes the backend's termination status or promotes an unfinished search to
an optimum.
office.CHECK(candidate, ...inputs) returns grid.layout.validation.v1 without
searching or requiring the solver backend. A reactive layout without formal
parameters also has name.CHECK(candidate). Named calls follow ordinary
parameter rules; candidate is reserved in a validated declaration. Checking
an old placement against changed inputs refuses its identity, even if the input
was unused or cancelled by arithmetic. Compatible units normalize before input
identity; all captured array cells and their shape participate.
CHECK accepts a v2 placement or an explicit native record with schema
"grid.layout.candidate.v1", matching definition_id, input_id, frame, and
an entities vector. Each entity must supply its admitted id and all four
geometry fields; names are optional labels. A CHECK report includes the expected
identities and frame even when a supplied candidate does not match. These
identities describe content; copying them does not bypass geometric checking.
The validator checks finite coordinates, complete entity coverage, fixed sizes,
origin domains, pins, bounds, and every supported relation. Fixed dimensions and
identity are exact. Geometric checks preserve exact binary-rational residuals
and allowances, along with authored origins. EXACT allows no violation of the
normalized numeric operands; an approximate solver result may therefore fail
that policy. An explicit allowance is absolute + relative * scale, using
involved sizes and clearances rather than absolute position. A tolerated positive
residual remains visible. This is checked geometry, not a proof of optimality,
necessity, or impossibility.
See the validated placement example for current versus stale input checks.
Numerical questions
A validated definition can declare a named directional question without adding it as a requirement. Call its QUERY companion to ask whether that relation is possible, necessary or excluded by the hard constraints:
office = LAYOUT(clearance)
VALIDATE EXACT
BOUNDS (0, 0) TO (12, 8)
RECTANGLE desk SIZE 3 BY 2
RECTANGLE cabinet SIZE 2 BY 1
REQUIRE desk LEFT OF cabinet
QUERY walkway: desk LEFT OF cabinet GAP AT LEAST clearance
END
possible = office.QUERY("walkway", "MAY", RECORD(), 1)
necessary = office.QUERY("walkway", "MUST", RECORD(), 1)
excluded = office.QUERY("walkway", "CANNOT", RECORD(), 20)| Mode | Question over feasible placements |
|---|---|
MAY |
Does any placement satisfy the declared relation? |
MUST |
Does every placement satisfy it? |
CANNOT |
Is the relation excluded from every placement? |
This profile supports LEFT OF, RIGHT OF, ABOVE and BELOW questions, with an
optional nonnegative GAP AT LEAST operand. The omitted gap is zero. Hard
requirements may use directional minimum/maximum gaps, WITHIN and the typed
affine requirements above. Contact,
shared-edge and non-overlap requirements are outside this query profile.
Use LAYOUT() for a definition with no inputs. QUERY requires VALIDATE and a
callable parameter list; up to 64 query names are allowed, each at most 128
bytes and unique ignoring ASCII case.
The companion takes query_name, query_mode, query_options, then the
definition's inputs. Name and mode must be literal strings; matching ignores
ASCII case. These three parameter names are reserved in the definition and its
captures. Named arguments follow ordinary callable rules. A partial call must
already bind its literal name and mode, for example
1 >> office.QUERY("walkway", "MAY", RECORD(), _). Definition and reflection
reads perform no search. Numeric input edits recompute query evidence.
Pass an empty native record for default options, or provide these fields:
| Option | Default | Accepted range |
|---|---|---|
solves |
2 | Integer 0–2 |
iterations |
2,000 | Integer 0–1,000,000 shared across native stages |
verification_work |
1,000,000 | Integer 1–1,000,000 exact-check work units |
Unknown fields and invalid counts refuse. These limits bound computational
effort; they are not a wall-clock deadline. Query execution requires the solver
capability, including when solves is zero.
Zero solves or iterations return an undetermined query without native runs.
An insufficient exact-check work allowance refuses the operation instead of
publishing unverified evidence.
The result has schema grid.layout.query.v1. Its status is holds,
does_not_hold, undetermined or infeasible_base. Insufficient evidence stays
undetermined; an infeasible base does not make MUST or CANNOT true. Inspect the
status explicitly instead of treating the result as a Boolean. evidence
distinguishes checked geometry, verified certificates, complete native solver
results and incomplete search. termination, runs, budgets and work retain
the search outcome and charged effort.
base_witness is an independently checked feasible placement. witness
satisfies the declared relation; counterexample violates it, regardless of
mode. Thus a witness refutes CANNOT and a counterexample refutes MUST. Available
Unindexed placements use grid.layout.candidate.v1; indexed placements use
grid.layout.candidate.v2. Both can be passed to their owner's CHECK with the
same definition inputs. Invalid native points are diagnostic-only. A verified
bound is separate from a checked placement; residual bounds use exact integer
numerator/denominator strings.
Search may check one additional midpoint between a valid base placement and an
invalid extremum. midpoint_probe identifies that proposal and its two source
candidates. Original native points remain unchanged; the proposal must pass
every exact geometry check before it can become a witness. This uses the same
verification budget and adds no solver call.
Claims concern the admitted finite hard feasible set, independently of the
placement objective. origin_domains exposes each entity's admitted coordinate
limits. Without BOUNDS these are the existing derived finite domains, so the
claim does not extend to an unbounded plane. Query comparisons are exact on the
normalized operands and always use zero tolerance, even when the placement
definition allows a numerical validation tolerance. Definition, input, query
and frame identities accompany the result; prior results supply no implicit
evidence.
See the numerical query example for length-valued questions and rechecking a MAY witness.
Finite sizing and discrete placement
A rectangle can have finite size domains and an optional aspect interval:
RECTANGLE panel SIZE 2m TO 6m BY 2m TO 4m ASPECT 1 TO 2
RECTANGLE door SIZE 4m BY 2m ORIENT {0,90}
OBSTACLE pillar SIZE 2m BY 4m AT 9m,6m
NONOVERLAP desks
NONOVERLAP desks WITH pillarWIDTH, HEIGHT and anchors use the selected physical size. Aspect constraints
remain affine; variable-by-variable products refuse. Orientation uses exact
selectors from the stated finite domain. Obstacles participate only in the
explicitly declared separation requirements. Non-overlap permits touching;
positive clearances must be declared separately. Integer choices fail closed
when the selected solver lacks MIP. CHECK needs no solver and checks the actual
coordinates, sizes, orientations and every hard requirement independently.
Arrangements, choices, snapping and distances
ARRANGE ROW desks GAP aisle
MIRROR CENTERS desks ABOUT X 10m
SNAP desks STEP 50cm AT (0m,0m)
CHOICE route: enabled AND ((first.RIGHT <= second.LEFT) OR (first.TOP <= second.BOTTOM))
DISTANCE access: MANHATTAN (first.CENTER_X,first.CENTER_Y) TO (second.CENTER_X,second.CENTER_Y) AT MOST 12mRows and columns use the immutable family order. Equal spacing and mirror
clauses add affine constraints; they do not move pins or imply non-overlap.
enabled must be Boolean. All raw operands retain their type, finiteness and
unit checks, including operands in an inactive branch. Strict inequality and
negated geometric inequalities refuse in this bounded choice profile.
SNAP uses a positive length step and explicit finite origin. It checks the
returned world coordinates against the grid equation. MANHATTAN and
CHEBYSHEV distances support AT MOST, AT LEAST and EXACTLY over the two
stated anchors. Lower and exact distances retain complete sign alternatives;
a free epigraph variable cannot establish a lower distance. Euclidean distance
is outside this affine profile.
The complete hard set is shared by solve, CHECK and directional QUERY. QUERY ignores soft objectives when answering feasibility questions. Combined component, indexed, pair and choice expansion is counted before copying. Existing limits remain: 128 rectangles, 1,000 requirements, 64 combined choice branches, 1,000 solver columns, 10,000 rows and 1,000,000 sparse coefficients. Snap integer-domain admission retains its separate 250,000-work reservation.
Preferences and explicit prior placement
PREFER near_entry PRIORITY 1 SCALE 1m: work.LEFT = target
PREFER aisle_side PRIORITY 2 SCALE 1m WEIGHT 2: work.LEFT >= 15m
MINIMIZE low PRIORITY 3 SCALE 1m: work.BOTTOMPreferences never relax REQUIRE. Equality measures absolute deviation; inequality measures one-sided nonnegative violation. Every scale and weight must be finite and positive. A scale has the objective's dimension and makes the reported cost dimensionless. Up to 128 terms and 16 priority levels share the existing model limits. Levels run lexicographically with actual native status and completed/unfinished evidence. A checked hard-feasible point is required before a completed level can protect its value for the next level. Huge weights do not approximate priorities.
prior = office(old_target)
request = RECORD("schema","grid.layout.movement.v1",
"matching","exact","scale",1m)
revised = office.MOVE(prior,request,new_target)MOVE adds a final normalized Manhattan objective over entity origins after all
authored preference levels. It requires exact owner/frame/typed-entity coverage;
the prior input identity may differ. Missing, duplicate, changed or nonfinite
entities refuse. No prior result is read from an ambient cache. The optional
weight is positive; iterations is an integer from 0 through 2,000. All levels
share the operation's iteration allowance and one 1,000,000-work independent
geometry verification budget. Publication consumes the checked point without
restarting that budget. A failed backend status is preserved.
Priority results use grid.layout.v10, with geometry_schema identifying the
underlying v2–v9 geometry profile and an objectives vector of level evidence.
Without preferences or MOVE the existing geometry result schema is retained.
Native local regions
region = office.REGION(placement,entity_id,inputs)
converted = target.TRANSFORM(region,
RECORD("schema","grid.layout.transform.v1",
"source_frame_id",region.frame.id,"target_frame_id",target_frame,
"x",2m,"y",0m,"rotation",90),target_inputs)REGION independently CHECKs the current placement and exports one immutable
grid.layout.region.v1 native record. It retains source/input/frame identities,
the owner-local entity and typed key, component path, working unit and a closed
five-vertex native ring. Component coordinates use the coupled root frame.
An endpoint that cannot be represented exactly as a native coordinate refuses.
Reading ordinary layout coordinates allocates no polygons.
Native topology accepts same-frame local regions and reuses the existing native polygon validity and relation classifier. Local/EPSG mixtures and unrelated local frames refuse. TRANSFORM explicitly binds both frame identities, compatible units, finite translation and one quarter rotation from 0, 90, 180 or 270 degrees. Its content identity binds the recorded transform; a digest does not replace geometry validity. These calls do not add ambient predicate facts.
Conflicts and immutable repairs
Validated results retain source-group provenance. Display labels do not grant origin authority. Explicit bounded analysis is separate from ordinary solving:
conflict = office.CONFLICT(
RECORD("schema","grid.layout.conflict-request.v1",
"solves",32,"iterations",2000),inputs)grid.layout.conflict.v1 retains whole authored groups, attempted removals,
backend outcomes and its fixed context. The affine profile can remove pins and
authored bounds over the finite numerical admission context. Discrete bounds,
dimensions and poses remain fixed context and are stated in the report.
Existing limits are 64 members without MIP and 256 with MIP, with at most 2,000
reserved native iterations. Incomplete, cancelled, unavailable and numerical
outcomes do not establish a removable group or irreducibility. Native
infeasibility is not an exact infeasibility certificate; irreducibility is not
minimum cardinality.
REPAIR takes grid.layout.repair-request.v1: current baseline definition/input/
frame identities, up to eight permitted numeric edit domains, their expected
old values, finite candidate values, minimum/maximum, positive compatible scales,
positive weights and priority levels. Domains name explicit pins, dimensions,
bounds or supported clearance/affine leaves using owner-local handles and source
groups. It counts the combined variants before expansion and refuses more than
64. Optional solve/iteration/verification allowances can lower the retained
limits; top_k is from 1 through 8.
repairs = office.REPAIR(request,inputs)
checked = office.CHECK_REPAIR(proposal,request,inputs)Proposals revise numeric leaves of the expanded admitted hard set. They do not
re-evaluate original source parameters or change structural membership. Each
immutable grid.layout.repair-proposal.v1 binds the current baseline, permissions,
typed edits, hypothetical revised identity, normalized lexicographic change
cost, actual candidate and complete independent geometry check. Unedited hard
constraints remain mandatory. CHECK_REPAIR reconstructs the permitted revision
and checks it without search; supplied validation flags grant no authority.
Forged costs, changed origins, stale baselines and out-of-domain edits refuse.
Partial search does not establish optimality or a complete top-k list. Generating
or inspecting a proposal applies nothing. Applying it requires explicit source
readmission.
Coordinates and relationships
Coordinates describe each rectangle's lower-left corner; x increases to the
right and y increases upward. By default, sizes are positive finite numbers in
one common, unitless coordinate system. Dimensions and explicit coordinates may be pure
numeric expressions over preceding constants and inputs. Each supplied dimension,
pin or bound must have magnitude at most 1,000,000. An optional AT x, y fixes the
lower-left corner, for example RECTANGLE room SIZE 10 BY 8 AT 2, 3.
Without explicit bounds, coordinates are nonnegative. BOUNDS (min_x, min_y) TO (max_x, max_y) permits signed coordinates and contains every rectangle in
that closed box. The minima must not exceed the maxima. A valid box that is too
small, or a pin outside it, produces an infeasible result.
input room_width = 4
input entrance_x = -3
floorplan = LAYOUT
BOUNDS (-10, -10) TO (20, 20)
RECTANGLE kitchen SIZE room_width + 1 BY 3 AT entrance_x, -2
RECTANGLE dining SIZE 5 BY 4
REQUIRE aisle: kitchen LEFT OF dining
REQUIRE joint: kitchen TOUCHES dining
ENDInput edits recompute the placement and the finite constants used for binary
choices. Text, booleans, blanks, nonfinite numbers and invalid sizes produce an
error instead of stale coordinates. Unitless layouts also reject tagged inputs. Loose arithmetic coercion does not bypass
these checks. Fixed-shape numeric arrays may supply values through INDEX;
the complete admitted array is validated, including unread cells. Random,
effectful and user-defined function calls are outside this parameter profile.
Length units
COORDINATES local IN m selects a length unit for the whole layout. Compatible
unit literals and typed scalar inputs convert before placement arithmetic. Sizes,
pins and bounds all require lengths in this mode, including zero (0m). A bare
number remains a scalar; it can multiply a length but cannot stand for one.
Use (value INTO unit:m) to explicitly construct a length from a scalar.
Custom length units declared with UNIT use the same registry and follow
owning-template renaming. A case-sensitive SI working prefix whose meaning
changes when a public tag is lowercased requires a lowercase custom alias,
for example UNIT megametre = 1000000m. It is rejected rather than mislabeled.
input room_width = 400cm
floorplan = LAYOUT
COORDINATES local IN m
RECTANGLE kitchen SIZE room_width + 50cm BY 3m AT 0m, 0m
ENDA later input value of 5m produces a width of 5.5m. An untagged 5, 5s,
text or a nonfinite quantity refuses the calculation. Raw scalar factors also
reject tags, text, booleans and blanks before loose arithmetic can coerce them.
The 1,000,000 coordinate and dimension limit applies after conversion into the
working unit. Public coordinates and sizes retain that unit tag; frame.kind
is "local" and frame.unit is the authored unit name.
Addition/subtraction and MIN, MAX, SUM require compatible dimensions.
Multiplication, division and bounded literal integer powers combine dimensions;
the final size or coordinate must be a length. ABS preserves dimensions.
Other numeric functions require scalar arguments: for example, round a ratio
against an explicit length and multiply the result by that length. Use typed
external scalar bindings or write compatible-length arithmetic inside LAYOUT;
an external formula whose ordinary evaluation erased its tag is not silently
reinterpreted. Pure helper calls follow the reusable-definition contracts above;
fixed component frames follow the R3c component contract.
Fixed-shape arrays may contain compatible quantities and supply dimensions
through INDEX(array, row, column). Positions must be constant positive integers
inside the admitted shape. An array must have one physical dimension throughout;
it cannot mix lengths with times or untagged numbers. Numeric factor arrays
remain separate untagged arrays. Tag each quantity, not the array container.
input room_sizes = [400cm, 3m; 2m, 300cm]
floorplan = LAYOUT
COORDINATES local IN m
RECTANGLE kitchen SIZE INDEX(room_sizes, 1, 1) BY INDEX(room_sizes, 1, 2)
RECTANGLE dining SIZE INDEX(room_sizes, 2, 1) BY INDEX(room_sizes, 2, 2)
REQUIRE kitchen LEFT OF dining
ENDEvery captured array element is validated and converted, including unread cells and reads cancelled by arithmetic. Edits may change compatible units and values; changed shapes, missing tags, incompatible dimensions and nonfinite values refuse the calculation. Captured arrays are bounded to 1,000 arrays and 1,000,000 cells in total, with at most 256 distinct unit spellings per quantity array.
Relationships
| Requirement | Meaning |
|---|---|
a LEFT OF b |
a.x + a.width <= b.x |
a RIGHT OF b |
b.x + b.width <= a.x |
a BELOW b |
a.y + a.height <= b.y |
a ABOVE b |
b.y + b.height <= a.y |
a TOUCHES b |
Boundaries intersect and interiors do not overlap; corner contact counts. |
a SHARES EDGE WITH b LENGTH AT LEAST length |
A common boundary segment has at least the positive requested length; a corner does not count. |
a DOES NOT OVERLAP b |
Interiors are disjoint; boundary contact is allowed. |
a WITHIN b |
All of a lies within b, including its boundary. |
a INSIDE b |
Compatibility spelling of WITHIN; it differs from proper containment in qualitative predicates. |
Rectangles have no implicit relationship. State non-overlap explicitly when needed. Requirements may refer to rectangles declared later in the same block. Names are case-insensitive for binding and must be unique within the layout. They do not declare ordinary module cells. The result preserves each rectangle's authored name as its record key.
An optional identifier before a colon labels a requirement, as aisle and
joint do above. Labels must be unique, case-insensitively, within the block.
They appear on its generated solver rows and do not create module bindings.
Directional requirements accept a minimum gap, maximum gap, or both:
REQUIRE aisle: kitchen LEFT OF dining GAP AT LEAST 1m AT MOST 2m
REQUIRE reach: storage ABOVE counter GAP AT MOST 50cm
REQUIRE wall_space: kitchen WITHIN enclosure MARGIN 20cm
REQUIRE joint: counter SHARES EDGE WITH storage LENGTH AT LEAST 1mThese clauses belong inside a layout with the named rectangles. Gaps measure
the distance between the facing edges on the selected axis. Omitting the
minimum means zero; it does not permit overlap. MARGIN applies the same inset
to all four sides of inclusive containment. Gaps and margins are nonnegative;
a shared-edge minimum must be positive. Every operand is bounded to 1,000,000
in the working unit and uses the same reactive scalar/array validation as sizes.
A gap minimum above its maximum is an invalid parameter. An otherwise valid
margin or contact length that cannot fit produces an infeasible placement.
Without explicit bounds, finite coordinate extents include minimum gaps.
Directional and containment requirements are affine. Contact with an authored
direction uses that direction and checks overlap of the perpendicular intervals.
Contact or non-overlap without a direction uses binary choices in the existing
MIP backend. An unavailable MIP backend returns invalid_problem with an
explanation; it never substitutes the continuous relaxation.
Inspecting published evidence
WHY reads the current committed layout value and its retained source origins.
Resolve the requested cell explicitly before inspection. A missing or cold
resident value refuses inspection; WHY does not solve, refresh or rehydrate a
layout. Other cells retain ordinary provenance behavior, including unknown
function names that resemble private layout kernels.
Results and limits
A legacy unvalidated result has schema: "grid.layout.v1", status,
rectangles, and report.
Each rectangle record contains x, y, width, and height. report retains
the native solver status, labels and diagnostics. An infeasible problem has
status: "infeasible" and blank rectangles. Invalid solver ingress propagates
an error. A solver result with an incumbent retains the solver's actual status;
inspect it before treating the placement as optimal.
Without an authored objective, the objective minimizes the sum of rectangle origins, choosing a compact placement near the origin. It does not optimize floor area. Multiple optimal placements may exist; clients should depend on the relationships, not a particular tie choice. Coordinates follow the existing solver's numerical tolerances.
Validated profiles use the versioned entity/validation records described above. Numerical convergence alone does not establish a usable placement: exact size domains or equality constraints can reject an approximate incumbent, including one just outside an endpoint. Inspect validation and diagnostic geometry as well as backend status. CHECK preserves supplied coordinates; it does not clip or repair them to pass validation.
Admission allows at most 128 rectangles, 1,000 requirements, 1,000 expanded
solver variables, 10,000 rows and 1,000,000 coefficients. Finite bounds and
conditional-row constants derive from validated sizes, pins and explicit bounds.
Arbitrary-angle rotation, general polygons as layout decision variables, strict
geometric inequalities, cell targets, assignment modifiers and decorated result
bindings are outside the bounded profile and refuse. The supported discrete
orientation, fixed component transforms and scaled objectives are described above.
Use ordinary SOLVE for other numerical models.
See the fixed layout example and reactive signed layout, and metric layout. The metric array layout uses a fixed width/height table for both rooms. The clearance example combines a bounded aisle, wall margins and a service edge.