|
| 1 | +""" |
| 2 | +TRS.py - representations for Term Rewriting Systems |
| 3 | +
|
| 4 | +Written by: Joshua Rule <joshua.s.rule@gmail.com> |
| 5 | +""" |
| 6 | + |
| 7 | + |
| 8 | +class Atom(object): |
| 9 | + def __init__(self, index, alias=None): |
| 10 | + self.index = index |
| 11 | + self.alias = alias |
| 12 | + |
| 13 | + |
| 14 | +class Term(object): |
| 15 | + def __init__(self, signature): |
| 16 | + self.signature = signature |
| 17 | + |
| 18 | + def vars(self): |
| 19 | + raise NotImplementedError |
| 20 | + |
| 21 | + def symbols(self): |
| 22 | + raise NotImplementedError |
| 23 | + |
| 24 | + |
| 25 | +class Symbol(Atom): |
| 26 | + def __init__(self, index, alias=None, arity=0): |
| 27 | + Atom.__init__(self, index=index, alias=alias) |
| 28 | + self.arity = arity # can ARS/TRS have Symbols without fixed arity? |
| 29 | + |
| 30 | + def __str__(self): |
| 31 | + return self.alias if self.alias else "S{:d}".format(self.index) |
| 32 | + |
| 33 | + def __repr__(self): |
| 34 | + return ('Symbol(index={:d}, ' |
| 35 | + 'alias=\'{}\', ' |
| 36 | + 'arity={:d})').format(self.index, |
| 37 | + self.alias, |
| 38 | + self.arity) |
| 39 | + |
| 40 | + |
| 41 | +class Variable(Atom, Term): |
| 42 | + """a lone variable""" |
| 43 | + def __init__(self, signature, index, alias=None): |
| 44 | + Atom.__init__(self, index=index, alias=alias) |
| 45 | + Term.__init__(self, signature) |
| 46 | + |
| 47 | + def __str__(self): |
| 48 | + return self.alias if self.alias else "V{:d}".format(self.index) |
| 49 | + |
| 50 | + def __repr__(self): |
| 51 | + return "Variable(index={:d}, alias=\'{}\')".format(self.index, |
| 52 | + self.alias) |
| 53 | + |
| 54 | + def vars(self): |
| 55 | + return set([self]) |
| 56 | + |
| 57 | + def symbols(self): |
| 58 | + return set([]) |
| 59 | + |
| 60 | + |
| 61 | +class Application(Term): |
| 62 | + """a function symbol applied to terms""" |
| 63 | + def __init__(self, signature, head, body=[],): |
| 64 | + sym_head = isinstance(head, Symbol) |
| 65 | + arity_match = len(body) is head.arity |
| 66 | + all_terms = all([isinstance(t, Term) for t in body]) |
| 67 | + sig_match = all([t.signature == signature for t in body]) |
| 68 | + if sym_head: |
| 69 | + if arity_match: |
| 70 | + if all_terms: |
| 71 | + if sig_match: |
| 72 | + Term.__init__(self, signature) |
| 73 | + self.head = head |
| 74 | + self.body = body |
| 75 | + else: |
| 76 | + raise SignatureViolationError |
| 77 | + else: |
| 78 | + raise TRSError('Subterms must be Terms') |
| 79 | + else: |
| 80 | + raise TRSError(('{} has arity {:d}' |
| 81 | + 'but given {:d} args').format( |
| 82 | + head, head.arity, len(body))) |
| 83 | + else: |
| 84 | + raise TRSError('The head of an application must be a Term') |
| 85 | + |
| 86 | + def __str__(self): |
| 87 | + if len(self.body) is 0: |
| 88 | + body = '' |
| 89 | + else: |
| 90 | + body = '(' + ', '.join([str(t) for t in self.body]) + ')' |
| 91 | + return str(self.head) + body |
| 92 | + |
| 93 | + def __repr__(self): |
| 94 | + return 'Application(head={}, body={})'.format(self.head, self.body) |
| 95 | + |
| 96 | + def vars(self): |
| 97 | + return set([]).union(*[t.vars() for t in self.body]) |
| 98 | + |
| 99 | + def symbols(self): |
| 100 | + return set([self.head]).union(*[t.symbols() for t in self.body]) |
| 101 | + |
| 102 | + |
| 103 | +class RewriteRule(object): |
| 104 | + def __init__(self, signature, lhs, rhs): |
| 105 | + sigs_match = lhs.signature == rhs.signature == signature |
| 106 | + lhs_is_app = isinstance(lhs, Application) |
| 107 | + lhs_ge_rhs = all([v in lhs.vars() for v in rhs.vars()]) |
| 108 | + if sigs_match: |
| 109 | + if lhs_is_app: |
| 110 | + if lhs_ge_rhs: |
| 111 | + self.signature = signature |
| 112 | + self.lhs = lhs |
| 113 | + self.rhs = rhs |
| 114 | + else: |
| 115 | + raise TRSError('RHS {} has variables \ |
| 116 | + not in LHS {}'.format(rhs, lhs)) |
| 117 | + else: |
| 118 | + raise TRSError('LHS cannot be a variable') |
| 119 | + else: |
| 120 | + SignatureViolationError |
| 121 | + |
| 122 | + def symbols(self): |
| 123 | + return self.lhs.symbols().union(self.rhs.symbols()) |
| 124 | + |
| 125 | + def vars(self): |
| 126 | + return self.lhs.vars().unoin(self.rhs.vars()) |
| 127 | + |
| 128 | + def __str__(self): |
| 129 | + return str(self.lhs) + ' -> ' + str(self.rhs) |
| 130 | + |
| 131 | + |
| 132 | +class TRS(object): |
| 133 | + def __init__(self, signature, rules): |
| 134 | + all_rules = all([isinstance(r, RewriteRule) for r in rules]) |
| 135 | + sigs_match = all([r.signature == signature for r in rules]) |
| 136 | + if all_rules: |
| 137 | + if sigs_match: |
| 138 | + self.signature = signature |
| 139 | + self.rules = rules |
| 140 | + else: |
| 141 | + raise SignatureViolationError |
| 142 | + else: |
| 143 | + raise TypeError('TRS needs RewriteRule evaluation rules') |
| 144 | + |
| 145 | + def __str__(self): |
| 146 | + return str([str(s) for s in self.signature]) + \ |
| 147 | + '\n\n' + '\n'.join([str(r) for r in self.rules]) |
| 148 | + |
| 149 | + |
| 150 | +class TRSError(Exception): |
| 151 | + pass |
| 152 | + |
| 153 | + |
| 154 | +class SignatureViolationError(TRSError): |
| 155 | + pass |
| 156 | + |
| 157 | + |
| 158 | +if __name__ == "__main__": |
| 159 | + |
| 160 | + # make SK-logic |
| 161 | + |
| 162 | + s = Symbol(1, 'S', 0) |
| 163 | + k = Symbol(2, 'K', 0) |
| 164 | + app = Symbol(3, '.', 2) |
| 165 | + sig = set([s, k, app]) |
| 166 | + |
| 167 | + a = Variable(sig, 1, 'a') |
| 168 | + b = Variable(sig, 2, 'b') |
| 169 | + c = Variable(sig, 3, 'c') |
| 170 | + |
| 171 | + def make(x, y): |
| 172 | + return Application(sig, app, [x, y]) |
| 173 | + |
| 174 | + t1 = make(make(make(Application(sig, s, []), a), b), c) |
| 175 | + t2 = make(make(a, c), make(b, c)) |
| 176 | + r1 = RewriteRule(sig, t1, t2) |
| 177 | + |
| 178 | + t3 = make(make(Application(sig, k, []), a), b) |
| 179 | + t4 = a |
| 180 | + r2 = RewriteRule(sig, t3, t4) |
| 181 | + |
| 182 | + sk = TRS(sig, set([r1, r2])) |
| 183 | + |
| 184 | + print sk |
0 commit comments