Skip to content

Example 8: Production under equipment man-hours ​

1. Overview ​

This bounded context chooses non-negative integer production quantities to maximize product profit under equipment man-hour capacities. The page follows the current Demo8 data and model; the code tabs are model-building fragments whose data is supplied by the source files.

The product profits are (123,94,105,132,118). Equipment amounts and per-product man-hours are:

EquipmentAmountP1P2P3P4P5
A12.23.44.17.08.36
B14.13–.20.37.19
C8–.25.34–.18
D6.55.72–.61–

Each equipment unit supplies at most 2000 man-hours. A dash denotes a missing source-map coefficient.

1. Dependent Contexts ​

  1. None. No external domain context is required.

2. Concepts / Entities ​

1. Product ​

A product can be produced in an integer quantity and contributes a fixed profit per unit.

Profitp: profit contributed by one unit of product p.

2. Equipment Type ​

An equipment type has several available units and consumes a product-specific number of man-hours for every produced unit.

Amounte: number of available units of equipment type e.

ManHoursep: man-hours of equipment type e required by one unit of product p, defined only for entries present in the source map.

ManHoursMax: maximum man-hours supplied by one equipment unit; the current value is 2000.


3. Variables ​

1. Decision Variables ​

xp: production quantity of product p, measured in product units, integer and non-negative, domain Z≥0, ∀p∈P. The Kotlin source uses UIntVariable1; the Rust source uses VariableCombination1D<UInteger>.

2. Auxiliary Variables ​

There are no separately declared auxiliary decision variables. Profit and ManHours_e are registered derived symbols.


4. Predicates ​

1. Equipment Usage Predicate ​

This predicate identifies coefficients that participate in a particular equipment expression.

Uses(e,p): true when the source has a non-missing e.manHours[p] coefficient. A missing map entry is omitted from the sum; the Rust data represents it with 0.00 and filters zero coefficients.


5. Sets ​

1. Product and Equipment Categories ​

P: universal set of products.

E: universal set of equipment types.

Pe: products with a defined man-hour coefficient for equipment e, Pe={p∈P∣Uses(e,p)}.

2. Entity Pairs / Relations ​

EquipmentUse: relation {(e,p)in E\times P\mid \mathrm{Uses}(e,p)\}.


6. Intermediate Values ​

1. Total Profit ​

Description: Total profit generated by all production quantities.

Profit=∑p∈PProfitpxp.

2. Equipment Man-Hours ​

Description: Total man-hours consumed on equipment type e by the products for which the source defines a coefficient. The coefficient is a time quantity, not a monetary cost.

ManHourse=∑p∈PeManHoursepxp,∀e∈E.

3. Equipment Capacity ​

Description: Total available man-hours of equipment type e, obtained by multiplying the number of units by the per-unit maximum.

Capacitye=AmounteManHoursMax,qquad∀e∈E.

Capacity_e is a documentation-level derived value; the current source writes the product directly in each constraint.


7. Assertions ​

1. Missing Coefficients Consume No Modeled Hours ​

Description: A product absent from an equipment map does not occur in that equipment's expression.

∀e∈E, p∉Pe⟹[xp]ManHourse=0.

2. Capacity Is Non-Negative ​

Description: Equipment amounts and the per-unit maximum are non-negative, so every equipment capacity is non-negative.

∀e∈E(Amounte≥0∧ManHoursMax≥0⟹Capacitye≥0).

3. Historical Solver Observation ​

Description: A previous run reported (x1,x2,x3,x4,x5)=(0,0,18771,19672,53431). The current structure test checks model construction only, so this value is informative rather than a pinned invariant.


8. Constraints ​

1. Equipment Man-Hour Capacity (设备工时容量约束) ​

Description: Production assigned to an equipment type cannot consume more hours than all available units provide.

s.t.ManHourse≤AmounteManHoursMax,qquad∀e∈E.

2. Production Domain (产量定义域约束) ​

Description: Every product quantity is a non-negative integer.

s.t.xp∈Z≥0,qquad∀p∈P.

9. Objective Function (if applicable) ​

Description: Maximize total product profit.

maxProfit.

10. Algorithm References ​

