summary refs log tree commit diff
path: root/main.py
blob: e8e4fa583fc656e829f3bd053a5c5947d1931bbd (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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)

# def count(n,elements):
#     l = len(elements)
#     def Convert(n,base):
#        string = elements
#        if n < base:
#           return [string[n]]
#        else:
#           return Convert(n//base,base) + [string[n%base]]
#     return (Convert(i,l) for i in range(0,l**n+1))

sys.setrecursionlimit(1000)

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.nx_pydot.write_dot(g, 'out.dot')
nx.draw(g, with_labels=True)
plt.show()

# for n1 in [S,K]:
#     for n2 in [S,K]:
#         for n3 in [S,K]:
#             # for n4 in [S,K]:
#             for term in enum_ordered([n1,n2,n3]):
#                 beta = BetaNormalisingVisitor().skip_intermediate(term) 
#                 if beta.body == Variable(beta.bound):
#                     print(str(term), 'reduces to identity')