domain-level constraints

This commit is contained in:
2026-03-04 16:53:58 -06:00
parent 00cc8dd9ef
commit 843baa15ad
11 changed files with 188 additions and 21 deletions

View File

@@ -7,7 +7,7 @@ import pytest
from physcom.db.schema import init_db
from physcom.db.repository import Repository
from physcom.models.entity import Entity, Dependency
from physcom.models.domain import Domain, MetricBound
from physcom.models.domain import Domain, DomainConstraint, MetricBound
from physcom.models.combination import Combination
@@ -225,4 +225,5 @@ def urban_domain():
MetricBound("availability", weight=0.15, norm_min=0.0, norm_max=1.0),
MetricBound("range_fuel", weight=0.10, norm_min=5000, norm_max=500000),
],
constraints=[DomainConstraint("medium", ["ground", "air"])],
)

View File

@@ -2,6 +2,7 @@
from physcom.engine.constraint_resolver import ConstraintResolver
from physcom.models.combination import Combination
from physcom.models.domain import DomainConstraint
from physcom.models.entity import Entity, Dependency
@@ -140,3 +141,22 @@ def test_energy_density_no_constraint_if_no_provider():
result = resolver.resolve(combo)
density_violations = [v for v in result.violations if "energy density" in v]
assert len(density_violations) == 0
def test_domain_constraint_blocks_wrong_medium(spaceship, solar_sail, solar_radiation):
"""Spaceship (space medium) should be blocked in a ground-only domain."""
resolver = ConstraintResolver()
combo = Combination(entities=[spaceship, solar_sail, solar_radiation])
constraints = [DomainConstraint("medium", ["ground", "air"])]
result = resolver.check_domain_constraints(combo, constraints)
assert result.status == "p1_fail"
assert any("medium" in v for v in result.violations)
def test_domain_constraint_allows_matching_medium(bicycle, human_pedalling, food_calories):
"""Bicycle (ground medium) should pass a ground+air domain constraint."""
resolver = ConstraintResolver()
combo = Combination(entities=[bicycle, human_pedalling, food_calories])
constraints = [DomainConstraint("medium", ["ground", "air"])]
result = resolver.check_domain_constraints(combo, constraints)
assert result.status == "valid"

View File

@@ -251,10 +251,10 @@ def test_blocked_combos_have_results(seeded_repo):
assert total_with_results == result.pass1_failed + result.pass3_scored
# Failed combos should have pass_reached=1 and composite_score=0.0
failed_results = [r for r in all_results if r["combination"].status == "p1_fail"]
# (includes both entity-blocked and domain-blocked combos)
failed_results = [r for r in all_results if r["pass_reached"] == 1]
assert len(failed_results) == result.pass1_failed
for br in failed_results:
assert br["pass_reached"] == 1
assert br["composite_score"] == 0.0