No standalone algorithm document is referenced. The model is registered as linear expressions and solved through the current Kotlin LinearMetaModel/SCIP path or Rust MetaModel/solver path.

Algorithm NameFile PathReferenced InBrief Description
None——No standalone algorithm is needed.

11. Ubiquitous Language ​

TermSymbolDefinition
Productp∈PItem whose integer production quantity is selected.
Equipmente∈EResource type with a finite number of units and hours.
ProfitProfitTotal value of production.
Man-hoursManHourseHours consumed on equipment type e.
CapacityCapacityeHours supplied by equipment type e.

12. Design Decisions ​

DecisionAlternativesRationaleDate
Keep production integral and unbounded above except through capacitiesContinuous production or hand-added product boundsMatches UIntVariable1/UInteger in the current sources2026-09-08
Omit missing equipment coefficientsTreat every dash as an explicit business penaltyThe Kotlin map omits the key and Rust filters zero coefficients2026-09-08
Preserve the name ManHoursRename it to CostThe coefficient has time units; Cost would misstate the physical meaning2026-09-08

Minimal current model-building snippets ​

products and equipments/equipment come from Demo8.kt and demo8.rs; the converter and solver setup are also source-owned. These fragments show the registered symbols and constraints only.

kotlin
// `products`, `equipments`, `maxManHours`, and `flt64Converter` come from Demo8.kt.
val metaModel = LinearMetaModel<Flt64>("demo8", converter = flt64Converter)
val x = UIntVariable1("x", Shape1(products.size))
val profit = LinearExpressionSymbol(
    sum(products.map { p -> p.profit * x[p] }),
    name = "profit"
)
val manHours = LinearIntermediateSymbols1<Flt64>(
    "man_hours",
    Shape1(equipments.size)
) { i, _ ->
    val e = equipments[i]
    LinearExpressionSymbol(
        sum(products.mapNotNull { p -> e.manHours[p]?.let { it * x[p] } }),
        name = "man_hours_${e.index}"
    )
}
metaModel.add(x)
metaModel.add(profit)
metaModel.add(manHours)
metaModel.maximize(profit, "profit")
for (e in equipments) {
    metaModel.addConstraint(
        manHours[e] leq e.amount.toFlt64() * maxManHours,
        name = "eq_man_hours_${e.index}"
    )
}
rust
// `products` and `equipments` come from demo8.rs.
let mut model = MetaModel::<f64>::new("demo8");
let x: VariableCombination1D<UInteger> =
    VariableCombination1D::new(Shape::new([products.len()]), "x");
let x_idx = model.register_combination(&x)?;
let profit = flat_map1_indexed("profit", products, |i, product| {
    ospf_rust_core::symbol::flatten::Linear::new(
        vec![ospf_rust_core::symbol::flatten::LinearMonomial::new(
            product.profit, x_idx[i],
        )],
        0.0,
    )
}, |_, product| product.name.clone());
model.add_symbol_combination(&profit)?;
let man_hours = flat_map1("man_hours", equipments, |equipment| {
    let monomials = products.iter().enumerate().filter_map(|(p, _)| {
        let value = equipment.man_hours_by_product[p];
        (value != 0.0).then(||
            ospf_rust_core::symbol::flatten::LinearMonomial::new(value, x_idx[p])
        )
    }).collect();
    ospf_rust_core::symbol::flatten::Linear::new(monomials, 0.0)
}, |_, equipment| equipment.name.clone());
model.add_symbol_combination(&man_hours)?;
let profit_coeffs = extract_coeffs(&profit[0]);
model.add_linear_objective(&profit_coeffs, "profit");
model.set_objective_category(ObjectiveCategory::Maximum);
for (e, equipment) in equipments.iter().enumerate() {
    model.add_linear_constraint(
        &extract_coeffs(&man_hours[e]), ConstraintRelation::LessEqual,
        equipment.amount * max_man_hours, &format!("equipment_{}_{}", e, equipment.name),
    )?;
}

13. Change Log ​

VersionChangeReason
2026-09-08Reorganized the page into the domain-model template; added quantified intermediate values, bilingual constraint names, and Kotlin/Rust tabsAlign documentation with the current Demo8 implementations

Source and verification ​