Skip to content

Multiple bugs in issue code of rule evaluation: Equality rules, match conjunctions, wildcards, assertEqualToResult, and equal? fail to unify or evaluate correctly #77

@sivaji1012

Description

@sivaji1012

Description:

A clear and concise description of what the bug is:
The MeTTa implementation in hyperon exhibits several related bugs in rule evaluation, pattern matching, and assertion functions. These prevent basic rules from firing correctly, even with proper syntax and facts in the atomspace, despite adhering to MeTTa's variable scoping best practice (variables bound in let or match should be used in the immediately following expression to ensure clear scope). The bugs are evident in minimal Python scripts mimicking REPL behavior. In a Python-based test harness with workarounds (e.g., direct facts), some queries succeed, but the underlying issues persist without workarounds in a pure MeTTa context.

To Reproduce:

Steps to reproduce the behavior:

 pip show hyperon
Name: hyperon
Version: 0.2.8+ga696c359
Summary: Hyperon API in Python
Home-page: https://github.com/trueagi-io/hyperon-experimental
Author: 
Author-email: 
License: MIT License
Location: /home/shivaji1012/AGI_Seed_Knowledge/.venv-agi/lib/python3.12/site-packages
Editable project location: /home/shivaji1012/hyperon-experimental/python
Requires: 
Required-by:

Install hyperon via pip install hyperon (version: [insert your version from pip show hyperon, e.g., 0.2.8]).
Run the following Python scripts for each bug (provided below). Each script initializes a MeTTa atomspace, loads minimal rules and facts without workarounds, and runs a query.
Observe the unexpected outputs in a pure MeTTa context. Optionally, test in a MeTTa REPL with equivalent .metta files.
Test Scripts and Outputs:
Here are the minimal Python scripts for reproduction. Run each with python3 <script.py>.

Equality Rule Bug (test_minimal_clean.py):

import hyperon

metta = hyperon.MeTTa()
print("Initialized MeTTa atomspace.")

minimal_rules = """
(: violates (-> Action SafetyConstraint TruthValue))
(= (violates $act $constraint $tv) (forbids $act $constraint $tv))
(forbids act-deceptive Respect-Autonomy (Pair 0.8 0.7))
"""

print("Loading minimal rules...")
metta.run(minimal_rules)
print("...Loading complete.")

test_program = """
!(match &self (forbids act-deceptive Respect-Autonomy $tv) $tv)
!(match &self (violates act-deceptive Respect-Autonomy $tv) $tv)
"""

print("\nRunning minimal test...")
results = metta.run(test_program)
print(f"Query 1 (forbids): {results[0]}")  # Expected: [(Pair 0.8 0.7)]
print(f"Query 2 (violates): {results[1]}")  # Actual: []

Output:

textInitialized MeTTa atomspace.
Loading minimal rules...
...Loading complete.

Running minimal test...
Query 1 (forbids): [(Pair 0.8 0.7)]
Query 2 (violates): []

Match Conjunction Bug (test_is_unsafe_simplified.py):

import hyperon

metta = hyperon.MeTTa()
print("Initialized MeTTa atomspace.")

minimal_rules = """
(: is-unsafe (-> Plan Boolean TruthValue))
(: violates (-> Action SafetyConstraint TruthValue))
(: contains-action (-> Plan Action TruthValue))
(= (is-unsafe $plan True (Pair 0.8 0.7))
   (match &self
      (, (isa $plan Plan (Pair 1.0 1.0))
         (contains-action $plan $act (Pair 0.9 0.8))
         (violates $act $constraint (Pair 0.8 0.7))
         (isa $constraint SafetyConstraint (Pair 1.0 1.0)))
      (Pair 0.8 0.7)))
(isa plan-A Plan (Pair 1.0 1.0))
(isa Respect-Autonomy SafetyConstraint (Pair 1.0 1.0))
(contains-action plan-A act-deceptive (Pair 0.9 0.8))
(violates act-deceptive Respect-Autonomy (Pair 0.8 0.7))
"""

print("Loading minimal rules...")
metta.run(minimal_rules)
print("...Loading complete.")

test_program = """
!(match &self (is-unsafe plan-A True (Pair 0.8 0.7)) (Pair 0.8 0.7))
"""

print("\nRunning simplified is-unsafe test...")
results = metta.run(test_program)
print(f"Query 1: {results}")

print("\nAtomspace contents:")
for atom in metta.space().get_atoms():
    print(atom)

Output:

textInitialized MeTTa atomspace.
Loading minimal rules...
...Loading complete.

Running simplified is-unsafe test...
Query 1: [[]]

Atomspace contents:
(: is-unsafe (-> Plan Boolean TruthValue))
(: violates (-> Action SafetyConstraint TruthValue))
(: contains-action (-> Plan Action TruthValue))
(= (is-unsafe $plan True (Pair 0.8 0.7)) (match ModuleSpace(GroundingSpace-top) (, (isa $plan Plan (Pair 1.0 1.0)) (contains-action $plan $act (Pair 0.9 0.8)) (violates $act $constraint (Pair 0.8 0.7)) (isa $constraint SafetyConstraint (Pair 1.0 1.0))) (Pair 0.8 0.7)))
(isa plan-A Plan (Pair 1.0 1.0))
(isa Respect-Autonomy SafetyConstraint (Pair 1.0 1.0))
(contains-action plan-A act-deceptive (Pair 0.9 0.8))
(violates act-deceptive Respect-Autonomy (Pair 0.8 0.7))

