41 Construction Project Example
This example shows how legality conditions can be expressed directly as constraints across a small network of related entities:
- Multi-entity legality: legality depends on the builder, licence, zoning rule, environmental clearance, project site and recorded violations.
- Temporal constraints: the licence and environmental clearance must be valid at the project start date.
- Identity and backlink constraints: licences, clearances and violations must refer to the same builder, site or project being certified.
- Cross-value constraints: project height and intended use must be compatible with the zoning rule.
- Declarative legality: there is no procedural validation code, only constraints that describe compliant worlds.
entity Person
{
String name;
Integer age;
}
entity BuilderLicence
{
Person holder;
Date validFrom;
Date validTo;
Boolean suspended;
constraints
{
// ∀A:Integer ∀H:Person
// (this.holder(H) ∧ H.age(A) → A ≥ 18)
holder.age ≥ 18;
// ∀V:Date ∀V1:Date
// (this.validFrom(V) ∧ this.validTo(V1) → V ≤ V1)
validFrom ≤ validTo;
}
}
entity ZoningRule
{
String zone;
Integer maxHeight;
Boolean residential;
Boolean commercial;
}
entity EnvironmentalClearance
{
String siteId;
Boolean approved;
Date expiry;
}
entity ConstructionProject
{
String id;
String siteId;
Person builder;
BuilderLicence licence;
ZoningRule zone;
Boolean residential;
Boolean commercial;
Integer height;
EnvironmentalClearance clearance;
Date startDate;
constraints
{
// 1. Builder must match the licence holder
// ∀H:Person ∀B:Person ∀L:BuilderLicence
// (this.licence(L) ∧ L.holder(H) ∧ this.builder(B) → H = B)
licence.holder = builder;
// 2. Licence must be valid at the start date
// ∀V:Date ∀S:Date ∀L:BuilderLicence
// (this.licence(L) ∧ L.validFrom(V) ∧ this.startDate(S) → V ≤ S)
licence.validFrom ≤ startDate;
// ∀S:Date ∀V:Date ∀L:BuilderLicence
// (this.startDate(S) ∧ this.licence(L) ∧ L.validTo(V) → S ≤ V)
startDate ≤ licence.validTo;
// 3. Licence must not be suspended
// ∀S:Boolean ∀L:BuilderLicence
// (this.licence(L) ∧ L.suspended(S) → ¬S)
¬licence.suspended;
// 4. Height must comply with zoning
// ∀H:Integer ∀M:Integer ∀Z:ZoningRule
// (this.height(H) ∧ this.zone(Z) ∧ Z.maxHeight(M) → H ≤ M)
height ≤ zone.maxHeight;
// 5. Environmental clearance must be approved and valid
// ∀A:Boolean ∀C:EnvironmentalClearance
// (this.clearance(C) ∧ C.approved(A) → A)
clearance.approved;
// ∀S:Date ∀E:Date ∀C:EnvironmentalClearance
// (this.startDate(S) ∧ this.clearance(C) ∧ C.expiry(E) → S ≤ E)
startDate ≤ clearance.expiry;
// 6. The clearance must be for this project site
// ∀S:String ∀S1:String ∀C:EnvironmentalClearance
// (this.clearance(C) ∧ C.siteId(S) ∧ this.siteId(S1) → S = S1)
clearance.siteId = siteId;
// 7. Residential/commercial compatibility
// (example: a commercial project cannot be built in a residential-only zone)
// ∀R:Boolean ∀R1:Boolean ∀Z:ZoningRule
// (this.residential(R) ∧ this.zone(Z) ∧ Z.residential(R1) ∧ R → R1)
residential → zone.residential;
// ∀C:Boolean ∀C1:Boolean ∀Z:ZoningRule
// (this.commercial(C) ∧ this.zone(Z) ∧ Z.commercial(C1) ∧ C → C1)
commercial → zone.commercial;
// ∀R:Boolean ∀C:Boolean
// (this.residential(R) ∧ this.commercial(C) → ¬(R ∧ C))
¬(residential ∧ commercial);
}
}
entity Violation
{
ConstructionProject project;
String code;
Boolean resolved;
}
entity LegalProject
{
ConstructionProject project;
Violation violation*;
constraints
{
// All violations must be resolved
// ∀R:Boolean ∀V:Violation
// (this.violation(V) ∧ V.resolved(R) → R)
violation.resolved;
// Every listed violation must belong to this legal project
// ∀P:ConstructionProject ∀P1:ConstructionProject ∀V:Violation
// (this.violation(V) ∧ V.project(P) ∧ this.project(P1) → P = P1)
violation.project = project;
}
}