I'm reading chapter 7 of Russell & Norvig's "Artificial Intelligence: A Modern Approach" textbook that is about designing Logical Agents using propositional logic. The code for the algorithms in the chapter are available for Python. I wanted to use Racket for implementing the code instead of just reading the Python so I can understand the algorithms better. However, since I'm new to Racket I'm having difficulty representing the logical expressions in it.
In the python code, a logical expression is represented by a class that takes two parameters - the logical operator (and
, or
, if
, iff
, not
) and its arguments. Here is a snippet of the python code
class Expr:
"""A mathematical expression with an operator and 0 or more arguments.
op is a str like '+' or 'sin'; args are Expressions.
Expr('x') or Symbol('x') creates a symbol (a nullary Expr).
Expr('-', x) creates a unary; Expr('+', x, 1) creates a binary."""
def __init__(self, op, *args):
self.op = str(op)
self.args = args
# Operator overloads
def __neg__(self):
return Expr('-', self)
def __pos__(self):
return Expr('+', self)
def __invert__(self):
return Expr('~', self)
def __add__(self, rhs):
return Expr('+', self, rhs)
In Racket, I'm representing logical expressions as pairs, i.e (cons op args)
. I also added a syntactic sugar for the expressions so that I can write (& a b)
and it will be transformed to (cons and '(a b))
. Another requirement is that both operators and their arguments should be represented as symbols unless they are explicitly evaluated - so that I can manipulate expressions symbolically. Hence, (& a b)
will be represented as (cons 'and '('a 'b))
and only when doing (! (& a b))
should this be evaluated as (and a b)
- I'm using !
to denote evaluation of an logical expression. This is the part I'm struggling with.
#lang racket
#lang racket
;function wrapper for the and operator
(define (and-fn patt ...)
(and patt ...))
;function wrapper for the or operator
(define (or-fn patt ...)
(and patt ...))
;function wrapper for the not operator
(define (not-fn patt)
(not patt))
(define-syntax (~ stx)
(syntax-case stx ()
([_ a] #'(cons 'not-fn #'a))))
(define-syntax (& stx)
(syntax-case stx ()
[(_ patt ...) #'(cons 'and-fn '(patt ...))]))
(define-syntax (|| stx)
(syntax-case stx ()
[(_ patt ...) #'(cons 'or-fn '(patt ...))]))
(define-syntax (=> stx)
(syntax-case stx ()
[(_ a b) #'(cons '=> '(a b))]))
(define-syntax (<=> stx)
(syntax-case stx ()
[(_ a b) #'(cons '<=> '(a b))]))
(define (! stx)
(syntax-case stx ()
[(_ op patt ...)
(match (op patt)
[('=> '(a b)) #'(! (|| (~ a) b))]
[('<=> '(a b)) #'(! (& (|| (~ a) b) (|| (~ b) a)))]
[_ #'(eval (op patt ...))])]))
(define a #t)
(define b #f)
(! (|| a b)) ;should evaluate to #t
(! (=> a b)) ;should evaluate to #f
When running the above code, I get match: syntax error in pattern in: ((quote =>) (quote (a b)))
error. How can I fix this and implement propositional logic expressions in Racket? I'm also open to suggestions n representing logical expressions other than (cons op args)