Deploy ECLiPSe CLP to Europe β ECRC Munich π©πͺ (ESPRIT 1988), the EU Constraint Logic Programming System Behind Airline Crew Rostering and Rail Scheduling, on EU Infrastructure in 2026
In 1988, five of Europe's largest technology companies formed a research consortium to solve a problem that neither database systems nor traditional programming languages could handle cleanly: expressing and solving complex combinatorial constraints over large solution spaces. Bull π«π·, ICL π¬π§, Siemens π©πͺ, Philips π³π±, and Nixdorf π©πͺ pooled resources at the ECRC (European Computer-Industry Research Centre) in Munich π©πͺ, funded by the EU ESPRIT programme β the European Strategic Programme on Research in Information Technology. The result was ECLiPSe: a constraint logic programming system that extends Prolog with integrated constraint solvers, coroutining, and a rich library of propagation algorithms.
More than three decades later, ECLiPSe remains the canonical EU-native constraint programming system. It is used industrially for airline crew rostering (Lufthansa π©πͺ, British Airways π¬π§ via ILOG), railway timetabling (European rail operators), and resource allocation across logistics, manufacturing, and scheduling. Developed within Europe, funded by European research programmes, and deployed in the operational systems that keep European aviation and rail running on time.
Constraint Logic Programming: Search + Propagation
CLP (Constraint Logic Programming) extends Prolog's unification-based search with constraint propagation: the solver does not merely enumerate possibilities but actively reduces the search space by pruning values inconsistent with the constraint store. The interaction between search (branching) and propagation (constraint narrowing) is what makes CLP dramatically more efficient than naive generate-and-test.
:- use_module(library(ic)).
% Constraint Logic Programming over integer intervals
% Worker scheduling: 4 shifts to assign to 3 workers
solve_schedule(Schedule) :-
% Variables: each shift assigned to a worker (1..3)
Schedule = [S1, S2, S3, S4],
S1 :: 1..3,
S2 :: 1..3,
S3 :: 1..3,
S4 :: 1..3,
% Constraint: each worker gets at most 2 shifts
occurrences(1, Schedule, C1), C1 #=< 2,
occurrences(2, Schedule, C2), C2 #=< 2,
occurrences(3, Schedule, C3), C3 #=< 2,
% Constraint: worker 1 cannot take shift 3 (medical training)
S3 #\= 1,
% Constraint: adjacent shifts (1,2) and (3,4) need different workers
S1 #\= S2,
S3 #\= S4,
% Search: labeling with first-fail heuristic
labeling(Schedule).
The :: operator declares a variable's domain. #=<, #\= are constraint primitives β not tests but propagators that actively prune domains. When S3 #\= 1 executes, ECLiPSe does not just record a constraint; it immediately removes value 1 from S3's domain. If this narrows another domain to a singleton, further propagation fires automatically. The search (labeling) only runs over the already-reduced space.
The ic Library: Interval Constraints
ECLiPSe's primary constraint library is ic (Interval Constraints): a CLP system over integer and real intervals. The ic library implements bounds consistency as its default propagation strength, with full arc consistency available for specific constraints.
:- use_module(library(ic)).
% Real-valued interval constraints: geometric layout
layout(X, Y, W, H) :-
% Rectangle position and dimensions
X :: 0.0..100.0,
Y :: 0.0..100.0,
W :: 10.0..50.0,
H :: 10.0..50.0,
% Must fit within 100x100 canvas
X + W #=< 100.0,
Y + H #=< 100.0,
% Minimum area
W * H #>= 200.0,
% Aspect ratio: width at most 3x height
W #=< 3.0 * H.
% Mixed integer/real: production planning
production_plan(Units, Cost, Revenue) :-
Units :: 0..1000, % integer: units produced
Cost :: 0.0..50000.0, % real: production cost
Revenue :: 0.0..100000.0, % real: revenue
% Cost model: fixed + variable
Cost #= 5000.0 + 45.0 * Units,
% Revenue model
Revenue #= 120.0 * Units,
% Profitability constraint
Revenue - Cost #>= 10000.0,
% Integer labeling for units
indomain(Units).
The key innovation of the ic library over earlier CLP(FD) systems is unified handling of integers and reals in the same constraint store. This is essential for engineering and financial optimisation problems where integer decisions (units, personnel counts) interact with continuous quantities (costs, times, flows).
Arc Consistency and Bounds Propagation
ECLiPSe implements both arc consistency (AC) and bounds consistency (BC), and allows the user to choose per-constraint:
Arc consistency (AC-5 algorithm): For a binary constraint C(X, Y), a value v in dom(X) is arc-consistent if there exists at least one value w in dom(Y) such that C(v, w) holds. AC removes values from domains that have no support. Full AC is complete but expensive for large domains.
Bounds consistency (BC): Weaker but cheaper β only prunes the minimum and maximum bounds of each domain, not interior values. Sufficient for most arithmetic constraints.
:- use_module(library(ic)).
:- use_module(library(ic_global)).
% Arc consistency example: alldifferent constraint
% Full AC (expensive but complete domain pruning)
permutation_problem(Vars) :-
Vars = [A, B, C, D, E],
Vars :: 1..5,
% alldifferent with full arc consistency
alldifferent(Vars), % IC global constraint: AC-propagation
% Additional arithmetic constraint (bounds propagation)
A + B #= 6,
C #> D,
labeling(Vars).
% Bounds consistency example: cumulative scheduling
machine_schedule(Tasks) :-
% Tasks: [Start, Duration, Resource]
Tasks = [[S1,3,2], [S2,2,3], [S3,4,1], [S4,1,2]],
% All starts in 0..20
( foreach([S,_,_], Tasks) do S :: 0..20 ),
% Cumulative: total resource usage β€ 4 at any time point
% Bounds propagation over time axis
( foreach([S,D,R], Tasks), foreach(S, Starts),
foreach(D, Durations), foreach(R, Resources) do true ),
cumulative(Starts, Durations, Resources, 4),
( foreach([S,_,_], Tasks) do indomain(S) ).
The cumulative constraint is ECLiPSe's canonical industrial constraint: it encodes "total resource consumption across all active tasks must not exceed capacity." This single constraint, with its bounds-propagation implementation, encodes the core of most crew rostering and machine scheduling problems.
Coroutining: Constraint Suspension and Waking
ECLiPSe's most distinctive implementation feature is coroutining via suspension: a goal can suspend on a variable until a specific condition holds (instantiation, domain narrowing, bounds update), then wake automatically when the condition is triggered.
:- use_module(library(ic)).
% Custom propagator via coroutining
% "Never schedule two tasks in the same room at overlapping times"
:- meta_predicate no_overlap(+, +, +, +).
no_overlap(Start1, Dur1, Start2, Dur2) :-
End1 is Start1 + Dur1,
End2 is Start2 + Dur2,
% Either task1 finishes before task2 starts, or vice versa
( End1 #=< Start2 ; End2 #=< Start1 ).
% Demon (coroutine): re-fires whenever bounds change
:- demon propagate_room_conflict/4.
propagate_room_conflict(S1, D1, S2, D2) :-
% Wake when any bound narrows
suspend(propagate_room_conflict(S1, D1, S2, D2),
4, % priority
[S1->min, S1->max, S2->min, S2->max]),
% Perform propagation with current bounds
ic:get_bounds(S1, MinS1, MaxS1),
ic:get_bounds(S2, MinS2, MaxS2),
E1Min is MinS1 + D1, E1Max is MaxS1 + D1,
E2Min is MinS2 + D2, E2Max is MaxS2 + D2,
% If task1 must start before task2 can end, enforce S1+D1 =< S2
( E1Min > MaxS2 -> S1 + D1 #=< S2 ; true ),
( E2Min > MaxS1 -> S2 + D2 #=< S1 ; true ).
This coroutining model β where user-defined propagators suspend and wake on domain events β is what allows ECLiPSe to implement custom constraint solvers in Prolog itself. The ILOG solver, which powered airline crew rostering at Lufthansa π©πͺ and British Airways π¬π§ in the 1990s-2000s, used ECLiPSe's suspension infrastructure as its extensibility layer.
EU Industrial Applications
Airline Crew Rostering: Lufthansa π©πͺ and British Airways π¬π§
Crew rostering is the canonical ECLiPSe industrial application. An airline must assign pilots and cabin crew to flights such that:
- EU Regulation 83/2014 (OPS): minimum rest periods, maximum flight duty time
- EASA Part-FCL: licence validity, type rating currency, recurrent training
- Company agreements: preferred crew pairings, base assignments, seniority rules
These are hard constraints (legal requirements) and soft constraints (quality objectives) over thousands of crew members and hundreds of daily flights. The problem is NP-hard for even small instances.
:- use_module(library(ic)).
:- use_module(library(ic_global)).
% Crew rostering: EASA Part-FCL + EU OPS compliance
% Simplified: 3-day roster for 4 crew, 6 flights
crew(c1; c2; c3; c4).
flight(f1, 06:00, 09:30, lhr, fra).
flight(f2, 10:00, 11:30, fra, cdg).
flight(f3, 12:00, 14:00, cdg, ams).
flight(f4, 07:00, 10:30, ams, fra).
flight(f5, 11:00, 14:30, fra, mad).
flight(f6, 15:00, 18:00, mad, lhr).
% Decision variable: assignment(Crew, Flight) in {0=unassigned, 1=assigned}
assignment_matrix(Assignments) :-
numlist(1, 4, Crews), numlist(1, 6, Flights),
( foreach(C, Crews), foreach(Row, Assignments) do
( foreach(F, Flights), foreach(Var, Row) do
Var :: 0..1,
% EU OPS: max 3 flights per crew per day
arg(F, flight_day(F), Day),
( foreach(V, DayFlights) do
flights_on_day(C, Day, DayFlights)
),
sum(DayFlights) #=< 3
)
),
% Each flight covered by exactly 2 crew (captain + first officer)
( foreach(F, Flights) do
( foreach(Row, Assignments), foreach(V, ColF) do nth1(F, Row, V) ),
sum(ColF) #= 2
),
% EU OPS: minimum 11h rest between duty periods
enforce_rest_constraints(Assignments),
% EASA Part-FCL: type rating validity
enforce_type_ratings(Assignments),
% Labeling with cost optimisation
( foreach(Row, Assignments) do labeling(Row) ).
ILOG (the company that commercialised ECLiPSe technology before being acquired by IBM πΊπΈ) reported a 15-20% reduction in crew cost at major European airlines through CLP-based rostering compared to manual scheduling. The savings come from better constraint propagation finding more legal roster combinations β directly translating to fewer reserve crew and reduced overtime.
SNCF π«π·: Railway Maintenance Scheduling
SNCF (SociΓ©tΓ© Nationale des Chemins de Fer FranΓ§ais) uses constraint programming for maintenance scheduling of the French high-speed rail network. The TGV network requires maintenance windows that must:
- Not conflict with train operations (capacity constraints)
- Respect ERTMS track-circuit possession procedures
- Complete mandatory EASA-equivalent (EPSF) maintenance intervals
- Minimise total disruption to the timetable
:- use_module(library(ic)).
% Railway maintenance scheduling: EPSF regulatory compliance
% Simplified: Paris-Lyon line, 3-day planning horizon
maintenance_job(j1, track_inspection, 4, 2). % job(ID, type, duration_h, track_km)
maintenance_job(j2, catenary_service, 3, 5).
maintenance_job(j3, signalling_test, 6, 3).
maintenance_job(j4, ballast_tamping, 8, 10).
% Maintenance windows: 01:00-05:00 (4-hour window), 3 nights
window(n1, 60, 300). % Night 1: minutes 60..300 from Day0 midnight
window(n2, 1500, 1740). % Night 2
window(n3, 2940, 3180). % Night 3
schedule_maintenance(Schedule) :-
findall(J, maintenance_job(J, _, _, _), Jobs),
% Assign each job to a start time
( foreach(J, Jobs), foreach(S, Schedule) do
maintenance_job(J, _, Dur, _),
S :: 0..3180,
% Must start and end within a maintenance window
( member(W, [n1, n2, n3]),
window(W, WStart, WEnd),
S #>= WStart,
S + Dur * 60 #=< WEnd
),
% EPSF: minimum 12h recovery between jobs on same track segment
( foreach(J2, Jobs), J2 \= J do
maintenance_job(J2, _, Dur2, Km2),
maintenance_job(J, _, _, Km1),
( abs(Km1 - Km2) < 3 ->
% Adjacent track segments: enforce gap
( S2 in Schedule,
nth1(Idx2, Jobs, J2),
nth1(Idx2, Schedule, S2),
( S + Dur * 60 + 720 #=< S2 ;
S2 + Dur2 * 60 + 720 #=< S )
)
; true )
)
),
% Optimise: complete highest-priority jobs in earliest windows
labeling(Schedule).
Philips π³π±: Manufacturing Resource Allocation
Philips (one of the original ECRC consortium members) uses constraint programming for wafer fabrication scheduling in semiconductor manufacturing. Each wafer batch must pass through a sequence of processing steps, each requiring specific equipment and certified operators:
:- use_module(library(ic)).
:- use_module(library(ic_global)).
% Wafer fab scheduling: equipment qualification + capacity
% Based on Philips Semiconductors (now NXP π³π±) use case
wafer_batch(wb1, [litho, etch, deposit, implant]).
wafer_batch(wb2, [litho, deposit, etch]).
wafer_batch(wb3, [implant, anneal, deposit]).
% Equipment: qualified for specific steps
equipment(litho_1, litho, 8). % machine, process, capacity_wafers_h
equipment(litho_2, litho, 8).
equipment(etch_1, etch, 12).
equipment(etch_2, etch, 12).
equipment(cvd_1, deposit, 6).
equipment(implant_1, implant, 4).
equipment(anneal_1, anneal, 10).
schedule_fab(Assignments) :-
findall(WB, wafer_batch(WB, _), Batches),
( foreach(WB, Batches), foreach(BatchSched, Assignments) do
wafer_batch(WB, Steps),
( foreach(Step, Steps), foreach(start(Step, S, E), BatchSched),
param(WB) do
S :: 0..480, % 8-hour shift in minutes
findall(Equip, equipment(Equip, Step, _), Equips),
% Must use a qualified machine for this step
( member(Equip, Equips),
equipment(Equip, Step, Cap),
Duration is 60 / Cap * 25, % 25 wafers per batch
E #= S + round(Duration)
)
),
% Precedence: steps must execute in order
( fromto(BatchSched, [start(_, _, E)|Rest], Rest, []) do
( Rest = [start(_, S2, _)|_] -> E #=< S2 ; true )
)
),
% Capacity: each machine handles at most 1 batch at a time
( foreach(step(Step, Equip), AllAllocations) do
( foreach(BA, Assignments), foreach(start(Step, S, E), StepTimes) do
member(start(Step, S, E), BA)
),
no_overlap_times(StepTimes)
),
( foreach(BA, Assignments) do
( foreach(start(_, S, _), BA) do indomain(S) )
).
ECLiPSe Architecture: Prolog + CLP + CHR
ECLiPSe integrates three computing paradigms in a single runtime:
| Component | Paradigm | Core abstraction |
|---|---|---|
| Prolog engine | Logic programming | Unification, backtracking, Horn clauses |
| ic library | CLP(FD/R) | Interval constraints, arc consistency |
| CHR | Constraint Handling Rules | User-defined propagation rules |
| Coroutining | Suspension/wake | Demand-driven constraint propagation |
CHR (Constraint Handling Rules) allows users to define new constraint propagators declaratively:
:- use_module(library(chr)).
% CHR rules: define "leq" (less-or-equal) constraint
:- chr_constraint leq/2.
% Reflexivity: leq(X,X) is trivially true
leq(X, X) <=> true.
% Antisymmetry: leq(X,Y) + leq(Y,X) => X = Y
leq(X, Y), leq(Y, X) <=> X = Y.
% Transitivity: leq(X,Y) + leq(Y,Z) => leq(X,Z)
leq(X, Y) \ leq(Y, Z) <=> leq(X, Z).
% Example usage
?- leq(A, B), leq(B, C), leq(C, A).
% CHR fires antisymmetry + transitivity:
% A = B = C
CHR propagators fire eagerly as constraints are added, performing sound transformations of the constraint store. This lets ECLiPSe users implement domain-specific constraint libraries β for example, temporal constraints, probability intervals, or custom resource models β with the same propagation infrastructure as the built-in ic constraints.
EU Provenance: ECRC Munich and ESPRIT
The ECRC (European Computer-Industry Research Centre) was established in Munich π©πͺ in 1984 under the EU ESPRIT (European Strategic Programme on Research in Information Technology) programme. ESPRIT was the European Commission's response to the Japanese Fifth Generation Computer Systems project and the US strategic computing initiative β a targeted investment in European IT research capability.
| Consortium member | Country | Role |
|---|---|---|
| Bull | π«π· France | Computing infrastructure, systems |
| ICL | π¬π§ United Kingdom | Mainframes, database systems |
| Siemens | π©πͺ Germany | Industrial computing, automation |
| Philips | π³π± Netherlands | Consumer electronics, semiconductors |
| Nixdorf | π©πͺ Germany | Business systems (later Siemens-Nixdorf) |
Key developers:
- Joachim Schimpf π©πͺ β Lead architect of the ECLiPSe constraint system (ECRC β IC-Parc Imperial College London π¬π§)
- Kees Shen π³π± β ic library and bounds propagation (ECRC β IC-Parc)
- Micha Meier π©πͺ β Original SEPIA kernel (the Prolog engine under ECLiPSe)
- Mark Wallace π¬π§ β Constraint modelling methodology (IC-Parc β Monash University π¦πΊ)
ECLiPSe was developed under EU ESPRIT funding, at a Munich research centre established by five European companies, with a team drawn from across the EU. It is the direct institutional product of European collaborative research. The current open-source release is maintained with contributions from IC-Parc (Imperial College London) and the broader European CLP community.
CRA 2027, NIS2, EU AI Act
EU AI Act Article 13 (Transparency and provision of information): CLP solutions are inherently transparent. When ECLiPSe finds a crew assignment satisfying all constraints, the assignment is justified by the constraint store: assign(c1, f3) because no_conflict(c1, f1, f3) and type_rating_valid(c1, a320) and rest_period_satisfied(c1, 14). Unlike neural network decisions, CLP decisions have complete, inspectable derivation chains. This directly satisfies the EU AI Act's requirement for high-risk AI systems (which include "AI systems used to dispatch or establish priorities in the servicing of emergency services") to provide human-understandable decision rationales.
EU AI Act Article 9(2)(e) β Risk management: CLP provides formal proofs of constraint satisfaction. If a crew roster is SATISFIABLE under EASA Part-FCL and EU OPS constraints, ECLiPSe has proved that the schedule is legally compliant β not merely tested it against a sample. If UNSATISFIABLE, it has proved no legal roster exists under the given parameters. This transforms compliance checking from probabilistic testing to formal verification.
NIS2 Article 21(2)(a) β Policy compliance checking: CLP can encode network security policies as constraints and verify that all proposed configurations satisfy the policy. A configuration space that is UNSATISFIABLE under security constraints means no valid configuration can violate the policy β a stronger guarantee than testing individual configurations.
CRA 2027 Article 13 β Systematic security properties: ECLiPSe's constraint propagation can verify configuration invariants across an entire product family simultaneously β not just individual instances. "No configuration in this product line exposes port 22 while also enabling anonymous authentication" is expressible as a CLP integrity constraint, verifiable in polynomial time.
Deploying ECLiPSe to sota.io
sota.io is a EU-native Platform-as-a-Service on German infrastructure β GDPR-compliant by default, with managed PostgreSQL, private networking, and zero DevOps overhead. Running ECLiPSe constraint solving on sota.io keeps all problem specifications, constraint models, and solutions within EU jurisdiction.
# ECLiPSe CLP on sota.io β EU infrastructure, GDPR-compliant
FROM ubuntu:22.04
# Install ECLiPSe CLP
RUN apt-get update && apt-get install -y wget tar && \
wget -q https://eclipseclp.org/Distribution/CurrentRelease/ECLiPSe_7.1_13.tgz && \
tar -xzf ECLiPSe_7.1_13.tgz -C /opt && \
rm ECLiPSe_7.1_13.tgz && \
ln -s /opt/ECLiPSe_7.1/bin/x86_64_linux/eclipse /usr/local/bin/eclipse
WORKDIR /workspace
COPY *.ecl ./
COPY solve.pl ./
CMD ["/usr/local/bin/eclipse", "-f", "solve.pl"]
% solve.pl β ECLiPSe HTTP service for constraint solving
:- use_module(library(ic)).
:- use_module(library(ic_global)).
:- module(solver).
% REST endpoint: solve a scheduling problem
solve_crew_roster(Input, Solution) :-
parse_roster_problem(Input, Flights, Crew, Constraints),
% Build constraint model
create_assignment_variables(Flights, Crew, Vars),
apply_regulatory_constraints(Vars, Constraints),
apply_optimisation_objectives(Vars),
% Solve with timeout
timeout(
labeling(Vars),
30, % 30 second timeout
(Solution = timeout, !)
),
extract_roster(Vars, Solution).
# sota.io deployment configuration
name: eclipse-solver
build:
context: .
dockerfile: Dockerfile
resources:
cpu: 2 # Constraint solving is CPU-intensive
memory: 4096 # Large domain problems need memory
env:
ECLIPSE_HOME: /opt/ECLiPSe_7.1
SOLVER_TIMEOUT: 300
MAX_SOLUTIONS: 1
# Scale for parallel problem instances
replicas: 2
# Deploy ECLiPSe solver to sota.io
sota deploy --name eclipse-solver \
--dockerfile ./Dockerfile \
--cpu 2 --memory 4096 \
--env SOLVER_TIMEOUT=300
# Submit a crew rostering problem
curl -X POST https://eclipse-solver.freedom.sota.io/roster \
-H "Content-Type: application/json" \
-d '{
"flights": ["LH400", "LH401", "LH402"],
"crew": ["c001", "c002", "c003", "c004"],
"horizon_days": 3,
"regulation": "eu_ops"
}'
# Response includes solution + constraint justification
# { "status": "SATISFIABLE",
# "roster": { "c001": ["LH400", "LH402"], "c002": ["LH401"] },
# "cost": 1240,
# "constraints_active": 47 }
The free tier on sota.io covers development and small-scale constraint validation (single-server scheduling, team rostering up to ~20 variables). For production airline or rail scheduling instances β thousands of variables, industrial constraint sizes β horizontal scaling adds solver replicas, each handling independent problem instances in parallel.
See Also
- Deploy Clingo/ASP to Europe β Answer Set Programming for combinatorial optimisation and scheduling; Clingo (University of Potsdam π©πͺ) complements ECLiPSe CLP with stable-model semantics and CDNL search
- Deploy Logtalk to Europe β object-oriented logic programming that runs on ECLiPSe as a backend, combining Logtalk's protocol/category structure with ECLiPSe's CLP(FD) constraint infrastructure
- Deploy Prolog to Europe β SWI-Prolog HTTP backends on EU infrastructure; ECLiPSe extends ISO Prolog with integrated constraint solvers and coroutining
- Deploy Curry to Europe β functional-logic language (Kiel π©πͺ/INRIA π«π·) that combines Haskell-style types with Prolog-style constraint solving, a sibling EU-research tradition to ECLiPSe CLP
ECLiPSe CLP: Joachim Schimpf π©πͺ + Kees Shen π³π± + Micha Meier π©πͺ (ECRC Munich, EU ESPRIT 1988 β Bull π«π·, ICL π¬π§, Siemens π©πͺ, Philips π³π±, Nixdorf π©πͺ). Later: IC-Parc, Imperial College London π¬π§. Mark Wallace π¬π§ (modelling methodology). ECLiPSe open-source since 2006. Mozilla Public License. eclipseclp.org. Constraint Handling Rules (CHR): Thom FrΓΌhwirth π©πͺ (Ulm University, ICLP 1991 β UniversitΓ© de Paris 6 / LIP6 π«π·). ILOG (commercialised ECLiPSe scheduler technology) acquired by IBM πΊπΈ 2009 β now IBM ILOG CPLEX CP Optimizer.