-
-
Notifications
You must be signed in to change notification settings - Fork 47.4k
Adding tt entails #12903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding tt entails #12903
Changes from all commits
969b313
518f003
62d616f
fe06a03
91e6fe6
e06f29f
6706319
b6727e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
""" | ||
TT-ENTAILS Algorithm (Propositional Logic) | ||
Reference: [Russell & Norvig, Artificial Intelligence: A Modern Approach, Ch. 7](https://aima.cs.berkeley.edu/) | ||
Wikipedia: [Entailment](https://en.wikipedia.org/wiki/Entailment) | ||
|
||
This algorithm checks if a knowledge base (KB) entails a query sentence (a) | ||
using truth tables. Returns True if KB entails a, False otherwise. | ||
""" | ||
|
||
import itertools | ||
import ast | ||
import operator | ||
|
||
OPS = {ast.And: operator.and_, ast.Or: operator.or_, ast.Not: operator.not_} | ||
|
||
|
||
def safe_eval(expr: str, model: dict[str, bool]) -> bool: | ||
"""Safely evaluate propositional logic expression using ast.""" | ||
tree = ast.parse(expr, mode="eval") | ||
|
||
def _eval(node): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: |
||
if isinstance(node, ast.Expression): | ||
return _eval(node.body) | ||
if isinstance(node, ast.Name): | ||
return model[node.id] | ||
if isinstance(node, ast.Constant): # True / False | ||
return node.value | ||
if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.Not): | ||
return OPS[ast.Not](_eval(node.operand)) | ||
if isinstance(node, ast.BoolOp): | ||
if isinstance(node.op, ast.And): | ||
return all(_eval(v) for v in node.values) | ||
if isinstance(node.op, ast.Or): | ||
return any(_eval(v) for v in node.values) | ||
raise ValueError(f"Unsupported expression: {expr}") | ||
|
||
return _eval(tree) | ||
|
||
|
||
def tt_entails(kb: list[str], query: str, symbols: list[str]) -> bool: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file |
||
""" | ||
Check if the knowledge base entails the query using truth tables. | ||
|
||
Args: | ||
kb (List[str]): List of propositional sentences in KB as strings | ||
query (str): Query sentence to test entailment | ||
symbols (List[str]): List of all propositional symbols used | ||
|
||
Returns: | ||
bool: True if KB entails query, False otherwise | ||
|
||
Example: | ||
tt_entails(["P or Q"], "Q", ["P","Q"]) | ||
|
||
""" | ||
for values in itertools.product([True, False], repeat=len(symbols)): | ||
model: dict[str, bool] = dict(zip(symbols, values)) | ||
# Check if KB is true under this model | ||
# # If query is false in this model, KB does not entail query | ||
if all(safe_eval(sentence, model) for sentence in kb) and not safe_eval( | ||
query, model | ||
): | ||
return False | ||
return True | ||
|
||
|
||
# Example usage | ||
if __name__ == "__main__": | ||
# Example 1: KB entails query → should return True | ||
symbols = ["P", "Q"] | ||
kb = ["P or Q", "not P or Q"] # KB says P or Q is True, and not P or Q is True | ||
query = "Q" # Query: Is Q True? | ||
print("Does KB entail query? : ", tt_entails(kb, query, symbols)) | ||
|
||
# Example 2: KB does NOT entail query → should return False | ||
symbols2 = ["P", "Q"] | ||
kb2 = ["P"] # KB says only P is True | ||
query2 = "Q" # Query asks if Q is True | ||
print("Does KB2 entail query2? : ", tt_entails(kb2, query2, symbols2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there is no test file in this pull request nor any test function or class in the file
machine_learning/ttentails.py
, please provide doctest for the functionsafe_eval