summary refs log tree commit diff
path: root/main.py
blob: 9a1f180ee56bc0de75e2e9c265c45be28075e1c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from lambda_calculus import Variable, Abstraction, Application
from lambda_calculus.visitors.normalisation import BetaNormalisingVisitor
import networkx as nx
import sys
import itertools

S = Abstraction('x', 
        Abstraction('y', 
            Abstraction('z', 
                Application(Application(Variable('x'), Variable('z')),
                     Application(Variable('y'), Variable('z'))))))

K = Abstraction('x', 
        Abstraction('y',
            Variable('x')))


class Node(object):
  def __init__(self, left, right):
    self.left = left
    self.right = right

  def __repr__(self):
    return '(%s %s)' % (self.left if isinstance(self.left, Node) else self.left[1], self.right if isinstance(self.right, Node) else self.right[1])

  def app(self):
    return Application(
        self.left.app() if isinstance(self.left, Node) else self.left[0],
        self.right.app() if isinstance(self.right, Node) else self.right[0])

# Given a tree and a label, yields every possible augmentation of the tree by
# adding a new node with the label as a child "above" some existing Node or Leaf.
def add_leaf(tree, label):
  yield Node(label, tree)
  if isinstance(tree, Node):
    for left in add_leaf(tree.left, label):
      yield Node(left, tree.right)
    for right in add_leaf(tree.right, label):
      yield Node(tree.left, right)

# Given a list of labels, yield each rooted, unordered full binary tree with
# the specified labels.
def enum_unordered(labels):
  if len(labels) == 1:
    yield labels[0]
  else:
    for tree in enum_unordered(labels[1:]):
      for new_tree in add_leaf(tree, labels[0]):
        yield new_tree

def enum_ordered(labels):
  if len(labels) == 1:
    yield labels[0]
  else:
    for i in range(1, len(labels)):
      for left in enum_ordered(labels[:i]):
        for right in enum_ordered(labels[i:]):
          yield Node(left, right)

all_products = lambda *args, repeat:itertools.chain(*(itertools.product(*args, repeat=n) for n in range(1,repeat+1)))

g = nx.Graph()
for term in all_products([(S,'S'), (K,'K')], repeat=5):
    for parensed in enum_ordered(term):
        try:
            beta = BetaNormalisingVisitor().skip_intermediate(
                parensed.app() if isinstance(parensed, Node) else parensed[0]
            )
            g.add_edge(repr(parensed) if isinstance(parensed, Node) else parensed[1], str(beta))
        except:
          print(str(beta), "cant be reduced")
          pass

import matplotlib.pyplot as plt
nx.draw(g, with_labels=True)
plt.show()