Wildcard Matching Bug (test_is_unsafe_boolean.py):

import hyperon

metta = hyperon.MeTTa()
print("Initialized MeTTa atomspace.")

minimal_rules = """
(: is-unsafe (-> Plan Boolean TruthValue))
(: is-unsafe (-> Plan Boolean))
(= (is-unsafe $plan True)
   (match &self ((is-unsafe $plan True $_) True)))
(is-unsafe plan-A True (Pair 0.8 0.7))
"""

print("Loading minimal rules...")
metta.run(minimal_rules)
print("...Loading complete.")

test_program = """
!(match &self (is-unsafe plan-A True) True)
"""

print("\nRunning minimal is-unsafe boolean test...")
results = metta.run(test_program)
print(f"Query 1: {results}")

print("\nAtomspace contents:")
for atom in metta.space().get_atoms():
    print(atom)

Output:

textInitialized MeTTa atomspace.
Loading minimal rules...
...Loading complete.

Running minimal is-unsafe boolean test...
Query 1: [[]]

Atomspace contents:
(: is-unsafe (-> Plan Boolean TruthValue))
(: is-unsafe (-> Plan Boolean))
(= (is-unsafe $plan True) (match ModuleSpace(GroundingSpace-top) ((is-unsafe $plan True $_) True)))
(is-unsafe plan-A True (Pair 0.8 0.7))

assertEqualToResult Bug (test_assertion.py):

import hyperon

metta = hyperon.MeTTa()
print("Initialized MeTTa atomspace.")

minimal_rules = """
(: is-unsafe (-> Plan Boolean))
(is-unsafe plan-A True)
"""

print("Loading minimal rules...")
metta.run(minimal_rules)
print("...Loading complete.")

test_program = """
!(match &self (is-unsafe plan-A True) True)
!(assertEqualToResult (match &self (is-unsafe plan-A True) True) [True])
"""

print("\nRunning minimal assertion test...")
results = metta.run(test_program)
print(f"Query 1: {results[0]}")  # [True]
print(f"Query 2: {results[1]}")  # [(Error ...)]

Output:

textInitialized MeTTa atomspace.
Loading minimal rules...
...Loading complete.

Running minimal assertion test...
Query 1: [True]
Query 2: [(Error (_assert-results-are-equal (True) [True] (assertEqualToResult (match ModuleSpace(GroundingSpace-top) (is-unsafe plan-A True) True) [True])) Atom is not an ExpressionAtom)]

equal? Bug (test_equal.py):

import hyperon

metta = hyperon.MeTTa()
print("Initialized MeTTa atomspace.")

test_program = """
!(equal? True True)
!(equal? [True] [True])
"""

print("\nRunning minimal equal test...")
results = metta.run(test_program)
print(f"Query 1: {results[0]}")  # [(equal? True True)]
print(f"Query 2: {results[1]}")  # [(equal? [True] [True])]

Output:

textInitialized MeTTa atomspace.

Running minimal equal test...
Query 1: [(equal? True True)]
Query 2: [(equal? [True] [True])]

Additional Context:

Python vs. REPL: In test_harness.py (Python), Queries 1, 2, and 4 succeed ([(Pair 0.8 0.7)], [(Pair 0.8 0.7), (Pair 0.8 0.7)], [True]) due to workarounds (direct facts for violates and is-unsafe) and a Python assertion. Query 3 fails ([]) due to the conjunction bug. Without workarounds, these queries would fail in a pure MeTTa REPL, as shown in the minimal tests.
MeTTa Version: [output of metta --version, if available]
Environment: Python [insert version from python --version, e.g., 3.11.0], hyperon [insert version from pip show hyperon, e.g., 0.2.8].
Workarounds: Direct facts (e.g., (violates act-deceptive Respect-Autonomy (Pair 0.8 0.7)), (is-unsafe plan-A True)) and Python assertions (str(results[3]) == "[True]") mask the bugs in test_harness.py.

Expected Behavior:

Equality rules should unify with existing facts (e.g., Query 2 in test_minimal_clean.py returns [(Pair 0.8 0.7)]).
Match conjunctions should produce results when all patterns match (e.g., Query 1 in test_is_unsafe_simplified.py returns [(Pair 0.8 0.7)]).
Wildcards should capture truth values (e.g., Query 1 in test_is_unsafe_boolean.py returns [True]).
assertEqualToResult should succeed on matching results (e.g., Query 2 in test_assertion.py returns []).
equal? should evaluate to [True] for equal arguments (e.g., Query 1 and 2 in test_equal.py return [True]).

Actual Behavior:

Equality rules return [] (e.g., Query 2 in test_minimal_clean.py).
Match conjunctions return [[]] or [] (e.g., Query 1 in test_is_unsafe_simplified.py and Query 3 in test_harness.py).
Wildcards return [[]] (e.g., Query 1 in test_is_unsafe_boolean.py).
assertEqualToResult raises a type error (e.g., Query 2 in test_assertion.py).
equal? returns unevaluated expressions (e.g., Query 1 and 2 in test_equal.py).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions