Lab 1: Small Low-Altitude Ontology and Rule Encoding#
Related chapters: Ch. 5 (Domain Knowledge Modeling) · Ch. 6 (KG Construction)
This lab builds a minimal runnable “domain knowledge modeling + rule encoding” pipeline. It demonstrates how to turn Chapter 5 domain objects and Chapter 6’s three-layer ontology / rule-layer ideas into executable Python data structures.
Design#
EntityType / RelationType — concept-layer entity and relation types
Rule / MinSeparationRule / NoFlyZoneRule — executable rules in the rule layer
LowAltitudeOntology — unified entity types, relation types, facts, and rules
build_demo_ontology() — construct a small low-altitude example
print_summary() — print ontology, facts, and rule firings
Key concepts#
Domain taxonomy: Aircraft, Airspace, Mission, Facility, Operator
Relations: in_zone, distance_between, assigned_to, operated_by
Rule objects: separation constraints, restricted airspace
Knowledge substrate: concept, instance, and rule layers
Symbolic reasoning: explicit rule matching and alerting
How to run#
python lab1_ontology_rules.py
Source code#
from dataclasses import dataclass, field
from typing import Dict, List, Tuple
@dataclass
class EntityType:
name: str
attributes: List[str]
@dataclass
class RelationType:
name: str
subject_type: str
object_type: str
@dataclass
class Rule:
name: str
description: str
def evaluate(self, facts: Dict[str, List[Tuple]]) -> List[str]:
raise NotImplementedError
@dataclass
class MinSeparationRule(Rule):
min_distance: float
def evaluate(self, facts: Dict[str, List[Tuple]]) -> List[str]:
alerts = []
for uav_a, uav_b, distance in facts.get("distance_between", []):
if distance < self.min_distance:
alerts.append(
f"[{self.name}] Separation between {uav_a} and {uav_b} is {distance:.1f} m, "
f"below minimum safe distance {self.min_distance:.1f} m"
)
return alerts
@dataclass
class NoFlyZoneRule(Rule):
def evaluate(self, facts: Dict[str, List[Tuple]]) -> List[str]:
alerts = []
zones = {uav: zone for uav, zone in facts.get("in_zone", [])}
restricted = {zone for zone, zone_type in facts.get("zone_type", []) if zone_type == "restricted"}
for uav, zone in zones.items():
if zone in restricted:
alerts.append(f"[{self.name}] {uav} entered restricted airspace {zone}")
return alerts
@dataclass
class LowAltitudeOntology:
entity_types: Dict[str, EntityType] = field(default_factory=dict)
relation_types: Dict[str, RelationType] = field(default_factory=dict)
facts: Dict[str, List[Tuple]] = field(default_factory=dict)
rules: List[Rule] = field(default_factory=list)
def add_entity_type(self, name: str, attributes: List[str]) -> None:
self.entity_types[name] = EntityType(name=name, attributes=attributes)
def add_relation_type(self, name: str, subject_type: str, object_type: str) -> None:
self.relation_types[name] = RelationType(name=name, subject_type=subject_type, object_type=object_type)
def add_fact(self, relation: str, fact: Tuple) -> None:
self.facts.setdefault(relation, []).append(fact)
def run_rules(self) -> List[str]:
messages = []
for rule in self.rules:
messages.extend(rule.evaluate(self.facts))
return messages
def build_demo_ontology() -> LowAltitudeOntology:
ontology = LowAltitudeOntology()
ontology.add_entity_type("Aircraft", ["id", "speed", "altitude", "status"])
ontology.add_entity_type("Airspace", ["zone_id", "zone_type"])
ontology.add_entity_type("Mission", ["mission_id", "priority"])
ontology.add_entity_type("Facility", ["facility_id", "kind"])
ontology.add_entity_type("Operator", ["operator_id", "name"])
ontology.add_relation_type("in_zone", "Aircraft", "Airspace")
ontology.add_relation_type("distance_between", "Aircraft", "Aircraft")
ontology.add_relation_type("assigned_to", "Aircraft", "Mission")
ontology.add_relation_type("operated_by", "Aircraft", "Operator")
ontology.add_fact("in_zone", ("UAV-01", "ZONE-R1"))
ontology.add_fact("in_zone", ("UAV-02", "ZONE-N1"))
ontology.add_fact("zone_type", ("ZONE-R1", "restricted"))
ontology.add_fact("zone_type", ("ZONE-N1", "normal"))
ontology.add_fact("distance_between", ("UAV-01", "UAV-02", 78.0))
ontology.add_fact("assigned_to", ("UAV-01", "MISSION-EMERGENCY"))
ontology.add_fact("operated_by", ("UAV-01", "OP-ALPHA"))
ontology.rules.append(
MinSeparationRule(
name="Minimum separation rule",
description="Distance between any two aircraft must be at least 100 m",
min_distance=100.0,
)
)
ontology.rules.append(
NoFlyZoneRule(
name="No-fly zone rule",
description="Aircraft must not enter restricted airspace",
)
)
return ontology
def print_summary(ontology: LowAltitudeOntology) -> None:
print("=== Ontology summary ===")
print("Entity types:")
for entity in ontology.entity_types.values():
print(f"- {entity.name}: {', '.join(entity.attributes)}")
print("\nRelation types:")
for relation in ontology.relation_types.values():
print(f"- {relation.name}: {relation.subject_type} -> {relation.object_type}")
print("\nFacts:")
for relation, relation_facts in ontology.facts.items():
for fact in relation_facts:
print(f"- {relation}{fact}")
print("\nRule firings:")
for alert in ontology.run_rules():
print(f"- {alert}")
if __name__ == "__main__":
demo = build_demo_ontology()
print_summary(demo)