Skip to content

Reasoners API Reference

This page documents the reasoners used in BOOMER.

Reasoner Interface

@dataclass
class Reasoner(ABC):
    """Abstract base class for reasoners."""

    @abstractmethod
    def reason(self, kb: KB, selections: List[Grounding], candidates: List[Grounding] | None = None) -> ReasonerResult:
        """
        Perform reasoning on a knowledge base with a set of selections.

        Args:
            kb: The knowledge base to reason over
            selections: Current selections (facts with truth values)
            candidates: Optional list of candidate facts to consider

        Returns:
            A ReasonerResult with entailed selections and unsatisfiable facts
        """
        pass

ReasonerResult

@dataclass
class ReasonerResult:
    """
    Result of reasoning.

    Attributes:
        unsatisfiable_facts: List of facts that make the KB unsatisfiable
        entailed_selections: List of selections entailed by the KB and current selections
    """
    unsatisfiable_facts: List[Fact]
    entailed_selections: List[Grounding]

    @property
    def satisfiable(self) -> bool:
        """Return True if the knowledge base is satisfiable with the given selections."""
        return len(self.unsatisfiable_facts) == 0

NxReasoner

class NxReasoner(Reasoner):
    """
    Reasoner that uses a networkx graph to reason about the KB.

    This reasoner builds a directed graph representing the relationships
    between entities and performs reasoning operations on this graph.
    """

    def reason(self, kb: KB, selections: List[Grounding], candidates: List[PFactIndex] | None = None) -> ReasonerResult:
        """
        Perform reasoning using NetworkX graph operations.

        Args:
            kb: The knowledge base to reason over
            selections: Current selections (facts with truth values)
            candidates: Optional list of candidate facts to consider

        Returns:
            A ReasonerResult with entailed selections and unsatisfiable facts
        """

Utility Functions

get_reasoner

def get_reasoner(reasoner_class: str) -> Reasoner:
    """
    Get a reasoner instance by class name.

    Args:
        reasoner_class: The fully qualified class name of the reasoner

    Returns:
        An instance of the specified reasoner

    Raises:
        ImportError: If the reasoner class cannot be imported
        AttributeError: If the reasoner class cannot be found in the module
    """

filter_unsats

def filter_unsats(fact_states: List[Tuple[bool, PFactIndex, Fact]]) -> List[Fact]:
    """
    Filter unsatisfiable facts from fact states.

    Args:
        fact_states: List of (truth_value, index, fact) tuples

    Returns:
        List of unsatisfiable facts
    """

Usage Example

from boomer.model import KB, PFact, EquivalentTo
from boomer.reasoners.nx_reasoner import NxReasoner
from boomer.reasoners import get_reasoner

# Create a knowledge base
kb = KB(
    pfacts=[
        PFact(fact=EquivalentTo(sub="A", equivalent="B"), prob=0.9),
        PFact(fact=EquivalentTo(sub="B", equivalent="C"), prob=0.8),
    ]
)

# Create a reasoner directly
reasoner = NxReasoner()

# Or get a reasoner by class name
reasoner = get_reasoner("boomer.reasoners.nx_reasoner.NxReasoner")

# Define some selections (fact index, truth value)
selections = [(0, True), (1, False)]  # A=B is true, B=C is false

# Perform reasoning
result = reasoner.reason(kb, selections)

# Check if the result is satisfiable
if result.satisfiable:
    print("The knowledge base is satisfiable with the given selections")
    print("Entailed selections:", result.entailed_selections)
else:
    print("The knowledge base is unsatisfiable with the given selections")
    print("Unsatisfiable facts:", result.unsatisfiable_facts)

Creating Custom Reasoners

To create a custom reasoner, implement the Reasoner interface:

from boomer.reasoners.reasoner import Reasoner, ReasonerResult
from boomer.model import KB, Grounding, Fact

class MyCustomReasoner(Reasoner):
    def reason(self, kb: KB, selections: List[Grounding], candidates: List[Grounding] | None = None) -> ReasonerResult:
        # Implement your reasoning logic here
        # ...

        # Return a ReasonerResult with:
        # 1. Unsatisfiable facts (empty list if satisfiable)
        # 2. Entailed selections
        return ReasonerResult(
            unsatisfiable_facts=[],
            entailed_selections=selections
        )