Constraint Solver
Kairos Constraint
Hocheffizienter Constraint-Satisfaction-Solver. Weist Entities auf einem N-dimensionalen Grid oder einer Zeitachse zu, erfüllt harte Regeln und minimiert weiche Penalties.
Pricing
Einmalig pro Request, unabhängig von Dauer und Ergebnis.
/v1/kairos/constraintLöst ein Constraint-Satisfaction-Problem. Die vollständige Lösung liegt hinter einem Pre-signed URL.
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
dimensions | array<Dimension> | Ja | — | Variablen-Achsen (≥ 1). Jeder Eintrag definiert eine Dimension mit eindeutiger id — siehe Abschnitt Dimensionen. |
entities | array<Entity> | Ja | — | Was platziert wird (≥ 1). Jede Entity hat min_placements / max_placements und optional pro Dimension eine Einschränkung — siehe Abschnitt Entities. |
constraints | array<Constraint> | Optional | [] | Liste der Regeln, die auf der Lösung gelten müssen (hard) oder zu Penalty-Kosten führen (soft). 15 Typen verfügbar — siehe Abschnitt Constraints. |
config | Config | Optional | {} | Solver-Einstellungen: Zeitbudget, Early-Stopping, Korrelations-ID, URL-Gültigkeit — siehe Abschnitt Config. |
Request
curl -X POST "https://api.centra.dbpg.io/v1/kairos/constraint" \
-H "Authorization: Bearer sk-live-your_api_key" \
-H "Content-Type: application/json" \
-d '{
"dimensions": [
{ "type": "range", "id": "slot", "size": 6, "ordered": true },
{ "type": "set", "id": "room", "values": ["main", "a", "b"] }
],
"entities": [
{ "id": "keynote",
"dimensions": { "slot": { "values": [0] }, "room": { "values": ["main"] } },
"min_placements": 1, "max_placements": 1 },
{ "id": "talk_a",
"dimensions": { "slot": {}, "room": { "values": ["a", "b"] } },
"min_placements": 1, "max_placements": 1 }
],
"constraints": [
{ "type": "not_same_slot", "hard": true,
"entity_a": "talk_a", "entity_b": "keynote", "dimension": "slot" }
],
"config": { "time_limit_seconds": 60, "request_id": "example-1" }
}'Response
{
"status": "optimal",
"request_id": "example-1",
"warnings": [],
"statistics": {
"timing": { "model_build_seconds": 0.01, "solve_seconds": 0.03, "total_seconds": 0.04 },
"problem_size": { "dimensions": 2, "entities": 2, "constraints": 1, "variables": 18, "cells": 18 },
"total_penalty": 0, "best_bound": 0, "gap_percent": 0.0,
"soft_constraint_violations": []
},
"result_url": "https://...s3.eu-central-1.amazonaws.com/csp/example-1.json?...",
"result_expires_at": "2026-04-24T17:00:00+00:00",
"usage": {
"credits_used": 2300,
"remaining_balance": 7700
}
}Dimensionen
Jede Dimension ist eine Achse, auf der Entities Werte annehmen können. Drei Typen. Jede Dimension braucht eine eindeutige id innerhalb des Requests.
set — Kategoriale Werte
Liste diskreter, namentlich aufgelisteter Werte. Geeignet für Räume, Teams, Produkte, Farben — alles, wo die Werte keinen natürlichen Zahlenbezug haben.
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
type | "set" | Ja | — | Discriminator, muss exakt "set" sein. |
id | string | Ja | — | Eindeutige Kennung der Dimension, wird in Entities und Constraints referenziert. |
values | array<string> | Ja | — | Erlaubte String-Werte. Die Reihenfolge ist nur signifikant, wenn ordered=true gesetzt ist. |
ordered | boolean | Optional | false | Default false. Wenn true, gelten die Werte als sortiert — relevant für sequence, proximity, spacing. |
{ "type": "set", "id": "room", "values": ["r1", "r2", "r3"], "ordered": false }range — Numerischer Bereich
Integer-Werte von 0 bis size-1. Ideal für Zeitslots, Nummern, Ringplätze — alles, wo die Reihenfolge semantisch relevant ist.
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
type | "range" | Ja | — | Discriminator, muss exakt "range" sein. |
id | string | Ja | — | Eindeutige Kennung der Dimension. |
size | integer ≥ 1 | Ja | — | Anzahl der Werte. Erlaubte Werte sind Integer 0..size-1. |
ordered | boolean | Optional | true | Default true. range-Dimensionen sind standardmässig geordnet. |
{ "type": "range", "id": "slot", "size": 40, "ordered": true }interval — Kontinuierliche Zeitachse
Zeit-Dimension mit konfigurierbarer Dauer. Intern erzeugt der Solver pro Entity ein IntervalVar mit Start/Dauer/Ende, NoOverlap pro Ressourcengruppe ist automatisch.
Parameter
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
type | "interval" | Ja | Discriminator, muss exakt "interval" sein. |
id | string | Ja | Eindeutige Kennung der Dimension. |
horizon | integer ≥ 1 | Ja | Gesamtlänge der Zeitachse in Zeiteinheiten (z. B. 480 = 8 Stunden in Minuten). |
{ "type": "interval", "id": "time", "horizon": 480 }Einschränkung: Maximal eine Interval-Dimension pro Request.
Entities
Das sind die Objekte, die der Solver platziert — Unterrichtsstunden, Werbespots, Schichten, Kisten, etc.
Felder
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
id | string | Ja | — | Eindeutige Kennung der Entity im Request. Wird in Constraints und in der Response referenziert. |
name | string | Optional | "" | Freitext-Bezeichnung für Display und Logs. Default leerer String. |
dimensions | object | Ja | — | Dict dim_id → EntityDimensionConfig. Jeder Eintrag legt fest, welche Werte dieser Entity auf der jeweiligen Dimension erlaubt sind. Fehlende Dimensionen bedeuten: alle Werte dieser Dimension erlaubt. |
min_placements | integer ≥ 1 | Ja | — | Minimale Anzahl aktiver Platzierungen für diese Entity (≥ 1). |
max_placements | integer ≥ 1 | Ja | — | Maximale Anzahl aktiver Platzierungen (≥ 1). Muss ≥ min_placements sein. |
EntityDimensionConfig
Pro Dimension unter entities[].dimensions. Jedes Feld ist optional.
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
values | array<string|integer> | Optional | — | Liste erlaubter Werte, Teilmenge der Dimension-Werte. Default: alle Werte der Dimension. |
mode | "any" | "all" | Optional | "any" | "any" = Entity wählt pro Platzierung einen Wert. "all" = Entity belegt alle angegebenen Werte gleichzeitig als Block. Default "any". |
size | integer ≥ 1 | Optional | 1 | Anzahl benachbarter Werte, die eine Platzierung belegt (≥ 1). Nur bei ordered-Dimensionen sinnvoll — z. B. size=2 für Doppelstunde. Default 1. |
duration | integer ≥ 1 | Optional | 1 | Nur bei Interval-Dimensionen. Dauer der Platzierung in Zeiteinheiten. Default 1. |
{
"id": "math_5a",
"name": "Math 5a with Mueller",
"dimensions": {
"slot": {},
"room": { "values": ["r1", "r2"], "mode": "any", "size": 1 }
},
"min_placements": 1,
"max_placements": 1
}Constraints
Regeln, die auf der Lösung gelten. Jede Regel ist entweder hart (muss erfüllt sein) oder weich (darf verletzt werden, kostet aber Penalty). Der Solver minimiert die Summe aller weichen Penalties.
Gemeinsame Felder
Alle Constraint-Typen teilen diese Basis-Felder. Die typ-spezifischen Felder kommen darunter.
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
type | string | Ja | — | Discriminator. Einer der 15 Typen unten. |
id | string | Optional | null | Optionale Kennung. Erscheint in response.statistics.soft_constraint_violations[].constraint_id, wenn verletzt. |
hard | boolean | Ja | — | true = muss erfüllt sein, ansonsten infeasible. false = darf verletzt werden, kostet aber penalty pro Verletzung. |
penalty | integer ≥ 1 | Alternative | — | Pflicht wenn hard=false. Kosten pro Verletzungs-Einheit (Integer ≥ 1). |
Übersicht
Alle 15 Regeltypen im Schnelldurchlauf. Die typ-Spalte ist auf das Detail darunter verlinkt.
| # | Typ | Mode | Kurzbeschreibung | Pflichtfelder |
|---|---|---|---|---|
| 1 | fill | hardsoft | Jede Zelle muss belegt sein. | — |
| 2 | cardinality | hardsoft | Begrenzt Anzahl Platzierungen einer Entity. | entityminmax |
| 3 | proximity | hardsoft | Mindestabstand zweier Entities auf einer Dimension. | entity_aentity_bdimensionmin_gap |
| 4 | spacing | soft | Anti-Clump — bestraft benachbarte Platzierungen derselben Entity. | entitydimensionclump_penalty |
| 5 | same_slot | hardsoft | Zwei Entities müssen denselben Dimensions-Wert teilen. | entity_aentity_bdimension |
| 6 | not_same_slot | hardsoft | Zwei Entities dürfen keinen Dimensions-Wert teilen. | entity_aentity_bdimension |
| 7 | sequence | hardsoft | Entity A muss vor Entity B kommen. | firstthendimension |
| 8 | follows | hardsoft | Entity B muss direkt nach Entity A platziert sein. | entity_aentity_bdimension |
| 9 | not_follows | hardsoft | Entity B darf nicht direkt nach Entity A platziert sein. | entity_aentity_bdimension |
| 10 | mutual_exclusion | hardsoft | Aus der Gruppe ist pro Wert nur eine Entity erlaubt. | entitiesdimension |
| 11 | max_per_value | hardsoft | Obergrenze für Platzierungen einer Entity pro Wert. | entitydimensionmax |
| 12 | cumulative | hardsoft | Gewichtete Kapazitätsschranke pro Wert. | dimensiondemandsmax_capacity |
| 13 | pairwise_exclusion | hardsoft | Pro Kombination mehrerer Dimensionen nur eine Entity. | dimensions |
| 14 | pairwise_fill | hardsoft | Jede Kombination mehrerer Dimensionen muss belegt sein. | dimensions |
| 15 | expression | hardsoft | Freie Regel in eigener DSL. | rule |
Detaillierte Typ-Referenz
fill
Jede Zelle (Kombination aller Dimensions-Werte) muss von mindestens einer Entity belegt sein. Klassisch für vollständige Abdeckung eines Grids.
Keine typ-spezifischen Felder — nur die gemeinsamen Felder oben.
Beispiel
{ "type": "fill", "hard": true }cardinality
Begrenzt, wie oft eine Entity platziert werden darf. Bei soft: jede fehlende oder überschüssige Platzierung kostet penalty.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity | string | Ja | ID der zu begrenzenden Entity. |
min | integer | Ja | Minimale Anzahl Platzierungen. |
max | integer | Ja | Maximale Anzahl Platzierungen. |
Beispiel
{
"type": "cardinality",
"hard": false,
"penalty": 5,
"entity": "math_5a",
"min": 4,
"max": 5
}proximity
Zwei Entities müssen auf der angegebenen (geordneten) Dimension mindestens min_gap Werte auseinanderliegen.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity_a | string | Ja | ID der ersten Entity. |
entity_b | string | Ja | ID der zweiten Entity. |
dimension | string | Ja | Dimension, auf der der Abstand gemessen wird. Muss ordered sein. |
min_gap | integer ≥ 1 | Ja | Mindestabstand in Werte-Schritten. |
Beispiel
{
"type": "proximity",
"hard": true,
"entity_a": "brand_A",
"entity_b": "brand_B",
"dimension": "slot",
"min_gap": 3
}spacing
Anti-Clump-Regel: verhindert, dass Platzierungen derselben Entity in direkt benachbarten Werten stehen. Immer soft — hard=false ist Pflicht.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity | string | Ja | ID der Entity, deren Platzierungen auseinandergehalten werden sollen. |
dimension | string (ordered) | Ja | Geordnete Dimension, auf der die Nachbarschaft geprüft wird. |
clump_penalty | integer ≥ 1 | Ja | Strafe pro direkt benachbartem Paar derselben Entity. |
Beispiel
{
"type": "spacing",
"hard": false,
"penalty": 10,
"entity": "lightning",
"dimension": "slot",
"clump_penalty": 50
}same_slot
Wenn Entity A aktiv ist, muss mindestens eine Platzierung von B denselben Dimensions-Wert haben. Für Kopplung zwischen Entities.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity_a | string | Ja | ID der ersten Entity (die die Kopplung auslöst). |
entity_b | string | Ja | ID der zweiten Entity (die denselben Wert haben muss). |
dimension | string | Ja | Dimension, auf der die Wertgleichheit gilt. |
Beispiel
{
"type": "same_slot",
"hard": true,
"entity_a": "a",
"entity_b": "b",
"dimension": "day"
}not_same_slot
Entity A und Entity B dürfen nicht denselben Dimensions-Wert haben. Für Entkopplung.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity_a | string | Ja | ID der ersten Entity. |
entity_b | string | Ja | ID der zweiten Entity. |
dimension | string | Ja | Dimension, auf der die Werte unterschiedlich sein müssen. |
Beispiel
{
"type": "not_same_slot",
"hard": true,
"entity_a": "a",
"entity_b": "b",
"dimension": "day"
}sequence
Die früheste aktive Platzierung von first muss vor der frühesten von then liegen. Für Reihenfolge-Abhängigkeiten.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
first | string | Ja | ID der Entity, die zuerst kommen muss. |
then | string | Ja | ID der Entity, die danach kommt. |
dimension | string (ordered) | Ja | Geordnete Dimension, auf der die Reihenfolge definiert ist. |
Beispiel
{
"type": "sequence",
"hard": true,
"first": "intro",
"then": "advanced",
"dimension": "slot"
}follows
Wenn Entity A an Position t aktiv ist, muss Entity B an Position t+1 aktiv sein. Für direkte zeitliche Nachfolge.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity_a | string | Ja | ID der vorherigen Entity. |
entity_b | string | Ja | ID der Entity, die direkt danach kommen muss. |
dimension | string (ordered) | Ja | Geordnete Dimension, auf der die Nachfolge definiert ist. |
Beispiel
{
"type": "follows",
"hard": true,
"entity_a": "a",
"entity_b": "b",
"dimension": "slot"
}not_follows
Wenn Entity A an Position t, darf Entity B nicht an Position t+1 sein. Negativform von follows.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity_a | string | Ja | ID der vorherigen Entity. |
entity_b | string | Ja | ID der Entity, die nicht direkt danach kommen darf. |
dimension | string (ordered) | Ja | Geordnete Dimension, auf der die Nachfolge geprüft wird. |
Beispiel
{
"type": "not_follows",
"hard": true,
"entity_a": "a",
"entity_b": "b",
"dimension": "slot"
}mutual_exclusion
Aus der angegebenen Gruppe darf pro Dimensions-Wert höchstens eine Entity aktiv sein.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entities | array<string> | Ja | Liste der Entity-IDs, die sich gegenseitig ausschliessen. |
dimension | string | Ja | Dimension, auf der die Exklusivität gilt. |
Beispiel
{
"type": "mutual_exclusion",
"hard": true,
"entities": ["a", "b", "c"],
"dimension": "slot"
}max_per_value
Obergrenze, wie oft eine einzelne Entity pro Dimensions-Wert platziert werden darf.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity | string | Ja | ID der betroffenen Entity. |
dimension | string | Ja | Dimension, auf der die Obergrenze gilt. |
max | integer ≥ 1 | Ja | Maximale Anzahl Platzierungen pro Wert (≥ 1). |
Beispiel
{
"type": "max_per_value",
"hard": true,
"entity": "brand_x",
"dimension": "slot",
"max": 1
}cumulative
Gewichtete Kapazitätsschranke: Summe der Gewichte aller auf einem Dimensions-Wert aktiven Entities darf max_capacity nicht überschreiten. Klassisch für Ressourcen mit Kapazität.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
dimension | string | Ja | Dimension, auf der die Kapazität gemessen wird. |
demands | object<entity_id, integer> | Ja | Dict entity_id → Gewicht. Entities ohne Eintrag haben Gewicht 0. |
max_capacity | integer ≥ 1 | Ja | Kapazitätsschranke pro Dimensions-Wert (≥ 1). |
Beispiel
{
"type": "cumulative",
"hard": true,
"dimension": "slot",
"demands": {
"truck_a": 3,
"truck_b": 2,
"truck_c": 4
},
"max_capacity": 6
}pairwise_exclusion
Für jede Kombination der angegebenen Dimensions-Werte darf höchstens eine Entity aktiv sein. Generalisiert die Zellen-Exklusivität auf eine beliebige Dimensions-Teilmenge. Klassisch: "Ein Lehrer nie gleichzeitig in zwei Räumen" mit dimensions=[slot, teacher].
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
dimensions | array<string> (≥ 1) | Ja | Liste der Dimensions-IDs, deren Kombinationen exklusiv sind (≥ 1 Element). |
Beispiel
{
"type": "pairwise_exclusion",
"hard": true,
"dimensions": ["slot", "teacher"]
}pairwise_fill
Für jede Kombination der angegebenen Dimensions-Werte muss mindestens eine Entity aktiv sein. Generalisiert fill auf eine beliebige Dimensions-Teilmenge.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
dimensions | array<string> (≥ 1) | Ja | Liste der Dimensions-IDs, deren Kombinationen belegt sein müssen (≥ 1 Element). |
Beispiel
{
"type": "pairwise_fill",
"hard": true,
"dimensions": ["slot", "room"]
}expression
Freie Regel in client-eigener DSL für Spezialfälle. Wird vom Verifier nicht inhaltlich geprüft — nur vom Solver ausgewertet. Nur verwenden, wenn keine der anderen 14 Typen passt.
Typ-spezifische Felder
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
rule | string (DSL) | Ja | Regel-String in eigener Syntax. |
Beispiel
{
"type": "expression",
"hard": true,
"rule": "<custom DSL>"
}Config
Alle Config-Felder sind optional. Defaults sind im Schema gesetzt.
Felder
Parameter
| Name | Typ | Status | Default | Beschreibung |
|---|---|---|---|---|
time_limit_seconds | float (1–600) | Optional | 60 | Maximale Zeit, die der Solver nach einer Lösung suchen darf. Zwischen 1 und 600 Sekunden. Default 60. |
stop_after_first_solution | boolean | Optional | false | true = Solver liefert die erste gültige Lösung zurück und beendet sich. Keine Optimierung weiterer Lösungen. Default false. |
relative_gap_limit | float (0–1) | null | Optional | null | Stoppt den Solver, sobald der relative Gap zur theoretischen Untergrenze ≤ X ist. Beispiel 0.05 = 5 %. Default null. |
absolute_gap_limit | integer ≥ 0 | null | Optional | null | Stoppt den Solver, sobald der absolute Penalty-Gap ≤ X ist. Default null. |
request_id | string | null | Optional | null | Eigene Korrelations-ID. Wird 1:1 in die Response echoed und erscheint in CloudWatch-Logs zur Zuordnung. |
result_url_expires_in | integer (60–604800) | Optional | 10800 | Gültigkeit des Pre-signed URLs in Sekunden. Zwischen 60 und 604800 (7 Tage). Default 10800 (3 h). |
hints | array<HintAssignment> | Optional | [] | Liste von Warm-Start-Vorgaben aus einer vorherigen Lösung. Jeder Eintrag hat die Felder entity und values. |
Response
Bei Status optimal und feasible liegt die vollständige Lösung hinter result_url. Die Felder im Wire-Body:
Status-Werte
HTTP-Statuscode und Abrechnungslogik pro Ergebnis-Klassifikation.
| status | HTTP | Abrechnung | Bedeutung |
|---|---|---|---|
optimal | 200 | Ja | beweisbar optimale Lösung |
feasible | 200 | Ja | gültige Lösung, Optimalität nicht bewiesen (Zeitlimit erreicht oder Early-Stop) |
infeasible | 200 | Ja | beweisbar keine Lösung möglich — diagnostics-Block liefert Details |
unknown | 200 | Ja | Timeout ohne Ergebnis und ohne Unlösbarkeitsbeweis |
invalid | 400 | Nein | Request schematisch ok, aber logisch ungültig (z. B. min > max) |
assignments
Liste aller Belegungen. Nur in der S3-Datei enthalten, nicht im Wire-Body. Bei Status infeasible / unknown / invalid fehlt der Block komplett.
Parameter
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
entity | string | Ja | ID der platzierten Entity. |
placement | integer | Ja | Laufnummer der Platzierung für diese Entity (1..max_placements). |
values | object | Ja | Konkrete Werte pro Dimension für diese Platzierung. Bei Interval-Dimensionen enthält das Objekt zusätzlich einen Schlüssel mit dem Suffix _end für den Endzeitpunkt. |
statistics
Performance- und Qualitätsmetriken. Immer im Wire-Body enthalten (auch bei offloadeten Responses).
Parameter
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
timing.model_build_seconds | float | Ja | Zeit für Variablen- und Constraint-Aufbau vor dem eigentlichen Solve. |
timing.solve_seconds | float | Ja | Reine Solver-Zeit. |
timing.total_seconds | float | Ja | Ende-zu-Ende im Solver (model_build + solve). Basis der Abrechnung. |
problem_size.dimensions | integer | Ja | Anzahl Dimensionen im Request. |
problem_size.entities | integer | Ja | Anzahl Entities im Request. |
problem_size.constraints | integer | Ja | Anzahl Constraints im Request. |
problem_size.variables | integer | Ja | Anzahl interner Solver-Variablen. Indikator für Problemgrösse. |
problem_size.cells | integer | Ja | Anzahl Zellen (Kombinationen aller Dimensions-Werte). |
placements_per_entity | object | Ja | Wie oft jede Entity in der Lösung platziert wurde. |
total_penalty | integer | Ja | Summe aller Soft-Verletzungs-Kosten in der Lösung. 0 = keine Soft-Verletzungen. |
best_bound | integer | Ja | Vom Solver bewiesene Untergrenze des Penalty. Bei total_penalty == best_bound ist die Lösung beweisbar optimal. |
gap_percent | float | Ja | (total_penalty - best_bound) / total_penalty × 100. 0 = optimal. |
soft_constraint_violations | array | Ja | Pro verletzter Soft-Constraint ein Eintrag mit constraint_id, type, violation_count, penalty_total. |
diagnostics
Nur bei Status infeasible oder unknown vorhanden. Hilft bei der Fehlersuche, warum der Solver keine Lösung gefunden hat.
Parameter
| Name | Typ | Status | Beschreibung |
|---|---|---|---|
message | string | Ja | Menschenlesbare Kurzzusammenfassung des Problems. |
capacity_conflicts | array | Optional | Liste der Dimensions-Werte, bei denen die Nachfrage grösser ist als die Kapazität. Pro Eintrag: dimension, value, min_demand, available_slots, entities. |
conflicting_constraints | array | Optional | Liste der Constraints, die das Problem unlösbar machen. Pro Eintrag: index, type, description. |