from __future__ import annotations
from dataclasses import dataclass
from typing import Optional
@dataclass(frozen=True)
class BDDNode:
"""Nœud d'un BDD (Binary Decision Diagram).
Forme terminale : variable=None, value∈{True,False}, enfants=None.
Forme interne : variable=str, child_false/child_true=BDDNode, value=None.
"""
variable: Optional[str] = None
child_false: Optional["BDDNode"] = None
child_true: Optional["BDDNode"] = None
value: Optional[bool] = None
@property
def is_terminal(self) -> bool:
return self.variable is None
@staticmethod
def create(variable: str, child_false: "BDDNode", child_true: "BDDNode") -> "BDDNode":
# Réduction : si les deux enfants sont identiques, retourner l'enfant.
if child_false == child_true:
return child_false
return BDDNode(variable=variable, child_false=child_false, child_true=child_true)
def evaluate(self, assignment: dict[str, bool]) -> bool:
"""Évalue le BDD pour une assignation de variables."""
if self.is_terminal:
assert self.value is not None
return self.value
var_value = assignment.get(self.variable, False)
child = self.child_true if var_value else self.child_false
assert child is not None
return child.evaluate(assignment)
def count_nodes(self) -> int:
"""Compte le nombre de nœuds (uniques par référence) dans le BDD."""
if self.is_terminal:
return 1
assert self.child_false is not None and self.child_true is not None
return 1 + self.child_false.count_nodes() + self.child_true.count_nodes()
def pretty(self, indent: str = "") -> str:
if self.is_terminal:
return f"{indent}({self.value})"
assert self.child_false is not None and self.child_true is not None
lines = [f"{indent}{self.variable}?"]
lines.append(f"{indent} |-> {self.child_true.pretty(indent + ' |').strip()}")
lines.append(f"{indent} |-> {self.child_false.pretty(indent + ' |').strip()}")
return "\n".join(lines)
def __str__(self) -> str:
return self.pretty()
# Terminaux (singletons immuables/hashables).
BDD_TRUE = BDDNode(value=True)
BDD_FALSE = BDDNode(value=False)
print("Classe BDDNode définie avec succès.")
print("Opérations disponibles :")
print(" - BDD_TRUE / BDD_FALSE : Terminaux (feuilles)")
print(" - BDDNode.create(var, low, high) : Crée un nœud de décision")
print(" - node.evaluate(assign) : Évalue le BDD")
print(" - node.count_nodes() : Compte les nœuds")Classe BDDNode définie avec succès.
Opérations disponibles :
- BDD_TRUE / BDD_FALSE : Terminaux (feuilles)
- BDDNode.create(var, low, high) : Crée un nœud de décision
- node.evaluate(assign) : Évalue le BDD
- node.count_nodes() : Compte les nœuds