fhops.planning.tactical_operational Package
Tactical–operational planning contracts, period templates, scenario overlays, reporting, scale benchmarks, and tactical→operational handoff helpers introduced in Phase 6.
Typical usage:
from fhops.planning.tactical_operational import load_tactical_operational_scenario
from fhops.model.milp.tactical_operational import (
build_tactical_operational_bundle,
solve_tactical_operational_milp,
)
scenario = load_tactical_operational_scenario(
"tests/fixtures/tactical_operational/topm-mini/specification.yaml"
)
bundle = build_tactical_operational_bundle(scenario)
result = solve_tactical_operational_milp(bundle)
print(result["objective"], result["objective_components"])
Tactical–operational planning contract, loaders, and period utilities.
- class fhops.planning.tactical_operational.BlockRoadAccess(*, block_id, road_id)[source]
Bases:
BaseModelMapping from a planning unit to a road that can enable harvest access.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.Economics(*, currency='CAD', base_year=2026, discount_rate_per_year=0.0, objective_profile='min_discounted_delivered_cost')[source]
Bases:
BaseModelCurrency, base-year, discounting, and objective metadata for tactical planning.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.ExternalSupply(*, source_id, destination_id, product_id, period_id, minimum_m3=0.0, maximum_m3=None, delivered_cost_per_m3=0.0)[source]
Bases:
BaseModelOptional outside wood purchase source feeding a facility.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.Facility(*, facility_id, facility_type=None, accepted_products=<factory>, terminal_inventory_value_per_m3=None)[source]
Bases:
BaseModelMill, terminal, or customer that accepts one or more products.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.FacilityDemand(*, facility_id, product_id, period_id, minimum_m3=0.0, target_m3=None, maximum_m3=None, value_per_m3=None)[source]
Bases:
BaseModelFacility/product/period demand envelope and optional delivered product value.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.FleetCapacity(*, system_id, period_id, capacity_m3=None, capacity_hours=None)[source]
Bases:
BaseModelAggregate production capacity for a harvest system in one period.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.FleetOption(*, option_id, system_id, purchase_period_id, purchase_cost=0.0, capacity_m3_per_period, max_units=0, economic_life_periods=1)[source]
Bases:
BaseModelOptional fleet acquisition that adds system capacity over an economic life.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.HarvestSystemOption(*, option_id, block_id, system_id, period_id, eligible=True, min_area_ha=0.0, max_area_ha=None, variable_cost_per_m3=0.0, fixed_cost=0.0, productivity_m3_per_period=None)[source]
Bases:
BaseModelEligible block × system × period harvest option with quantity and cost bounds.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.InitialInventory(*, facility_id, product_id, opening_m3)[source]
Bases:
BaseModelOpening product inventory at a facility.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.PeriodLevel(value)[source]
Bases:
StrEnumSupported tactical–operational period resolutions.
- DAY = 'day'
- FOUR_WEEK = 'four_week'
- MONTH = 'month'
- SEASON = 'season'
- SHIFT = 'shift'
- WEEK = 'week'
- YEAR = 'year'
- class fhops.planning.tactical_operational.PlanningPeriod(*, period_id, level, sequence, start_date, end_date, duration_days=None, available_hours=None, parent_period_id=None, discount_factor=1.0, season_tags=<factory>)[source]
Bases:
BaseModelAggregate planning period with optional hierarchy and discounting metadata.
- Parameters:
- end_date: date
- level: PeriodLevel
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- start_date: date
- class fhops.planning.tactical_operational.PlanningUnit(*, block_id, gross_area_ha, operable_area_ha, forest_class=None, initial_state=None, product_yields_m3_per_ha=<factory>)[source]
Bases:
BaseModelAggregate harvestable unit with area and product yields.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.Product(*, product_id, species_group=None, grade=None)[source]
Bases:
BaseModelA product/species-grade tracked through harvest, transport, and facility inventory.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.RoadDependency(*, road_id, depends_on_road_id)[source]
Bases:
BaseModelDirected prerequisite relationship between two road projects.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.RoadProject(*, road_id, build_cost=0.0, maintenance_cost_per_period=0.0, earliest_period_id=None, capacity_m3_per_period=None)[source]
Bases:
BaseModelCandidate road project with activation timing, cost, and throughput capacity.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.SilvicultureTransition(*, transition_id, block_id, system_id, activity_id, earliest_period_id, cost_per_ha=0.0, required=True, next_state=None)[source]
Bases:
BaseModelRequired follow-up activity generated by a block/system harvest decision.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.TacticalOperationalScenario(*, name, planning_level='tactical_operational', schema_version='0.1.0', parent=None, overlay_id=None, source_hash=None, economics=<factory>, periods, products, planning_units, harvest_system_options, fleet_capacity=<factory>, facilities, facility_demand=<factory>, initial_inventory=<factory>, transport_arcs=<factory>, external_supply=<factory>, roads=<factory>, road_dependencies=<factory>, block_road_access=<factory>, silviculture_transitions=<factory>, fleet_options=<factory>)[source]
Bases:
BaseModelValidated aggregate planning contract for TOPM-inspired FHOPS scenarios.
The schema uses long-form, dimension-flexible tables. Cross-validation checks all period, product, block, system-option, facility, transport, inventory, and external-supply references.
- Parameters:
name (str)
planning_level (str)
schema_version (str)
parent (str | None)
overlay_id (str | None)
source_hash (str | None)
economics (Economics)
periods (list[PlanningPeriod])
planning_units (list[PlanningUnit])
harvest_system_options (list[HarvestSystemOption])
fleet_capacity (list[FleetCapacity])
facility_demand (list[FacilityDemand])
initial_inventory (list[InitialInventory])
transport_arcs (list[TransportArc])
external_supply (list[ExternalSupply])
roads (list[RoadProject])
road_dependencies (list[RoadDependency])
block_road_access (list[BlockRoadAccess])
silviculture_transitions (list[SilvicultureTransition])
fleet_options (list[FleetOption])
- block_road_access: list[BlockRoadAccess]
- external_supply: list[ExternalSupply]
- facility_demand: list[FacilityDemand]
- fleet_capacity: list[FleetCapacity]
- fleet_options: list[FleetOption]
- harvest_system_options: list[HarvestSystemOption]
- initial_inventory: list[InitialInventory]
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- periods: list[PlanningPeriod]
- planning_units: list[PlanningUnit]
- road_dependencies: list[RoadDependency]
- roads: list[RoadProject]
- silviculture_transitions: list[SilvicultureTransition]
- transport_arcs: list[TransportArc]
- class fhops.planning.tactical_operational.TransportArc(*, arc_id, origin_id, destination_id, product_id, mode='truck', period_id, cost_per_m3=0.0, capacity_m3=None, distance_km=None)[source]
Bases:
BaseModelEligible product flow arc from a block/origin to a facility for one period.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- fhops.planning.tactical_operational.children_by_parent(periods)[source]
Group child periods by parent period ID for roll-up reporting.
- Parameters:
periods (list[PlanningPeriod])
- Return type:
- fhops.planning.tactical_operational.four_week_periods(year, *, start_month=1, start_day=1, periods=13, discount_rate_per_year=0.0)[source]
Build thirteen (or a custom count of) four-week planning periods for a calendar year.
The final period is truncated at December 31 when the accounting calendar overflows the year. Discount factors are assigned at each period start using an effective annual rate.
- fhops.planning.tactical_operational.load_tactical_operational_scenario(yaml_path)[source]
Load and validate a TOPM-inspired tactical–operational scenario.
The loader accepts either inline YAML sections or a
data:mapping from section names to CSV files.topm-mini-style specifications may usefixture_id/specification_version; those aliases are normalized tonameandschema_versionbefore Pydantic validation.- Parameters:
- Return type:
- fhops.planning.tactical_operational.seasonal_periods(year, *, discount_rate_per_year=0.0)[source]
Build a conventional four-season calendar-year period template.
- Parameters:
- Return type:
- fhops.planning.tactical_operational.tactical_scenario_dimensions(scenario)[source]
Return model dimension counts for CLI output and telemetry.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
- fhops.planning.tactical_operational.tactical_scenario_to_dict(scenario)[source]
Serialize a tactical–operational scenario to a JSON-compatible dictionary.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
- fhops.planning.tactical_operational.validate_period_hierarchy(periods)[source]
Validate uniqueness, parent references, and chronological ordering of a period set.
- Parameters:
periods (list[PlanningPeriod])
- Return type:
None
Pydantic contract for TOPM-inspired tactical–operational planning scenarios.
The models in this module describe aggregate, multi-period planning inputs. They are intentionally
separate from fhops.scenario.contract.Scenario, which remains the stable schema 1.0.0
contract for detailed day/shift machine scheduling.
- class fhops.planning.tactical_operational.models.BlockRoadAccess(*, block_id, road_id)[source]
Bases:
BaseModelMapping from a planning unit to a road that can enable harvest access.
- block_id: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- road_id: str
- class fhops.planning.tactical_operational.models.Economics(*, currency='CAD', base_year=2026, discount_rate_per_year=0.0, objective_profile='min_discounted_delivered_cost')[source]
Bases:
BaseModelCurrency, base-year, discounting, and objective metadata for tactical planning.
- Parameters:
- base_year: int
- currency: str
- discount_rate_per_year: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- objective_profile: str
- class fhops.planning.tactical_operational.models.ExternalSupply(*, source_id, destination_id, product_id, period_id, minimum_m3=0.0, maximum_m3=None, delivered_cost_per_m3=0.0)[source]
Bases:
BaseModelOptional outside wood purchase source feeding a facility.
- Parameters:
- delivered_cost_per_m3: float
- destination_id: str
- minimum_m3: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- period_id: str
- product_id: str
- source_id: str
- class fhops.planning.tactical_operational.models.Facility(*, facility_id, facility_type=None, accepted_products=<factory>, terminal_inventory_value_per_m3=None)[source]
Bases:
BaseModelMill, terminal, or customer that accepts one or more products.
- Parameters:
- facility_id: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class fhops.planning.tactical_operational.models.FacilityDemand(*, facility_id, product_id, period_id, minimum_m3=0.0, target_m3=None, maximum_m3=None, value_per_m3=None)[source]
Bases:
BaseModelFacility/product/period demand envelope and optional delivered product value.
- Parameters:
- facility_id: str
- minimum_m3: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- period_id: str
- product_id: str
- class fhops.planning.tactical_operational.models.FleetCapacity(*, system_id, period_id, capacity_m3=None, capacity_hours=None)[source]
Bases:
BaseModelAggregate production capacity for a harvest system in one period.
- Parameters:
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- period_id: str
- system_id: str
- class fhops.planning.tactical_operational.models.FleetOption(*, option_id, system_id, purchase_period_id, purchase_cost=0.0, capacity_m3_per_period, max_units=0, economic_life_periods=1)[source]
Bases:
BaseModelOptional fleet acquisition that adds system capacity over an economic life.
- Parameters:
- capacity_m3_per_period: float
- economic_life_periods: int
- max_units: int
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- option_id: str
- purchase_cost: float
- purchase_period_id: str
- system_id: str
- class fhops.planning.tactical_operational.models.HarvestSystemOption(*, option_id, block_id, system_id, period_id, eligible=True, min_area_ha=0.0, max_area_ha=None, variable_cost_per_m3=0.0, fixed_cost=0.0, productivity_m3_per_period=None)[source]
Bases:
BaseModelEligible block × system × period harvest option with quantity and cost bounds.
- Parameters:
- block_id: str
- eligible: bool
- fixed_cost: float
- min_area_ha: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- option_id: str
- period_id: str
- system_id: str
- variable_cost_per_m3: float
- class fhops.planning.tactical_operational.models.InitialInventory(*, facility_id, product_id, opening_m3)[source]
Bases:
BaseModelOpening product inventory at a facility.
- facility_id: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- opening_m3: float
- product_id: str
- class fhops.planning.tactical_operational.models.PeriodLevel(value)[source]
Bases:
StrEnumSupported tactical–operational period resolutions.
- DAY = 'day'
- FOUR_WEEK = 'four_week'
- MONTH = 'month'
- SEASON = 'season'
- SHIFT = 'shift'
- WEEK = 'week'
- YEAR = 'year'
- class fhops.planning.tactical_operational.models.PlanningPeriod(*, period_id, level, sequence, start_date, end_date, duration_days=None, available_hours=None, parent_period_id=None, discount_factor=1.0, season_tags=<factory>)[source]
Bases:
BaseModelAggregate planning period with optional hierarchy and discounting metadata.
- Parameters:
- discount_factor: float
- end_date: date
- level: PeriodLevel
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- period_id: str
- sequence: int
- start_date: date
- class fhops.planning.tactical_operational.models.PlanningUnit(*, block_id, gross_area_ha, operable_area_ha, forest_class=None, initial_state=None, product_yields_m3_per_ha=<factory>)[source]
Bases:
BaseModelAggregate harvestable unit with area and product yields.
- Parameters:
- block_id: str
- gross_area_ha: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- operable_area_ha: float
- class fhops.planning.tactical_operational.models.Product(*, product_id, species_group=None, grade=None)[source]
Bases:
BaseModelA product/species-grade tracked through harvest, transport, and facility inventory.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- product_id: str
- class fhops.planning.tactical_operational.models.RoadDependency(*, road_id, depends_on_road_id)[source]
Bases:
BaseModelDirected prerequisite relationship between two road projects.
- depends_on_road_id: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- road_id: str
- class fhops.planning.tactical_operational.models.RoadProject(*, road_id, build_cost=0.0, maintenance_cost_per_period=0.0, earliest_period_id=None, capacity_m3_per_period=None)[source]
Bases:
BaseModelCandidate road project with activation timing, cost, and throughput capacity.
- Parameters:
- build_cost: float
- maintenance_cost_per_period: float
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- road_id: str
- class fhops.planning.tactical_operational.models.SilvicultureTransition(*, transition_id, block_id, system_id, activity_id, earliest_period_id, cost_per_ha=0.0, required=True, next_state=None)[source]
Bases:
BaseModelRequired follow-up activity generated by a block/system harvest decision.
- Parameters:
- activity_id: str
- block_id: str
- cost_per_ha: float
- earliest_period_id: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- required: bool
- system_id: str
- transition_id: str
- class fhops.planning.tactical_operational.models.TacticalOperationalScenario(*, name, planning_level='tactical_operational', schema_version='0.1.0', parent=None, overlay_id=None, source_hash=None, economics=<factory>, periods, products, planning_units, harvest_system_options, fleet_capacity=<factory>, facilities, facility_demand=<factory>, initial_inventory=<factory>, transport_arcs=<factory>, external_supply=<factory>, roads=<factory>, road_dependencies=<factory>, block_road_access=<factory>, silviculture_transitions=<factory>, fleet_options=<factory>)[source]
Bases:
BaseModelValidated aggregate planning contract for TOPM-inspired FHOPS scenarios.
The schema uses long-form, dimension-flexible tables. Cross-validation checks all period, product, block, system-option, facility, transport, inventory, and external-supply references.
- Parameters:
name (str)
planning_level (str)
schema_version (str)
parent (str | None)
overlay_id (str | None)
source_hash (str | None)
economics (Economics)
periods (list[PlanningPeriod])
planning_units (list[PlanningUnit])
harvest_system_options (list[HarvestSystemOption])
fleet_capacity (list[FleetCapacity])
facility_demand (list[FacilityDemand])
initial_inventory (list[InitialInventory])
transport_arcs (list[TransportArc])
external_supply (list[ExternalSupply])
roads (list[RoadProject])
road_dependencies (list[RoadDependency])
block_road_access (list[BlockRoadAccess])
silviculture_transitions (list[SilvicultureTransition])
fleet_options (list[FleetOption])
- block_road_access: list[BlockRoadAccess]
- dimension_summary()[source]
Return model-dimension counts used by CLI validation and telemetry.
- economics: Economics
- external_supply: list[ExternalSupply]
- facility_demand: list[FacilityDemand]
- fleet_capacity: list[FleetCapacity]
- fleet_options: list[FleetOption]
- harvest_system_options: list[HarvestSystemOption]
- initial_inventory: list[InitialInventory]
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str
- periods: list[PlanningPeriod]
- planning_level: str
- planning_units: list[PlanningUnit]
- road_dependencies: list[RoadDependency]
- roads: list[RoadProject]
- schema_version: str
- silviculture_transitions: list[SilvicultureTransition]
- to_dict()[source]
Return a JSON-compatible round-trip representation of the scenario.
- transport_arcs: list[TransportArc]
- class fhops.planning.tactical_operational.models.TransportArc(*, arc_id, origin_id, destination_id, product_id, mode='truck', period_id, cost_per_m3=0.0, capacity_m3=None, distance_km=None)[source]
Bases:
BaseModelEligible product flow arc from a block/origin to a facility for one period.
- Parameters:
- arc_id: str
- cost_per_m3: float
- destination_id: str
- mode: str
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- origin_id: str
- period_id: str
- product_id: str
YAML/CSV loaders for tactical–operational planning scenarios.
- fhops.planning.tactical_operational.io.load_tactical_operational_scenario(yaml_path)[source]
Load and validate a TOPM-inspired tactical–operational scenario.
The loader accepts either inline YAML sections or a
data:mapping from section names to CSV files.topm-mini-style specifications may usefixture_id/specification_version; those aliases are normalized tonameandschema_versionbefore Pydantic validation.- Parameters:
- Return type:
- fhops.planning.tactical_operational.io.tactical_scenario_dimensions(scenario)[source]
Return model dimension counts for CLI output and telemetry.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
- fhops.planning.tactical_operational.io.tactical_scenario_to_dict(scenario)[source]
Serialize a tactical–operational scenario to a JSON-compatible dictionary.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
Period templates and hierarchy helpers for tactical–operational planning.
- fhops.planning.tactical_operational.time.children_by_parent(periods)[source]
Group child periods by parent period ID for roll-up reporting.
- Parameters:
periods (list[PlanningPeriod])
- Return type:
- fhops.planning.tactical_operational.time.four_week_periods(year, *, start_month=1, start_day=1, periods=13, discount_rate_per_year=0.0)[source]
Build thirteen (or a custom count of) four-week planning periods for a calendar year.
The final period is truncated at December 31 when the accounting calendar overflows the year. Discount factors are assigned at each period start using an effective annual rate.
- fhops.planning.tactical_operational.time.seasonal_periods(year, *, discount_rate_per_year=0.0)[source]
Build a conventional four-season calendar-year period template.
- Parameters:
- Return type:
- fhops.planning.tactical_operational.time.validate_period_hierarchy(periods)[source]
Validate uniqueness, parent references, and chronological ordering of a period set.
- Parameters:
periods (list[PlanningPeriod])
- Return type:
None
Scenario overlays, diffs, batch runs, and reports for tactical–operational planning.
- fhops.planning.tactical_operational.scenario.apply_tactical_overlay_payload(base, overlay)[source]
Merge a sparse tactical overlay into a base scenario payload.
List sections are merged by their declared identifier field(s): matching rows are deep-updated, new rows are appended, and
_removemay contain identifiers to delete. Scalar sections such asnameandeconomicsare deep-updated recursively.
- fhops.planning.tactical_operational.scenario.diff_tactical_scenarios(base, candidate)[source]
Return a row-per-field diff between two validated tactical scenarios.
- Parameters:
base (TacticalOperationalScenario)
candidate (TacticalOperationalScenario)
- Return type:
DataFrame
- fhops.planning.tactical_operational.scenario.load_tactical_overlay_scenario(base_path, overlay_path)[source]
Load a base tactical scenario and apply a sparse overlay YAML.
- Parameters:
- Return type:
- fhops.planning.tactical_operational.scenario.markdown_tactical_summary(result)[source]
Render solver status and objective decomposition as a compact Markdown report.
- fhops.planning.tactical_operational.scenario.read_yaml_mapping(path)[source]
Read a YAML mapping from disk.
- fhops.planning.tactical_operational.scenario.scenario_content_hash(payload)[source]
Return a deterministic SHA-256 hash for a scenario payload.
- fhops.planning.tactical_operational.scenario.solve_tactical_batch_manifest(manifest_path, *, out_dir)[source]
Solve a manifest of tactical scenario cases and write per-case plus comparison outputs.
Manifest YAML format:
cases: - case_id: base scenario: path/to/base.yaml - case_id: low-demand scenario: path/to/base.yaml overlay: path/to/overlay.yaml enable_roads: true
- fhops.planning.tactical_operational.scenario.write_tactical_report(result, out_dir, *, formats='csv,markdown')[source]
Write normalized tactical result tables and a Markdown objective summary.
- fhops.planning.tactical_operational.scenario.write_tactical_scenario_yaml(scenario, path)[source]
Write a validated tactical scenario as a human-readable YAML mapping.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
None
Tactical→operational handoff and rolling-state helpers for Phase 6.
- class fhops.planning.tactical_operational.integration.TacticalCommitment(block_id, system_id, period_id, area_ha, total_volume_m3, product_volumes_m3=<factory>)[source]
Bases:
objectA selected aggregate block/system/period commitment.
- Parameters:
- area_ha: float
- block_id: str
- period_id: str
- system_id: str
- total_volume_m3: float
- class fhops.planning.tactical_operational.integration.TacticalRollingState(remaining_area_ha, remaining_product_volume_m3, facility_inventory_m3, active_roads, fleet_units, cumulative_costs, commitments)[source]
Bases:
objectAggregate state carried between tactical–operational planning iterations.
- Parameters:
- commitments: list[TacticalCommitment]
- fhops.planning.tactical_operational.integration.apply_operational_realization(state, assignments, *, yield_per_ha, block_map=None)[source]
Update block/product state from realized operational assignment production.
yield_per_hamaps operational block IDs to total m³/ha. Production is treated as aggregate delivered volume unless callers pre-aggregate product-specific flows and updatefacility_inventory_m3separately.
- fhops.planning.tactical_operational.integration.build_tactical_rolling_state(scenario, result)[source]
Build a rolling state snapshot from a tactical scenario and solve result.
- Parameters:
scenario (TacticalOperationalScenario)
- Return type:
TacticalRollingState
- fhops.planning.tactical_operational.integration.commitments_from_result(result)[source]
Extract selected harvest commitments from a tactical solve result payload.
- fhops.planning.tactical_operational.integration.compile_business_window_scenario(base, commitments, *, block_map=None, start_day=1, horizon_days=None)[source]
Compile tactical commitments into a filtered operational scenario.
The base operational scenario provides machines, calendars, production rates, landings, and mobilisation tables. Tactical commitments select eligible blocks and override their harvest system IDs. Block windows are clamped to the requested business window without rebasing days.
- fhops.planning.tactical_operational.integration.write_operational_scenario_bundle(scenario, out_dir)[source]
Write an operational scenario object as a YAML/CSV bundle compatible with
load_scenario.
Synthetic scale fixtures and benchmark helpers for tactical–operational planning.
- class fhops.planning.tactical_operational.scale.TacticalScaleConfig(num_blocks=100, years=1, periods_per_year=4, num_products=2, num_facilities=2, num_systems=2, seed=44, demand_fraction=0.25)[source]
Bases:
objectConfiguration for a deterministic tactical–operational scale scenario.
- Parameters:
- demand_fraction: float = 0.25
- num_blocks: int = 100
- num_facilities: int = 2
- num_products: int = 2
- num_systems: int = 2
- periods_per_year: int = 4
- seed: int = 44
- years: int = 1
- fhops.planning.tactical_operational.scale.generate_tactical_scale_scenario(config)[source]
Generate a deterministic TOPM-shaped scale scenario.
The generator is intentionally simple and synthetic: it creates a rectangular block × system × period eligibility grid with product yields, fleet capacity, facility demand, transport arcs, and optional outside supply. It is meant for model-size/runtime envelopes, not ecological realism.
- Parameters:
config (TacticalScaleConfig)
- Return type:
- fhops.planning.tactical_operational.scale.run_tactical_scale_benchmark(configs, *, solver='highs', time_limit=None, gap=None)[source]
Solve generated tactical scenarios and return scale/timing/model-size telemetry.