Skip to content

gds_business.supplychain.model

SupplyChainModel — declarative container for supply chain networks.

Bases: BaseModel

A complete supply chain network declaration.

Validates at construction: 1. At least one node 2. No duplicate node names 3. Shipment source/target reference declared nodes 4. Demand target references a declared node 5. OrderPolicy node references a declared node 6. OrderPolicy inputs reference declared nodes

Source code in packages/gds-business/gds_business/supplychain/model.py
class SupplyChainModel(BaseModel):
    """A complete supply chain network declaration.

    Validates at construction:
    1. At least one node
    2. No duplicate node names
    3. Shipment source/target reference declared nodes
    4. Demand target references a declared node
    5. OrderPolicy node references a declared node
    6. OrderPolicy inputs reference declared nodes
    """

    name: str
    nodes: list[SupplyNode]
    shipments: list[Shipment] = Field(default_factory=list)
    demand_sources: list[DemandSource] = Field(default_factory=list)
    order_policies: list[OrderPolicy] = Field(default_factory=list)
    description: str = ""

    @model_validator(mode="after")
    def _validate_structure(self) -> Self:
        errors: list[str] = []

        # 1. At least one node
        if not self.nodes:
            errors.append("Supply chain must have at least one node")

        # 2. No duplicate node names
        names: list[str] = [n.name for n in self.nodes]
        seen: set[str] = set()
        for n in names:
            if n in seen:
                errors.append(f"Duplicate node name: {n!r}")
            seen.add(n)

        node_names = set(names)

        # 3. Shipment source/target reference declared nodes
        for s in self.shipments:
            if s.source not in node_names:
                errors.append(
                    f"Shipment {s.name!r} source {s.source!r} is not a declared node"
                )
            if s.target not in node_names:
                errors.append(
                    f"Shipment {s.name!r} target {s.target!r} is not a declared node"
                )

        # 4. Demand target references a declared node
        for d in self.demand_sources:
            if d.target not in node_names:
                errors.append(
                    f"DemandSource {d.name!r} target {d.target!r} "
                    f"is not a declared node"
                )

        # 5. OrderPolicy node references a declared node
        for op in self.order_policies:
            if op.node not in node_names:
                errors.append(
                    f"OrderPolicy {op.name!r} node {op.node!r} is not a declared node"
                )

        # 6. OrderPolicy inputs reference declared nodes
        for op in self.order_policies:
            for inp in op.inputs:
                if inp not in node_names:
                    errors.append(
                        f"OrderPolicy {op.name!r} input {inp!r} is not a declared node"
                    )

        if errors:
            raise BizValidationError(
                f"SupplyChainModel {self.name!r} validation failed:\n"
                + "\n".join(f"  - {e}" for e in errors)
            )
        return self

    # ── Convenience properties ──────────────────────────────

    @property
    def node_names(self) -> set[str]:
        return {n.name for n in self.nodes}

    # ── Compilation ─────────────────────────────────────────

    def compile(self) -> GDSSpec:
        """Compile this model to a GDS specification."""
        from gds_business.supplychain.compile import compile_scn

        return compile_scn(self)

    def compile_system(self) -> SystemIR:
        """Compile this model to a flat SystemIR for verification + visualization."""
        from gds_business.supplychain.compile import compile_scn_to_system

        return compile_scn_to_system(self)

compile()

Compile this model to a GDS specification.

Source code in packages/gds-business/gds_business/supplychain/model.py
def compile(self) -> GDSSpec:
    """Compile this model to a GDS specification."""
    from gds_business.supplychain.compile import compile_scn

    return compile_scn(self)

compile_system()

Compile this model to a flat SystemIR for verification + visualization.

Source code in packages/gds-business/gds_business/supplychain/model.py
def compile_system(self) -> SystemIR:
    """Compile this model to a flat SystemIR for verification + visualization."""
    from gds_business.supplychain.compile import compile_scn_to_system

    return compile_scn_to_system(self)