Agentic Architecture Pattern: Logical Reasoning

Written by

in


    """
Pattern 209: Logical Reasoning Pattern

Applies formal logic, propositional and predicate logic to derive conclusions.
Handles logical operators (AND, OR, NOT), quantifiers, and logical proofs.
"""

from typing import Dict, Any, List, Optional, Set
from dataclasses import dataclass, field
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI


class LogicalOperator(Enum):
    """Logical operators."""
    AND = "AND"
    OR = "OR"
    NOT = "NOT"
    IMPLIES = "=>"
    IFF = ""  # if and only if


@dataclass
class Proposition:
    """Logical proposition."""
    statement: str
    truth_value: Optional[bool] = None
    variables: Set[str] = field(default_factory=set)


@dataclass
class LogicalRule:
    """Logical inference rule."""
    premises: List[str]
    conclusion: str
    rule_name: str = "modus_ponens"


@dataclass
class LogicalArgument:
    """Complete logical argument."""
    premises: List[Proposition]
    conclusion: Proposition
    is_valid: Optional[bool] = None
    proof_steps: List[str] = field(default_factory=list)


class LogicalReasoningAgent:
    """Agent that performs logical reasoning."""
    
    def __init__(self, name: str, model_name: str = "gpt-4"):
        self.name = name
        self.llm = ChatOpenAI(model=model_name, temperature=0.1)  # Low temp for logic
        self.knowledge_base: List[Proposition] = []
        self.rules: List[LogicalRule] = []
    
    def add_proposition(self, prop: Proposition):
        """Add proposition to knowledge base."""
        self.knowledge_base.append(prop)
        print(f"  Added: {prop.statement} = {prop.truth_value}")
    
    def evaluate_logical_expression(self, expression: str, 
                                    context: Dict[str, bool]) -> bool:
        """Evaluate logical expression given variable values."""
        prompt = ChatPromptTemplate.from_messages([
            ("system", "Evaluate logical expression. Answer only TRUE or FALSE."),
            ("human", """Expression: {expression}
Variable values: {context}

What is the truth value? (TRUE or FALSE)""")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({
            "expression": expression,
            "context": str(context)
        })
        
        return "TRUE" in response.content.upper()
    
    def check_validity(self, argument: LogicalArgument) -> bool:
        """Check if logical argument is valid."""
        print(f"\n  {self.name}: Checking argument validity...")
        
        premises_text = "\n".join([f"- {p.statement}" for p in argument.premises])
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", "You are a logic expert. Determine if the conclusion follows "
                      "logically from the premises."),
            ("human", """Premises:
{premises}

Conclusion: {conclusion}

Is this argument logically valid? Answer YES or NO and explain why.""")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({
            "premises": premises_text,
            "conclusion": argument.conclusion.statement
        })
        
        is_valid = "YES" in response.content.split("\n")[0].upper()
        argument.is_valid = is_valid
        
        print(f"  Argument is {'valid' if is_valid else 'invalid'}")
        return is_valid
    
    def construct_proof(self, premises: List[str], conclusion: str) -> List[str]:
        """Construct logical proof from premises to conclusion."""
        print(f"\n  {self.name}: Constructing proof...")
        
        premises_text = "\n".join([f"{i+1}. {p}" for i, p in enumerate(premises)])
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", "Construct a step-by-step logical proof."),
            ("human", """Given premises:
{premises}

Prove: {conclusion}

Provide proof steps, each on a new line, showing logical progression.""")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({
            "premises": premises_text,
            "conclusion": conclusion
        })
        
        proof_steps = [line.strip() for line in response.content.split("\n") 
                      if line.strip() and not line.strip().startswith("Prove")]
        
        print(f"  Proof constructed with {len(proof_steps)} steps")
        return proof_steps
    
    def apply_modus_ponens(self, conditional: str, antecedent: str) -> Optional[str]:
        """Apply modus ponens: If P then Q, P, therefore Q."""
        print(f"\n  Applying modus ponens...")
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", "Apply modus ponens rule."),
            ("human", """Rule: {conditional}
Fact: {antecedent}

What conclusion follows? (Just state the conclusion)""")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({
            "conditional": conditional,
            "antecedent": antecedent
        })
        
        conclusion = response.content.strip()
        print(f"  Conclusion: {conclusion}")
        return conclusion
    
    def check_consistency(self) -> bool:
        """Check if knowledge base is logically consistent."""
        if len(self.knowledge_base)  str:
        """Solve logic puzzle using reasoning."""
        print(f"\n  {self.name}: Solving logic puzzle...")
        
        prompt = ChatPromptTemplate.from_messages([
            ("system", "Solve this logic puzzle step-by-step using logical reasoning."),
            ("human", "{puzzle}")
        ])
        
        chain = prompt | self.llm
        response = chain.invoke({"puzzle": puzzle})
        
        return response.content


class LogicalReasoningPattern:
    """
    Logical Reasoning Pattern - Apply formal logic.
    
    Handles logical operators, validates arguments, constructs proofs,
    and applies inference rules.
    """
    
    def __init__(self):
        self.agents: Dict[str, LogicalReasoningAgent] = {}
    
    def register_agent(self, agent: LogicalReasoningAgent):
        """Register logical reasoning agent."""
        self.agents[agent.name] = agent
    
    def run(self, scenarios: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Execute logical reasoning scenarios."""
        print("=== Logical Reasoning Pattern ===\n")
        
        results = []
        for agent in self.agents.values():
            for scenario in scenarios:
                scenario_type = scenario.get("type", "argument")
                
                if scenario_type == "argument":
                    argument = LogicalArgument(
                        premises=[Proposition(p) for p in scenario["premises"]],
                        conclusion=Proposition(scenario["conclusion"])
                    )
                    is_valid = agent.check_validity(argument)
                    results.append({"type": "argument", "valid": is_valid})
                
                elif scenario_type == "proof":
                    proof = agent.construct_proof(
                        scenario["premises"],
                        scenario["conclusion"]
                    )
                    results.append({"type": "proof", "steps": len(proof)})
                
                elif scenario_type == "modus_ponens":
                    conclusion = agent.apply_modus_ponens(
                        scenario["conditional"],
                        scenario["antecedent"]
                    )
                    results.append({"type": "inference", "conclusion": conclusion})
                
                elif scenario_type == "puzzle":
                    solution = agent.solve_logic_puzzle(scenario["puzzle"])
                    results.append({"type": "puzzle", "solution": solution[:100]})
        
        return {
            "pattern": "LogicalReasoning",
            "agents": len(self.agents),
            "scenarios_processed": len(scenarios),
            "results": results
        }


# Example usage
if __name__ == "__main__":
    print("=== Logical Reasoning Pattern Demo ===\n")
    
    # Create pattern and agent
    pattern = LogicalReasoningPattern()
    agent = LogicalReasoningAgent("Logician")
    pattern.register_agent(agent)
    
    # Logical reasoning scenarios
    print("1. Testing logical reasoning capabilities...\n")
    scenarios = [
        {
            "type": "argument",
            "premises": [
                "All humans are mortal",
                "Socrates is a human"
            ],
            "conclusion": "Socrates is mortal"
        },
        {
            "type": "proof",
            "premises": [
                "If it rains, the ground gets wet",
                "It is raining"
            ],
            "conclusion": "The ground is wet"
        },
        {
            "type": "modus_ponens",
            "conditional": "If it's sunny, we go to the beach",
            "antecedent": "It's sunny"
        },
        {
            "type": "puzzle",
            "puzzle": "Three people: Alice, Bob, and Carol. One always tells truth, "
                     "one always lies, one alternates. Alice says 'I am not the liar'. "
                     "Bob says 'Alice is the liar'. Who is who?"
        }
    ]
    
    # Run logical reasoning
    summary = pattern.run(scenarios)
    
    print(f"\n=== Summary ===")
    print(f"Scenarios processed: {summary['scenarios_processed']}")
    print(f"Results: {len(summary['results'])} logical operations completed")
    
    print("\nāœ“ Logical reasoning: applying formal logic!")

    

Agentic Architecture Pattern: Logical Reasoning

Pattern 209: 209 Logical Reasoning Pattern – Line-by-Line Explanation

Overview

Pattern 209: Logical Reasoning Pattern

Applies formal logic, propositional and predicate logic to derive conclusions. Handles logical operators (AND, OR, NOT), quantifiers, and logical proofs.


Code Structure Analysis

File Information

  • Pattern Number: 209
  • Pattern Name: 209 Logical Reasoning Pattern
  • File Path: patterns\advanced_reasoning\209_logical_reasoning_pattern.py
  • Total Lines: 304

Detailed Code Explanation

Module Docstring

"""
Pattern 209: Logical Reasoning Pattern

Applies formal logic, propositional and predicate logic to derive conclusions.
Handles logical operators (AND, OR, NOT), quantifiers, and logical proofs.
"""

Explanation: This module docstring describes the purpose and key features of the 209 Logical Reasoning Pattern pattern.


Imports Section

from typing import Dict, Any, List, Optional, Set
from dataclasses import dataclass, field
from enum import Enum
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI  # First 20 imports shown

Explanation: The module imports necessary dependencies: – from typing import Dict, Any, List, Optional, Set: Type hints for better code documentation – from dataclasses import dataclass, field: Data class decorators for clean data structures – from enum import Enum: Enumeration support for fixed sets of values – from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration – from langchain_openai import ChatOpenAI: LangChain framework integration


Enumerations

LogicalOperator (Line 15)

class LogicalOperator(Enum):
    AND
    OR
    NOT
    IMPLIES
    IFF

Purpose: Logical operators.

Values: – AND: Represents and – OR: Represents or – NOT: Represents not – IMPLIES: Represents implies – IFF: Represents iff


Classes

LogicalOperator (Line 15)

Description: Logical operators.

Proposition (Line 25)

Description: Logical proposition.

LogicalRule (Line 33)

Description: Logical inference rule.

LogicalArgument (Line 41)

Description: Complete logical argument.

LogicalReasoningAgent (Line 49)

Description: Agent that performs logical reasoning.

Methods:

__init__ (Line 52)
def __init__(self, name, model_name):
    """No method docstring."""

Purpose: No method docstring.

Parameters: – self: Instance reference – name: Identifier or label – model_name: LLM model to use (e.g., “gpt-4”)

add_proposition (Line 58)
def add_proposition(self, prop):
    """Add proposition to knowledge base."""

Purpose: Add proposition to knowledge base.

Parameters: – self: Instance reference – prop: Parameter for prop

evaluate_logical_expression (Line 63)
def evaluate_logical_expression(self, expression, context):
    """Evaluate logical expression given variable values."""

Purpose: Evaluate logical expression given variable values.

Parameters: – self: Instance reference – expression: Parameter for expression – context: Parameter for context

check_validity (Line 82)
def check_validity(self, argument):
    """Check if logical argument is valid."""

Purpose: Check if logical argument is valid.

Parameters: – self: Instance reference – argument: Parameter for argument

construct_proof (Line 111)
def construct_proof(self, premises, conclusion):
    """Construct logical proof from premises to conclusion."""

Purpose: Construct logical proof from premises to conclusion.

Parameters: – self: Instance reference – premises: Parameter for premises – conclusion: Parameter for conclusion

apply_modus_ponens (Line 139)
def apply_modus_ponens(self, conditional, antecedent):
    """Apply modus ponens: If P then Q, P, therefore Q."""

Purpose: Apply modus ponens: If P then Q, P, therefore Q.

Parameters: – self: Instance reference – conditional: Parameter for conditional – antecedent: Parameter for antecedent

check_consistency (Line 161)
def check_consistency(self):
    """Check if knowledge base is logically consistent."""

Purpose: Check if knowledge base is logically consistent.

Parameters: – self: Instance reference

solve_logic_puzzle (Line 182)
def solve_logic_puzzle(self, puzzle):
    """Solve logic puzzle using reasoning."""

Purpose: Solve logic puzzle using reasoning.

Parameters: – self: Instance reference – puzzle: Parameter for puzzle

LogicalReasoningPattern (Line 197)

Description: Logical Reasoning Pattern – Apply formal logic.

Handles logical operators, validates arguments, constructs proofs, and applies inference rules.

Methods:

__init__ (Line 205)
def __init__(self):
    """No method docstring."""

Purpose: No method docstring.

Parameters: – self: Instance reference

register_agent (Line 208)
def register_agent(self, agent):
    """Register logical reasoning agent."""

Purpose: Register logical reasoning agent.

Parameters: – self: Instance reference – agent: Parameter for agent

run (Line 212)
def run(self, scenarios):
    """Execute logical reasoning scenarios."""

Purpose: Execute logical reasoning scenarios.

Parameters: – self: Instance reference – scenarios: Parameter for scenarios


Design Patterns Used

  • Strategy Pattern: Different execution strategies for various scenarios
  • State Pattern: Managing different states in the workflow
  • Chain of Responsibility: Sequential processing through workflow nodes
  • Observer Pattern: Tracking and monitoring pattern execution
  • Factory Pattern: Creating instances with proper configuration

Usage Example

# Initialize the pattern
pattern = LogicalOperator(name="example", model_name="gpt-4")

# Configure and execute
result = pattern.execute(data={"key": "value"})

# Check results
print(result)

Key Concepts

  • LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
  • Workflow Orchestration: LangGraph manages execution flow through nodes
  • State Management: TypedDict defines workflow state structure
  • Error Handling: Comprehensive error handling and fallback mechanisms
  • Extensibility: Designed for easy customization and extension

Extension Points

This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *