# Constraints
Constraints define the feasible region of optimization problems. Constraints can be equality
or inequality types, and can be temporarily removed while preserving their definition.
```rust
use ommx::{Constraint, Function, Linear, linear, coeff};
// Create constraints: x1 + x2 <= 10 (as x1 + x2 - 10 <= 0)
let constraint_expr = coeff!(1.0) * linear!(1) + coeff!(1.0) * linear!(2) + Linear::from(coeff!(-10.0));
let constraint = Constraint::less_than_or_equal_to_zero(Function::from(constraint_expr));
// Equality constraint: x1 - x2 = 0 (as f(x) = 0)
let eq_expr = coeff!(1.0) * linear!(1) - coeff!(1.0) * linear!(2);
let eq_constraint = Constraint::equal_to_zero(Function::from(eq_expr));
```
## Constraint Type System
OMMX supports four first-class constraint types:
- **[`Constraint`](crate::Constraint)** — standard equality / inequality
constraints on a [`Function`](crate::Function).
- **[`IndicatorConstraint`](crate::IndicatorConstraint)** —
`indicator_variable = 1 → f(x) {=,<=} 0`, keyed by
[`IndicatorConstraintID`](crate::IndicatorConstraintID).
- **[`OneHotConstraint`](crate::OneHotConstraint)** — exactly one of a
set of binary variables is 1, keyed by
[`OneHotConstraintID`](crate::OneHotConstraintID).
- **[`Sos1Constraint`](crate::Sos1Constraint)** — at most one of a set
of variables is non-zero, keyed by
[`Sos1ConstraintID`](crate::Sos1ConstraintID).
Each constraint type also has its own independent ID type to prevent
accidental cross-type lookups, and each ID lives on the enclosing
[`BTreeMap`](std::collections::BTreeMap) key rather than on the
constraint struct.
### Stage parameter
Each constraint type follows the **Stage pattern** — parameterized by
lifecycle phase, with three inhabited stages:
- `Created` — the constraint as defined in the problem, carrying its
[`Function`](crate::Function).
- `Evaluated` — the result of evaluating the constraint against a
single [`State`](crate::v1::State); carries `evaluated_value`,
`feasible`, `dual_variable`, and the set of variable IDs it used.
- `Sampled` — the result of evaluating against a
[`Sampled<State>`](crate::Sampled); carries per-sample evaluated
values and feasibility.
Each constraint type implements the
[`ConstraintType`](crate::ConstraintType) trait, which maps all three
stages as associated types — a defunctionalization of `Stage → Type`
since Rust lacks HKTs. "Removed" is **not** a stage: removal is
collection-level metadata tracked as a
[`RemovedReason`](crate::RemovedReason) paired with the original
`Created` constraint.
### Collections
Three generic collection wrappers handle constraints uniformly:
- [`ConstraintCollection`](crate::ConstraintCollection) —
active + removed, used in [`Instance`](crate::Instance). Removed
constraints are stored as `(T::Created, RemovedReason)` tuples.
- [`EvaluatedCollection`](crate::EvaluatedCollection) — evaluation
results, used in [`Solution`](crate::Solution).
- [`SampledCollection`](crate::SampledCollection) — sampled results,
used in [`SampleSet`](crate::SampleSet).
To add a new constraint type, see the docs on
[`ConstraintType`](crate::ConstraintType).