├── .gitignore
├── .travis.yml
├── README.md
├── bb
├── .gitignore
├── README
├── data
│ └── machine_3_2_sorted
├── harland
│ ├── .gitignore
│ ├── CITATION
│ ├── analyse.pl
│ ├── emulate.pl
│ ├── engine.pl
│ ├── generate.pl
│ ├── monsters.pl
│ ├── search.pl
│ └── top.pl
├── run.py
├── search.py
├── skelet
│ ├── .gitignore
│ └── bbfind.pp
├── tnf.py
├── zany.sh
└── zanyzoo.cc
├── coq
├── go.py
├── grammar.g
├── stl
│ └── peano.v
├── test.sh
└── twoplustwo.v
├── harrison
├── chap1.ml
├── full.ml
└── run.sh
├── metamath
├── .gitignore
├── cc
│ ├── .gitignore
│ ├── Math.g
│ ├── README
│ ├── SConstruct
│ └── main.cc
├── check.sh
├── lean
│ ├── .gitignore
│ └── main.lean
├── lib
│ ├── peano.mm
│ └── peano2.mm
├── miu2.mm
├── mm.g
├── realtwoplustwo.mm
├── simple.mm
├── simple2.mm
├── test.sh
├── twoplustwo.mm
└── verify.py
├── prove
├── .gitignore
├── fact.c
└── test.c
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .*.swp
2 | .*.swo
3 |
4 | *.vo
5 | *.glob
6 | *.aux
7 | *.pyc
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 |
3 | install:
4 | - pip install -r requirements.txt
5 |
6 | script:
7 | # keep it simple and fast for now
8 | - cd metamath && ./verify.py miu2.mm && ./verify.py simple.mm && ./verify.py simple2.mm
9 | #- cd metamath && ./test.sh
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # twitchcoq -- a backspace.ai project
2 |
3 | Reimplementing a subset of Coq in Python.
4 |
5 | Just kidding, Coq is too complex. We implemented metamath instead.
6 |
7 | It (slowly) verifies set.mm as of 11/3/2019
8 |
9 | Ideally, Coq and friends should be rewritten in metamath. It's really the future, just wish it looked better. But omg, this is the proper stack for formal math, "formalism" is alive and well and is the truth in philosophy.
10 |
11 | # metamath as execution
12 |
13 | We should be able to "run" a metamath program, aka proof without the target. It's a stack machine. The interpreter is only verifying that the proof is a valid program trace for the machine.
14 |
15 | # metamath on search
16 |
17 | Take set.mm, remove all $p definitions. Find them with search. Powered by AI(tm).
18 |
19 | "metasmash" written in C++17. First with the intermediate nodes in the graph. Then make it sparser. Then remove it altogether.
20 |
21 | How many of the 71 Metamath theorems can we rediscover without the scaffolding?
22 |
23 | Hmm, https://github.com/dwhalen/holophrasm
24 |
25 | # random notes
26 |
27 | First order logic:
28 |
29 |
30 | Theorem test : exists x : nat, x + 2 = 4.
31 | Theorem test2 : forall y : nat, (exists x : nat, x = y).
32 |
33 |
34 | Second order logic (quantifing over first order logic statements):
35 |
36 |
37 | forall y : (fun x : nat -> nat)
38 |
39 |
40 | Higher order logic...so on and so forth
41 |
42 | # randomer notes
43 |
44 | Imagine twitch, but VR. We'll rebuild the cybercafes, the revolutionary coffee shops, the old hacker spaces, the town square, the churches, all of the trappings of civilization. But we'll build them in machines. We'll build them in math. We'll build them in homomorphically encrypted lockers. We'll build them where copies are free, tax is ridiculous, removing your landlord is a fork, and the only axis on which to compete is quality. True freedom of association.
45 |
46 | We need embodiment to be free from the tyranny of owned space. And we need formalization to be secure.
47 |
48 | The attacker vs defender battle may have been lost IRL. But in the world of information, the defender seems to win.
49 |
50 | # thoughts
51 |
52 | To build a machine that can program.
53 |
54 | * How much of programming exists without real world context?
55 | * Refactoring definitely is, optimizing for some notion of "readability".
56 | * Speed definitely is, optimizing for well, speed.
57 |
58 | metamath is just the program trace of a proof. Any language can be built on top of it to generate the trace.
59 |
60 | Instead of proving two programs the same, can we prove two program traces the same? Depends on how we define the same, in the metamath sense, it's only the output at the end, aka easy.
61 |
62 | Hehe, a program is just the compression of all of its traces. QIRA is AI lah
63 |
64 | # compression aside
65 |
66 | Lossy compression has no meaning, though there is something aside from lossless compression. There's task specific compression, dealt with this at comma. The trees on the side of the road have no effect on the driving problem, and that's why a straight up lossless compressor isn't the goal function.
67 |
68 | I think "Value Prediction Networks" (https://arxiv.org/abs/1707.03497) gets this right, would be fun to implement that. Correct to say you are just compressing to predict the reward?
69 |
70 | Then there's the universal goal function of compression progress (https://arxiv.org/abs/0812.4360) as a way of separating noise (which will never be compressed), from signal (which will have a gradient of compression).
71 |
72 |
73 |
--------------------------------------------------------------------------------
/bb/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | a.out
3 |
--------------------------------------------------------------------------------
/bb/README:
--------------------------------------------------------------------------------
1 | Attack Steps
2 |
3 | 0. Naive
4 | 5+1 states, 2 values, 2 moves ^ 10 labels
5 | 24^10 = 63 trillion, possible for sigma(5, 2)
6 |
7 | 1. Determine a canonical numbering of all the machines that's easy to enumerate and refer to the machines by. Should be simple, yet remove many isomorphic machines.
8 | bbprover claims 150M machines
9 | zany zoo claims 102,550,546
10 | our imp gets 276,413,630
11 | now it gets 102,596,896
12 | Goal: a list of all the machines to check, and a spot check that many random machines are obviously equivalent to one on the list
13 | (put number here)
14 |
15 | 1b. Rejecting "active" approaches to machine generation
16 | Say we only exclude isomorphic machines, how many are left?
17 | 3,2 is 3+1 * 2 * 2 = base 16 with length 3*2 = 6 -> 16^6 = 16,777,216 -> 3440
18 |
19 | 2. Exclude all machines that halt with <= 4098 (current ones record)
20 | Run for 47,176,870 steps
21 | (put number here)
22 |
23 | 3. Exclude all machines with a repeated state
24 | (put number here)
25 |
26 | 4. Now it's proving time
27 | a. If they halt, no proof required, just the halting step.
28 | b. If they repeat state, no proof required, just the repeating step and to which step it repeats.
29 | c. The rest run for longer than the suspected BB number, and likely don't halt. But how to prove it.
30 | I think it's all some form of induction.
31 |
32 | How can we put the machines in a proof assistant?
33 |
34 | https://skelet.ludost.net/bb/nreg.html <-- claims only 43!
35 |
36 |
--------------------------------------------------------------------------------
/bb/harland/.gitignore:
--------------------------------------------------------------------------------
1 | a.out
2 | raw
3 | results
4 |
--------------------------------------------------------------------------------
/bb/harland/CITATION:
--------------------------------------------------------------------------------
1 | From https://web.archive.org/web/20180318123007/http://goanna.cs.rmit.edu.au/~jah/busybeaver/
2 |
3 |
--------------------------------------------------------------------------------
/bb/harland/analyse.pl:
--------------------------------------------------------------------------------
1 | analyse(N, M, Ones, Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
2 | number_of_states(M, States),
3 | number_of_symbols(M, Symbols),
4 | number_of_dirs(M, Dirs),
5 | analyse(States, Symbols, Dirs, N, M, Ones, Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs).
6 |
7 | analyse(States, Symbols, Dirs, N, M, Ones, Hops, Status, Outputs, Ones, Hops, Status, Outputs) :-
8 | % \+ member(Status, [going,going(_),unknown]), !.
9 | % format("% Checking status~n", []),
10 | check_status(Status, States, Symbols, Dirs, N, M),
11 | % format("% Checked~n", []),
12 | !.
13 |
14 | analyse(_States, _Symbols, _Dirs, _N, M, _Ones, _Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
15 | member(Status, [going,going(_),unknown]),
16 | % format("% Static check .... ~n", []),
17 | static_checks(M, Args, NewOnes, NewHops, NewStatus, NewOutputs),
18 | \+ member(NewStatus, [going,going(_),unknown]),
19 | % format("% Static check done~n", []),
20 | !.
21 |
22 | analyse(States, Symbols, Dirs, _N, M, _Ones, _Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
23 | member(Status, [going,unknown]),
24 | % format("% Analysing 1 (~k)~n", [Status]),
25 | bound(States, Symbols, Dirs, analyse, Bound, MaxSteps),
26 | % format("% Analysing 1 ", []), write(Status), format(" with Bound ~d~n", [Bound]),
27 | % emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),loop,escape,blank,otter,induction,optcom,newtrie(10,5)], NewOnes, NewHops, NewStatus, NewOutputs),
28 | % emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),otter,induction,optcom,newtrie(10,5)], NewOnes, NewHops, NewStatus, NewOutputs),
29 | emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),otter,induction,compress2,trie(20)], NewOnes, NewHops, NStatus, NewOutputs),
30 | % format("Emulation done, NStatus is ~k~n", [NStatus]),
31 | set_status(NStatus, NewStatus),
32 | % format("% Analysing 1: ~k to ~k~n", [Status,NewStatus]),
33 | ( member(nomonster, Args) -> true; \+ member(NewStatus, [going,going(_),unknown]) ), % Give up here unless monster search is specified.
34 | !.
35 |
36 | analyse(States, Symbols, Dirs, _N, M, _Ones, _Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
37 | member(Status, [going(SoFar)]),
38 | % format("% Analysing 1 (~k)~n", [Status]),
39 | bound(States, Symbols, Dirs, analyse, Bound1, MaxSteps),
40 | Bound is max(2*SoFar, Bound1),
41 | % format("% Analysing 2 ", []), write(Status), format(" with Bound ~d~n", [Bound]),
42 | % emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),loop,escape,blank,otter,induction,optcom,newtrie(10,5)], NewOnes, NewHops, NewStatus, NewOutputs),
43 | % emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),otter,induction,optcom,newtrie(10,5)], NewOnes, NewHops, NewStatus, NewOutputs),
44 | emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),otter,induction,compress2,trie(20)], NewOnes, NewHops, NStatus, NewOutputs),
45 | set_status(NStatus, NewStatus),
46 | % format("% Analysing 2: ~k to ~k~n", [Status, NewStatus]),
47 | ( member(nomonster, Args) -> true; \+ member(NewStatus, [going,going(_),unknown]) ), % Give up here unless monster search is specified.
48 | !.
49 |
50 | % Dynamic nontermination checks go here, if any ...
51 | % Punt that it is a monster and then give up.
52 | analyse(States, Symbols, Dirs, _N, M, _Ones, _Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
53 | member(Status, [going,going(_),unknown]),
54 | \+ member(nomonster, Args),
55 | % format("% Analysing 2 (~k)~n", [Status]),
56 | bound(States, Symbols, Dirs, monster, Bound, MaxSteps), % Punt that it is a monster ...
57 | % format("% Analysing 3 ", []), write(Status), format(" with Bound ~d~n", [Bound]),
58 | % format("% Monster punt (~k) with Bound ~d~n", [Status,Bound]),
59 | emulate_bb(M, Bound, flex, [maxsteps(MaxSteps),otter,compress2,trie(20)], NewOnes, NewHops, NewStatus, NewOutputs),
60 | % format("% Analysing 2 (~k)~n", [Status]),
61 | % \+ member(NewStatus, [going,going(_),unknown]), !.
62 | true, !.
63 |
64 | % analyse(States, Symbols, Dirs, _N, M, Ones, Hops, Status, Args, NewOnes, NewHops, NewStatus, NewOutputs) :-
65 | % member(Status, [going,going(_),unknown]),
66 | % member(nomonster, Args),
67 | % % Give up!
68 | % NewOnes = Ones, NewHops = Hops,
69 | % set_status(Status, NewStatus),
70 | % NewOutputs = Outputs,
71 | % !, true.
72 |
73 | check_status(Status, _States, _Symbols, _Dirs, _N, _Machine) :- \+ member(Status, [going,going(_),unknown,abort,abort(_)]), !.
74 | check_status(Status, States, Symbols, Dirs, N, Machine) :-
75 | member(Status, [abort,abort(_)]), !,
76 | directory(output, States, Symbols, Dirs, tnf, Base), ensure_exists(Base),
77 | filename(Base, input, States, Symbols, Dirs, tnf, abort, 1, Name, AbortInFile),
78 | filename(Base, output, States, Symbols, Dirs, tnf, abort, 1, Name, AbortOutFile),
79 | find_extra_machines(States, Symbols, Dirs, N, Machine, AbortInFile, AbortOutFile).
80 |
81 | set_status(S, S) :- \+ member(S, [going, going(_), unknown]).
82 | set_status(unknown,going).
83 | set_status(going,going).
84 | set_status(going(N),going(N)).
85 |
86 | bound(M, Type, Bound, Steps) :-
87 | number_of_states(M, States),
88 | number_of_symbols(M, Symbols),
89 | number_of_dirs(M, Dirs),
90 | bound(States, Symbols, Dirs, Type, Bound, Steps).
91 |
92 | bound(2,2,2,search, 50, 50).
93 | bound(2,2,2,analyse, 100, 100).
94 | bound(2,2,2,abort, 100, 100).
95 | bound(2,2,2,monster, 1000, 1000).
96 | bound(3,2,2,search, 50, 100).
97 | bound(3,2,2,analyse, 200, 100).
98 | bound(3,2,2,abort, 200, 100).
99 | bound(3,2,2,monster, 1000, 1000).
100 | bound(2,3,2,analyse, 10000, 1000).
101 | bound(2,3,2,abort, 1000, 1000).
102 | bound(2,3,2,monster, 100000, 2000).
103 | bound(2,3,2,search, 50, 100).
104 | bound(4,2,2,monster, 150000, 2000).% Some 4,2 cases need history 1,000 and hops 150,000 ...
105 | bound(4,2,2,analyse, 50000, 10000).
106 | bound(4,2,2,search, 100, 100).
107 | bound(4,2,2,abort, 100, 100).
108 | bound(2,4,2,analyse, 500000, 20000).
109 | bound(2,4,2,abort, 1000, 1000).
110 | bound(2,4,2,monster, 5000000, 200000).
111 | bound(2,4,2,search, 100, 100).
112 | bound(3,3,2,analyse, 20000, 1000).
113 | bound(3,3,2,monster, 10000000000, 20000000).
114 | bound(3,3,2,search, 100, 100).
115 | bound(3,3,2,abort, 1000, 1000).
116 | bound(5,2,2,analyse, 20000, 1000).
117 | bound(5,2,2,monster, 50000000, 50000).
118 | bound(5,2,2,search, 300, 300).
119 | bound(5,2,2,abort, 1000, 1000).
120 | bound(2,5,2,analyse, 10000, 1000).
121 | bound(2,5,2,monster, 100000000, 5000).
122 | bound(2,5,2,search, 200, 200).
123 | bound(2,5,2,abort, 1000, 1000).
124 |
125 | bound(6,2,2,search,100,100).
126 | bound(4,3,2,search,100,100).
127 | bound(3,4,2,search,100,100).
128 | bound(2,6,2,search,100,100).
129 |
130 | meander(1,[t(a,0,4,l,b),t(a,1,1,r,z),t(a,2,2,r,a),t(a,3,0,l,b),t(a,4,3,l,b),t(b,0,2,r,a),t(b,1,3,l,b),t(b,2,3,r,b),t(b,3,2,l,b),t(b,4,1,l,b)]). % Not a meanderer!
131 | meander(2,[t(a,0,1,r,b),t(a,1,1,r,z),t(a,2,2,r,a),t(a,3,0,l,b),t(a,4,3,l,b),t(b,0,2,r,a),t(b,1,3,l,b),t(b,2,3,r,b),t(b,3,2,l,b),t(b,4,1,l,b)]). % Not a meanderer!
132 | meander(3,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(b,0,1,l,c),t(b,1,1,l,a),t(b,2,2,r,c),t(c,0,1,l,z),t(c,1,1,l,a),t(c,2,2,r,b)]). % Not a meanderer!
133 | meander(4,[t(a,0,1,r,b),t(a,1,1,l,a),t(b,0,0,l,a),t(b,1,1,l,c),t(c,0,1,r,z),t(c,1,0,l,d),t(d,0,1,r,d),t(d,1,0,l,a)]). % Meanderer from CATS07 paper.
134 |
135 | % Designed to normalise Machines generated elsewhere. NewMachine will have the properties below.
136 | % The first transition (when run on a blank tape) will be t(a,0,1,r,b).
137 | % NewMachine will be a sorted list of transitions, sorted by lexographic ordering on States x Symbols
138 | normalise(Machine, NewMachine) :-
139 | set_first_state(a, Machine, Machine1),
140 | set_first_output(1, Machine1, Machine2),
141 | set_first_direction(r, Machine2, Machine3),
142 | sort_transitions(Machine3, Machine4),
143 | NewMachine = Machine4,!,
144 | true.
145 | normalise(Machine, Machine) :- format("Normalisation failed for ", []), write(Machine), nl.
146 |
147 | set_first_state(State, Machine, Machine) :- \+ member(t(a,0,0,_,_), Machine).
148 | set_first_state(State, Machine, NewMachine) :-
149 | member(t(a,0,0,_,_), Machine),
150 | % This is only needed if the first transitions is of the form t(a,0,0,D,NS)
151 | Bound = 10,
152 | find_true_first(Machine, a, First, 0, Bound),
153 | swap_states(State, First, [], Machine, NewMachine).
154 |
155 | find_true_first(Machine, State, First, Now, Bound) :-
156 | Now < Bound,
157 | member(t(State, 0, O, _D, NS), Machine), O \== 0,
158 | First = NS.
159 | find_true_first(Machine, State, First, Now, Bound) :-
160 | Now < Bound,
161 | member(t(State, 0, 0, _D, NS), Machine), Now1 is Now + 1,
162 | find_true_first(Machine, NS, First, Now1, Bound).
163 |
164 | swap(State1, State2, State3, NewState) :-
165 | State3 == State1, NewState = State2.
166 | swap(State1, State2, State3, NewState) :-
167 | State3 == State2, NewState = State1.
168 | swap(State1, State2, State3, NewState) :-
169 | State3 \== State1, State3 \== State2, NewState = State3.
170 |
171 | swap_states(_State1, _State2, SoFar, [], SoFar).
172 | swap_states(State1, State2, SoFar, [t(S,I,O,D,NS)|Rest], NewMachine) :-
173 | swap(State1, State2, S, NewS),
174 | swap(State1, State2, NS, NewNS),
175 | append(SoFar, [t(NewS, I, O, D, NewNS)], NewSoFar),
176 | swap_states(State1, State2, NewSoFar, Rest, NewMachine).
177 |
178 | set_first_output(Output, Machine, NewMachine) :-
179 | member(t(a,0,Out,_D,_NS), Machine), Out == Output,
180 | Machine = NewMachine.
181 | set_first_output(Output, Machine, NewMachine) :-
182 | member(t(a,0,Out,_D,_NS), Machine), Out \== Output,
183 | swap_symbols(Output, Out, [], Machine, NewMachine).
184 |
185 | swap_symbols(_Symbol1, _Symbol2, SoFar, [], SoFar).
186 | swap_symbols(Symbol1, Symbol2, SoFar, [t(S,I,O,D,NS)|Rest], NewMachine) :-
187 | swap(Symbol1, Symbol2, I, NewI),
188 | swap(Symbol1, Symbol2, O, NewO),
189 | append(SoFar, [t(S, NewI, NewO, D, NS)], NewSoFar),
190 | swap_symbols(Symbol1, Symbol2, NewSoFar, Rest, NewMachine).
191 |
192 | set_first_direction(Dir, Machine, NewMachine) :-
193 | member(t(a,0,_Out,Dir,_NS), Machine),
194 | NewMachine = Machine.
195 | set_first_direction(Dir, Machine, NewMachine) :-
196 | member(t(a,0,_Out,D,_NS), Machine), D \== Dir,
197 | swap_directions(D, Dir, [], Machine, NewMachine).
198 |
199 | swap_directions(_Direction1, _Direction2, SoFar, [], SoFar).
200 | swap_directions(Direction1, Direction2, SoFar, [t(S,I,O,D,NS)|Rest], NewMachine) :-
201 | swap(Direction1, Direction2, D, NewD),
202 | append(SoFar, [t(S, I, O, NewD, NS)], NewSoFar),
203 | swap_directions(Direction1, Direction2, NewSoFar, Rest, NewMachine).
204 |
205 | sort_transitions(Machine, NewMachine) :-
206 | number_of_states(Machine, States),
207 | number_of_symbols(Machine, Symbols),
208 | sortmachine(0, States, Symbols, a,0,[],Machine,SortM),
209 | NewMachine = SortM, % Need to work on this!
210 | true.
211 |
212 | static_checks(_M, _Outputs, _NewOnes, _NewHops, _NewStatus, _NewOutputs) :- fail. % To test induction ...
213 | % static_checks(M, _Outputs, NewOnes, NewHops, NewStatus, NewOutputs) :-
214 | % meandering(M),
215 | % NewOnes = 0,
216 | % NewHops = 0,
217 | % NewStatus = meander,
218 | % NewOutputs = [].
219 | % % fail.
220 |
221 | % nonterminating(M, _Outputs, NewStatus) :- looping(M), !, NewStatus = loops.
222 | nonterminating(M, _Outputs, NewStatus) :- meandering(M), !, NewStatus = meander.
223 |
224 | meandering(M) :-
225 | member(t(S,I,_O,_D,H), M), halt_state(H),
226 | % format("Halt transition is ~k, ~k, ~k, ~k, ~k~n", [S,I,O,D,H]),
227 | % run_backwards(M, ....),
228 | % \+ run_backwards(state([],S,[I]), M, 100, naive, 0, 0),
229 | backwards_bound(Bound),
230 | \+ run_backwards(config([], S, I, l, []), M, Bound, naive, 0),
231 | true.
232 |
233 | backwards_bound(10). % Experiment with this value.
234 |
235 | run_backwards(_Config, _M, Bound, Mode, Hops) :-
236 | member(Mode, [naive]),
237 | Hops > Bound,
238 | % format("Finishing with ", []), display_config(Config), nl,
239 | true.
240 |
241 | run_backwards(Config, _M, Bound, Mode, Hops) :-
242 | member(Mode, [naive]),
243 | Hops =< Bound,
244 | Config = config(Left, State, Item, Dir, Right), check_blank(Left, Left1), check_blank(Right, Right1),
245 | initial_config(naive,eval,blank,config(Left1, State, Item, Dir, Right1),_),
246 | % format("Initial Configuration ", []), display_config(Config), nl,
247 | true.
248 | run_backwards(config(Left, State, Item, Dir, Right), M, Bound, Mode, Hops) :-
249 | member(Mode, [naive]),
250 | Hops =< Bound,
251 | \+ initial_config(naive,eval,blank,config(Left, State, Item, Dir, Right),_),
252 | % format("Up to ~d: ", [Hops]), display_config(config(Left, State, Item, Dir, Right)),
253 | member(t(NewState, In, Out, TransDir, State), M),
254 | % format(" Current transition is ~k, ~k, ~k, ~k, ~k", [NewState, In, Out, TransDir, State]),
255 | update_backwards(config(Left, State, Item, TransDir, Right), t(NewState, In, Out, TransDir, State), config(NewLeft, NewState, NewItem, NewDir, NewRight)),
256 | % format(" Updated ", []), display_config(config(NewLeft, NewState, NewItem, NewDir, NewRight)), nl,
257 | Hops1 is Hops + 1,
258 | run_backwards(config(NewLeft, NewState, NewItem, NewDir, NewRight), M, Bound, Mode, Hops1).
259 |
260 | update_backwards(config(Left, State, Item, _Dir, Right), t(NewState, In, _Out, r, State), config([], NewState, In, l, [Item|Right])) :- Left == [].
261 | update_backwards(config(Left, State, Item, _Dir, Right), t(NewState, In, Out, r, State), config(RestL, NewState, In, l, [Item|Right])) :- Left = [Out|RestL].
262 | update_backwards(config(Left, State, Item, _Dir, Right), t(NewState, In, _Out, l, State), config([Item|Left], NewState, In, l, [])) :- Right == [].
263 | update_backwards(config(Left, State, Item, _Dir, Right), t(NewState, In, Out, l, State), config([Item|Left], NewState, In, l, RestR)) :- Right = [Out|RestR].
264 |
265 | % looping(_M) :- fail. %% Is this really needed?
266 |
267 | output_row(Symbols) :- output_row1(0, Symbols).
268 | output_row1(Current, Final) :- Current >= Final.
269 | output_row1(Current, Final) :- Current < Final, format("~d", [Current]), NewCurrent is Current + 1, output_row1(NewCurrent, Final).
270 |
271 | output_html_table(Symbols, M) :-
272 | sortmachine(Symbols, a, 0, [], M, SortM),
273 | format(" ", []),
274 | output_row(Symbols),
275 | output_html_table1(SortM).
276 |
277 | output_html_table1([]).
278 | output_html_table1([t(S,I,O,D,NS)|Rest]) :-
279 | format(" | ~k", [S]),
280 | output_html_table2(S,[t(S,I,O,D,NS)|Rest]).
281 |
282 | output_html_table2(S, [t(S,_I,O,D,NS)|Rest]) :-
283 | format(" | ~k ~k ~k", [O, D, NS]),
284 | output_html_table2(S, Rest).
285 |
286 | output_html_table2(State, [t(S,I,O,D,NS)|Rest]) :-
287 | State \== S, % Finished this row
288 | format("~n"),
289 | output_html_table1([t(S,I,O,D,NS)|Rest]).
290 |
291 | output_html_table2(_State, []) :-
292 | % Finished last row
293 | format("~n | ~n").
294 |
295 |
296 |
--------------------------------------------------------------------------------
/bb/harland/engine.pl:
--------------------------------------------------------------------------------
1 | :- include(emulate).
2 | :- include(monsters).
3 | :- include(search).
4 | :- include(generate).
5 | :- include(analyse).
6 | :- include(top).
7 |
8 | :- op(1000, fx, timex).
9 | timex G :- time(G).
10 |
11 | twod1 :- tell('machines2d1.txt'),
12 | machine2d1(1),
13 | machine2d1(2),
14 | machine2d1(3),
15 | machine2d1(4),
16 | machine2d1(5),
17 | machine2d1(6),
18 | machine2d1(7),
19 | machine2d1(8),
20 | machine2d1(9),
21 | told.
22 |
23 | machine2d1(N) :-
24 | machine2d(N,M),
25 | format("Machine ~d: ", [N]), write(M), nl,
26 | format("Native: ~n", []),
27 | emulate_2d(M, blank, 100, naive, rel, [], [final], _Hops1, _Status1, Outputs1), !,
28 | transform_rel_to_abs(M, MT),
29 | format("Transformed : ", []), write(MT), nl,
30 | initial_state(IState), initial_index(Index), initial_map(Map), blank_symbol(Symbol),
31 | initial_direction(Direction), transform_state(IState, Direction, State),
32 | emulate_2d(MT, config2d(State, Index, Map, Symbol), 100, naive, abs, [], [final], _Hops1T, _Status1T, Outputs1T), !,
33 | member(config2d(_, _, MapA, _), Outputs1T), member(config2d(_, _, MapR, _, _), Outputs1),
34 | (MapA == MapR -> format("Same maps~n~n",[]); format("Maps differ~n~n", [])),
35 | transform_abs_to_rel(MT, MTT),
36 | format("Re-transformed : ", []), write(MTT), nl,
37 | transform_state(State, Direction, NewIState), format("New starting state is ~k~n", [NewIState]),
38 | emulate_2d(MTT, config2d(NewIState, Index, Map, Symbol, Direction), 100, naive, rel, [], [final], _Hops1TT, _Status1TT, Outputs1TT), !,
39 | member(config2d(_, _, MapRR, _, _), Outputs1TT),
40 | (MapRR == MapR -> format("Still same maps!~n~n",[]); format("Oops! Maps differ~n~n", [])),
41 | true.
42 |
43 | twod2 :- tell('machines2d2.txt'),
44 | machine2d2(1),
45 | told.
46 |
47 | machine2d2(N) :-
48 | machine2dabs(N,M),
49 | format("Machine ~d: ", [N]), write(M), nl,
50 | format("Native: ~n", []),
51 | emulate_2d(M, blank, 100, naive, abs, [], [final], _Hops1, _Status1, Outputs1), !,
52 | transform_abs_to_rel(M, MT),
53 | format("Transformed : ", []), write(MT), nl,
54 | initial_state(IState), initial_index(Index), initial_map(Map), blank_symbol(Symbol),
55 | initial_direction(Direction), transform_state(IState, Direction, State),
56 | emulate_2d(MT, config2d(State, Index, Map, Symbol, Direction), 100, naive, rel, [], [final], _Hops1T, _Status1T, Outputs1T),
57 | member(config2d(_, _, MapA, _), Outputs1), member(config2d(_, _, MapR, _, _), Outputs1T),
58 | (MapA == MapR -> format("Same maps~n~n",[]); format("Maps differ~n~n", [])),
59 | transform_rel_to_abs(MT, MTT),
60 | format("Re-transformed : ", []), write(MTT), nl,
61 | transform_state(State, Direction, NewIState), format("New starting state is ~k~n", [NewIState]),
62 | emulate_2d(MTT, config2d(NewIState, Index, Map, Symbol), 100, naive, abs, [], [final], _Hops1TT, _Status1TT, Outputs1TT), !,
63 | member(config2d(_, _, MapAA, _), Outputs1TT),
64 | (MapAA == MapA -> format("Still same maps!~n~n",[]); format("Oops! Maps differ~n~n", [])),
65 | true.
66 |
67 | relative(N) :-
68 | N >= 1, N =< 9,
69 | machine2d(N,M), emulate_2d(M, blank, 100, naive, rel, [], [final], _Hops, _Status, _Outputs).
70 |
71 | absolute(N) :-
72 | N == 1, machine2dabs(N,M), emulate_2d(M, blank, 100, naive, abs, [], [final], _Hops, _Status, _Outputs).
73 |
--------------------------------------------------------------------------------
/bb/harland/generate.pl:
--------------------------------------------------------------------------------
1 | create_machines(States, Symbols, Dirs, Style, Type) :-
2 | generate_machines(States, Symbols, Dirs, Style, Type), % format("Numbering~n", []),
3 | number_machines(States, Symbols, Dirs, Style, Type).
4 |
5 | generate_machines(States, Symbols, _Dirs, _Style, _Type) :-
6 | States * Symbols >= 13, !,
7 | format("Too large!~n", []).
8 |
9 | generate_machines(States, Symbols, _Dirs, Style, _Type) :-
10 | States * Symbols < 13, \+ member(Style, [rel,abs]), !,
11 | format("Unknown style ~k~n", [Style]).
12 |
13 | generate_machines(States, Symbols, _Dirs, Style, Type) :-
14 | States * Symbols < 13, member(Style, [rel,abs]), \+ member(Type, [all,free,tnf]), !,
15 | format("Unknown type ~k~n", [Type]).
16 |
17 | generate_machines(States, Symbols, Dirs, Style, Type) :-
18 | States * Symbols < 13, member(Style, [rel,abs]), member(Type, [all,free,tnf]), !,
19 | % format("Calling directory~n", []),
20 |
21 | %% How do we cope with Style information here??
22 | directory(input, States, Symbols, Dirs, Style, Type, Base1), ensure_exists(Base1),
23 | % format("Calling filename~n", []), format("Base 1: ~s~n", [Base1]), ttyflush,
24 | filename(Base1, generate, States, Symbols, Dirs, Style, Type, raw, 1, Name, _File),
25 |
26 | NewFileName = Name,
27 | % format("Name is ~s~n", [Name]), ttyflush,
28 | string_concat(NewBaseName, "-part1.pl", NewFileName),
29 | % format("NewBaseName is ~s~n", [NewBaseName]), ttyflush,
30 | atom_codes(NewFile, NewFileName),
31 |
32 | retractall(fragment(_)), assert(fragment(1)),
33 | tell(NewFile), !,
34 | generate_machines1(NewBaseName, States, Symbols, Dirs, Style, Type), !,
35 | told.
36 |
37 | generate_machines1(Name, States, Symbols, Dirs, Style, Type) :-
38 | find_machine(States, Symbols, Dirs, Style, Type, Machine, Ones, Hops, Status),
39 | find_trans(Machine, M),
40 | write_machine(Name, M, Ones, Hops, Status),
41 | fail.
42 | generate_machines1(_Name, _States, _Symbols, _Dirs, _Style, _Type) :- !.
43 |
44 | write_machine(_Name, Machine, Ones, Hops, Status) :-
45 | current_output(Stream), line_count(Stream, Count),
46 | filelinemax(Max), Count =< Max, !, % Keep writing to same file
47 | bbinternalprint(bb, 3, Machine, Ones, Hops, Status), !.
48 |
49 | write_machine(Name, Machine, Ones, Hops, Status) :-
50 | current_output(Stream), line_count(Stream, Count),
51 | filelinemax(Max), Count > Max, !, % Time for a new file
52 | retract(fragment(Frag)), NewFrag is Frag+1, assert(fragment(NewFrag)),
53 | number_string(NewFrag, NewF),
54 |
55 | % append(Name, "-part", NewF, T1), append(T1, ".pl" , NewFileName),
56 | string_concat(Name, "-part", T11), string_concat(T11, NewF, T1), string_concat(T1, ".pl" , NewFileName),
57 | atom_codes(NewFile, NewFileName), % format("% New file is ~k~n", [NewFile]),!,
58 |
59 | told,
60 | tell(NewFile),
61 |
62 | bbinternalprint(bb,3,Machine,Ones,Hops,Status), !.
63 |
64 | filelinemax(1000000) :- !. % maximum number of lines to write to a file before starting a new one.
65 | % filelinemax(50) :- !. % maximum number of lines to write to a file before starting a new one.
66 |
67 | % find_machine(States, Symbols, Dirs, Style, Type, Machine, Ones, Hops, Status, ),
68 | find_machine(1, _Symbols, Dirs, Style, tnf, [t(a,0,O,D,N)], 0, 0, unknown) :- halt_trans(Dirs, Style, t(a,0,O,D,N)).
69 | find_machine(States, Symbols, Dirs, Style, tnf, Machine, Ones, Hops, Status) :-
70 | Dirs = 2, Style = abs, % Don't know how to do relative machines in one-dimension yet ...
71 | States > 1, bound(States, Symbols, Dirs, search, Bound, _MaxSteps),
72 | initial_machine(States, Symbols, Dirs, Style, M),
73 | % format("Initialised~n",[]),
74 | %% Hmmm... may need to think about arguments here and variety of generation -- eg raw but later most efficiently sorted ...
75 | emulate_search(States, Symbols, Dirs, M, blank, Bound, search, [blank,loop], [], Machine, Ones, Hops, Status, _).
76 | % format("Searched~n", []),
77 | % true.
78 |
79 | find_machine(States, Symbols, Dirs, Style, free, _Machine, 0, 0, unknown) :-
80 | Dirs = 2, Style = abs,
81 | States > 1,
82 | States * Symbols > 10, !, format("Too big for free generation~n", []).
83 |
84 | find_machine(States, Symbols, Dirs, Style, free, Machine, 0, 0, unknown) :-
85 | Dirs = 2, Style = abs,
86 | States > 1,
87 | States * Symbols =< 10, !,
88 | free_trans(States, Symbols, List),
89 | append(Pre, [p(S,I)|Post], List),
90 | b0_transition(States, Symbols, Dirs, Style, t(b,0,O1,D1,N1)),
91 | trans(States, Symbols, Dirs, Pre, Trans1), trans(States, Symbols, Dirs, Post, Trans2),
92 | halt_trans(Dirs, Style, t(S,I,O,D,N)),
93 | append([t(a,0,1,r,b),t(b,0,O1,D1,N1)], Trans1, [t(S,I,O,D,N)], Temp1),
94 | append(Temp1, Trans2, Machine).
95 |
96 | find_machine(States, Symbols, _Dirs, _Style, all, _Machine, 0, 0, unknown) :-
97 | States * Symbols > 8,!, format("Too big for all generation~n", []).
98 |
99 | find_machine(States, Symbols, Dirs, Style, all, Machine, 0, 0, unknown) :-
100 | % 1-halting case
101 | States * Symbols =< 8,
102 | all_trans(States, Symbols, List),
103 | append(Pre, [p(S,I)|Post], List),
104 | trans(States, Symbols, Dirs, Style, Pre, Trans1), trans(States, Symbols, Dirs, Style, Post, Trans2),
105 | halt_trans(Dirs, Style, t(S,I,O,D,N)),
106 | append(Trans1, [t(S,I,O,D,N)], Trans2, Machine).
107 | find_machine(States, Symbols, Dirs, Style, all, Machine, 0, 0, unknown) :-
108 | % 0-halting case, which doesn't make sense for bb machines ...
109 | Dirs > 2,
110 | States * Symbols =< 8,
111 | all_trans(States, Symbols, List),
112 | trans(States, Symbols, Dirs, Style, List, Machine).
113 |
114 | free_trans(2, 2, [p(a,1),p(b,1)]).
115 | free_trans(2, 3, [p(a,1),p(b,1),p(a,2),p(b,2)]).
116 | free_trans(3, 2, [p(a,1),p(b,1),p(c,0),p(c,1)]).
117 | free_trans(2, 4, [p(a,1),p(b,1),p(a,2),p(b,2),p(a,3),p(b,3)]).
118 | free_trans(4, 2, [p(a,1),p(b,1),p(c,0),p(c,1),p(d,0),p(d,1)]).
119 |
120 | all_trans(1, 2, [p(a,0),p(a,1)]).
121 | all_trans(1, 3, [p(a,0),p(a,1),p(a,2)]).
122 | all_trans(1, 4, [p(a,0),p(a,1),p(a,2),p(a,3)]).
123 | all_trans(2, 2, [p(a,0),p(a,1),p(b,0),p(b,1)]).
124 | all_trans(2, 3, [p(a,0),p(a,1),p(a,2),p(b,0),p(b,1),p(b,2)]).
125 | all_trans(3, 2, [p(a,0),p(a,1),p(b,0),p(b,1),p(c,0),p(c,1)]).
126 | all_trans(2, 4, [p(a,0),p(a,1),p(a,2),p(a,3),p(b,0),p(b,1),p(b,2),p(b,3)]).
127 | all_trans(4, 2, [p(a,0),p(a,1),p(b,0),p(b,1),p(c,0),p(c,1),p(d,0),p(d,1)]).
128 |
129 | halt_trans(2, abs, t(_,_,1,r,Halt)) :- halt_state(Halt).
130 | halt_trans(Dirs, abs, t(_,_,1,n,Halt)) :- Dirs > 2, halt_state(Halt).
131 | halt_trans(_Dirs, rel, t(_,_,1,f,Halt)) :- halt_state(Halt).
132 |
133 | trans(_States, _Symbols, _Dirs, _Style, [], []) :- !.
134 | trans(States, Symbols, Dirs, Style, [p(S,I)|Rest], [t(S,I,O,D,N)|Result]) :-
135 | state(States, N), symbol(Symbols, O), dir(Dirs, Style, D),
136 | trans(States, Symbols, Dirs, Style, Rest, Result).
137 |
138 | % Make this far more specific for initial testing ...
139 | initial_machine(States, Symbols, Dirs, Style, [t(a,0,1,r,b), BTrans]) :- b0_transition(States, Symbols, Dirs, Style, BTrans).
140 |
141 | b0_transition(_States, _Symbols, _Dirs, _Style, t(b,0,S,l,a)) :- member(S, [0,1]). % If new state is a or b, direction must be left.
142 | b0_transition(_States, Symbols, _Dirs, _Style, t(b,0,2,l,a)) :- Symbols > 2. % Third symbol, if any, must be 2.
143 | b0_transition(_States, _Symbols, _Dirs, _Style, t(b,0,S,l,b)) :- member(S, [0,1]).
144 | b0_transition(_States, Symbols, _Dirs, _Style, t(b,0,2,l,b)) :- Symbols > 2. % Third symbol, if any, must be 2.
145 | b0_transition(States, _Symbols, Dirs, Style, t(b,0,S,Dir,c)) :- States > 2, member(S, [0,1]), dir(Dirs, Style, Dir).
146 | b0_transition(States, Symbols, Dirs, Style, t(b,0,2,Dir,c)) :- States > 2, Symbols > 2, dir(Dirs, Style, Dir). % Third symbol, if any, must be 2.
147 |
148 | %% Can probably delete this looping(), but want to make sure ...
149 | %% looping(_List, state(Left, _State, In, Right), _History) :- all_blank(Left), all_blank(Right), all_blank([In]). % Blank tape, so it is of no interest
150 | %% looping(_List, state(Left, State, In, Right), History) :- member(state(Left, State, In, Right), History). % Looping
151 | %% looping(List, state(Left, State, In, Right), _History) :- blank_symbol(In), road_runner1(List, Left, State, Right).
152 |
153 | % Numbering
154 |
155 | number_machines(States, Symbols, Dirs, Style, Type) :-
156 | number_all_machine_files(States, Symbols, Dirs, Style, Type, 1, 1).
157 |
158 | number_all_machine_files(States, Symbols, Dirs, Style, Type, N1, _) :-
159 | directory(input, States, Symbols, Dirs, Style, Type, Base1),
160 | filename(Base1, generate, States, Symbols, Dirs, Style, Type, raw, N1, Name, _File),
161 | NewFileName = Name,
162 | \+ exists_file(NewFileName),
163 | % No more files, so stop ...
164 | !, true.
165 |
166 | number_all_machine_files(States, Symbols, Dirs, Style, Type, N1, Current) :-
167 | directory(input, States, Symbols, Dirs, Style, Type, Base1),
168 | filename(Base1, generate, States, Symbols, Dirs, Style, Type, raw, N1, Name, _File),
169 | NewFileName = Name,
170 | exists_file(NewFileName), !,
171 | % Another file, so ...
172 | % format("File found~n", []),
173 | number_one_file(NewFileName, States, Symbols, Dirs, Style, Type, N1, Current, Next), !,
174 | NNew is N1 + 1, !,
175 | % format("Next file ...~n", []),
176 | number_all_machine_files(States, Symbols, Dirs, Style, Type, NNew, Next), !.
177 |
178 | number_one_file(RawName, States, Symbols, Dirs, Style, Type, N, Current, Result) :-
179 | directory(input, States, Symbols, Dirs, Style, Type, Base1), % beaver_output(Base2),
180 | filename(Base1, input, States, Symbols, Dirs, Style, Type, number, N, NameOut, _),
181 | NewFileName = RawName,
182 | atom_codes(NewFile, NewFileName),
183 | open(NewFile, read, Input),
184 | atom_codes(Out, NameOut),
185 | tell(Out), !,
186 | process_number(Current, Input, Result),
187 | close(Input),
188 | told,
189 | delete_file(NewFile), % Remove temp-THING now that it is numbered ...
190 | true.
191 |
192 | process_number(Current, Input, Result) :-
193 | read(Input, Term), !,
194 | process_number1(Current, Input, Term, Result).
195 |
196 | process_number1(Current, _, end_of_file, Current) :- !.
197 | % process_number1(_Current, _Input, Term, _Result) :-
198 | % Term \== end_of_file,
199 | % Term \= bb(_, _M, _Ones, _Hops, _Status), !,
200 | % format("% Unknown term ", []), display(Term), nl, !.
201 | process_number1(Current, Input, Term, Result) :-
202 | Term \== end_of_file,
203 | Term = bb(_, M, Ones, Hops, Status), !,
204 | bbinternalprint(bb,Current,M,Ones,Hops,Status),
205 | NewCurrent is Current + 1, !,
206 | process_number(NewCurrent, Input, Result).
207 |
208 | % Use this when we need to number from the name of the file (Demon Duck of Doom will probably require this)
209 | % number_machines_files(4,2,2,abs,all,1,100)
210 | number_machines_files(_States, _Symbols, _Dirs, _Style, _Type, Start, End) :- Start > End.
211 | number_machines_files(States, Symbols, Dirs, Style, Type, Start, End) :-
212 | Start =< End,
213 | directory(input, States, Symbols, Dirs, Style, Type, Base1),
214 | filename(Base1, generate, States, Symbols, Dirs, Style, Type, raw, Start, Name, _File),
215 | NewFileName = Name,
216 | \+ exists_file(NewFileName), !,
217 | % Don't number this one, but keep going ...
218 | NewStart is Start + 1,
219 | number_machines_files(States, Symbols, Dirs, Style, Type, NewStart, End).
220 |
221 | number_machines_files(States, Symbols, Dirs, Style, Type, Start, End) :-
222 | Start =< End,
223 | directory(input, States, Symbols, Dirs, Style, Type, Base1),
224 | filename(Base1, generate, States, Symbols, Dirs, Style, Type, raw, Start, Name, _File),
225 | NewFileName = Name,
226 | exists_file(NewFileName), !,
227 | % Number this one and move on ...
228 | % Assumes 1,000,000 machines per file ...
229 | % Machines in file N are numbered (N-1) million + 1 to N million
230 | Number is (Start - 1)*1000000 + 1,
231 | number_one_file(NewFileName, States, Symbols, Dirs, Style, Type, Start, Number, _Next), !,
232 | NewStart is Start + 1,
233 | number_machines_files(States, Symbols, Dirs, Style, Type, NewStart, End).
234 |
--------------------------------------------------------------------------------
/bb/harland/monsters.pl:
--------------------------------------------------------------------------------
1 | monster(1, [t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(a,3,1,l,a),t(b,0,3,l,a),t(b,1,1,r,z),t(b,2,2,r,b),t(b,3,2,l,a)]). % Michel 2x4 #a
2 | monster(2, [t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,1,l,a),t(a,3,1,r,a),t(b,0,2,l,a),t(b,1,1,r,z),t(b,2,3,r,a),t(b,3,3,r,b)]). % Michel 2x4 #b
3 | monster(3, [t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(a,3,1,l,a),t(b,0,3,l,a),t(b,1,1,r,z),t(b,2,2,r,b),t(b,3,2,r,a)]). % Michel 2x4 #c
4 | monster(4, [t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,1,r,a),t(a,3,1,r,a),t(b,0,1,l,b),t(b,1,1,l,a),t(b,2,2,l,z),t(b,3,2,r,b)]). % Ligocki 2x4 #a reworked by me
5 | monster(5, [t(a,0,1,r,b),t(a,1,2,l,b),t(a,2,1,l,c),t(b,0,1,l,a),t(b,1,2,r,b),t(b,2,1,r,b),t(c,0,1,r,z),t(c,1,2,l,a),t(c,2,0,l,c)]). % Brady #SB ??? This is a tough one .... macro(3) works but
6 | monster(6, [t(a,0,1,r,b),t(a,1,2,r,a),t(a,2,1,l,a),t(b,0,2,l,c),t(b,1,0,r,c),t(b,2,1,r,b),t(c,0,1,r,z),t(c,1,2,l,a),t(c,2,1,r,b)]). % Brady #b macro(2)
7 | monster(7, [t(a,0,1,r,b),t(a,1,1,r,z),t(a,2,2,l,c),t(b,0,1,l,c),t(b,1,2,r,b),t(b,2,1,l,b),t(c,0,1,l,a),t(c,1,0,r,b),t(c,2,2,l,a)]). % Brady #c macro(2)
8 | monster(8, [t(a,0,1,r,b),t(a,1,1,l,c),t(a,2,2,r,z),t(b,0,1,l,a),t(b,1,1,l,c),t(b,2,2,r,b),t(c,0,1,r,b),t(c,1,2,l,c),t(c,2,1,r,c)]). % Brady #d macro(2)
9 | monster(9, [t(a,0,1,r,b),t(a,1,2,r,a),t(a,2,2,r,c),t(b,0,1,l,c),t(b,1,1,r,z),t(b,2,1,l,a),t(c,0,1,r,a),t(c,1,2,l,b),t(c,2,1,l,c)]). % Souris #a macro(2)
10 | monster(10,[t(a,0,1,r,b),t(a,1,1,l,b),t(a,2,2,l,a),t(b,0,1,l,a),t(b,1,1,r,c),t(b,2,1,r,z),t(c,0,0,l,a),t(c,1,2,r,c),t(c,2,1,l,c)]). % Souris #b macro(2)
11 | monster(11,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(b,0,1,l,c),t(b,1,1,l,a),t(b,2,2,r,c),t(c,0,1,l,z),t(c,1,1,l,a),t(c,2,2,r,b)]). % Lafitte and Papazian #a macro(2)
12 | monster(12,[t(a,0,1,r,b),t(a,1,1,r,z),t(a,2,2,r,b),t(b,0,1,l,c),t(b,1,0,l,b),t(b,2,1,r,a),t(c,0,1,r,a),t(c,1,2,l,c),t(c,2,1,r,c)]). % Lafitte and Papazian #b macro(2)
13 | monster(13,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(b,0,1,l,b),t(b,1,1,l,a),t(b,2,2,r,c),t(c,0,1,r,z),t(c,1,1,l,c),t(c,2,2,r,b)]). % Laitte and Papazian #c macro(2)
14 | monster(14,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(b,0,1,r,c),t(b,1,2,r,b),t(b,2,0,r,c),t(c,0,1,l,a),t(c,1,1,r,z),t(c,2,1,l,a)]). % Lafitte and Papazian #d macro(2)
15 | monster(15,[t(a,0,1,r,b),t(a,1,2,l,z),t(a,2,2,l,c),t(b,0,1,l,c),t(b,1,2,r,b),t(b,2,1,l,b),t(c,0,1,l,a),t(c,1,2,r,c),t(c,2,2,l,a)]). % Lafitte and Papazian #e macro(2)
16 | monster(16,[t(a,0,1,r,b),t(a,1,2,r,c),t(a,2,1,l,a),t(b,0,2,l,a),t(b,1,1,r,b),t(b,2,1,r,z),t(c,0,2,r,b),t(c,1,2,r,a),t(c,2,1,l,c)]). % Ligockis 3x3 #a macro(2) 4 work
17 | monster(17,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,l,c),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,1,l,b),t(c,0,1,r,z),t(c,1,1,r,a),t(c,2,1,r,c)]). % Ligockis 3x3 #b macro(2) 1 work
18 | monster(18,[t(a,0,1,r,b),t(a,1,1,l,c),t(b,0,1,r,c),t(b,1,1,r,b),t(c,0,1,r,d),t(c,1,0,l,e),t(d,0,1,l,a),t(d,1,1,l,d),t(e,0,1,r,z),t(e,1,0,l,a)]).
19 | monster(19,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,1,l,b),t(c,0,1,r,a),t(c,1,1,l,d),t(d,0,1,r,a),t(d,1,1,l,e),t(e,0,1,r,z),t(e,1,0,l,c)]).
20 | monster(20,[t(a,0,1,r,b),t(a,1,0,l,d),t(b,0,1,l,c),t(b,1,1,r,d),t(c,0,1,l,a),t(c,1,1,l,c),t(d,0,1,r,z),t(d,1,1,r,e),t(e,0,1,r,a),t(e,1,0,r,b)]).
21 | monster(21,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,1,r,d),t(c,0,1,l,a),t(c,1,1,l,c),t(d,0,1,r,z),t(d,1,0,r,e),t(e,0,1,l,c),t(e,1,1,r,b)]).
22 | monster(22,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,0,r,d),t(c,0,1,l,a),t(c,1,1,l,c),t(d,0,1,r,z),t(d,1,1,r,e),t(e,0,0,l,e),t(e,1,1,r,b)]).
23 | monster(23,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,0,r,d),t(c,0,1,l,a),t(c,1,1,l,c),t(d,0,1,r,z),t(d,1,1,r,e),t(e,0,1,l,c),t(e,1,1,r,b)]).
24 | monster(24,[t(a,0,1,r,b),t(a,1,1,l,c),t(b,0,0,l,a),t(b,1,0,l,d),t(c,0,1,l,a),t(c,1,1,r,z),t(d,0,1,l,b),t(d,1,1,r,e),t(e,0,0,r,d),t(e,1,0,r,b)]).
25 | monster(25,[t(a,0,1,r,b),t(a,1,1,r,d),t(b,0,1,l,c),t(b,1,0,l,e),t(c,0,0,r,a),t(c,1,0,l,b),t(d,0,1,r,e),t(d,1,1,r,z),t(e,0,1,l,c),t(e,1,1,r,c)]).
26 | monster(26,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,r,c),t(b,1,1,r,d),t(c,0,1,l,a),t(c,1,0,r,b),t(d,0,0,r,e),t(d,1,1,r,z),t(e,0,1,l,c),t(e,1,1,r,a)]).
27 | monster(27,[t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,1,l,b),t(a,3,1,r,a),t(a,4,3,r,a),t(b,0,2,l,b),t(b,1,3,l,a),t(b,2,3,r,a),t(b,3,4,r,b),t(b,4,1,r,z)]). % Lafitte and Papazian #a macro(1) !! but macro(2) is close
28 | monster(28,[t(a,0,1,r,b),t(a,1,2,r,b),t(a,2,3,l,a),t(a,3,2,r,a),t(a,4,3,r,a),t(b,0,2,l,b),t(b,1,2,l,a),t(b,2,1,l,a),t(b,3,4,r,b),t(b,4,1,r,z)]). % Lafitte and Papazian #b macro(2) but macro(1) is close
29 | monster(29,[t(a,0,1,r,b),t(a,1,2,r,b),t(a,2,3,r,b),t(a,3,4,l,a),t(a,4,3,r,a),t(b,0,0,l,a),t(b,1,4,r,b),t(b,2,1,r,z),t(b,3,0,r,b),t(b,4,1,l,b)]). % Lafitte and Papazian #c macro(2)
30 | monster(30,[t(a,0,1,r,b),t(a,1,3,r,b),t(a,2,3,r,b),t(a,3,1,l,a),t(a,4,3,l,b),t(b,0,2,l,a),t(b,1,3,r,a),t(b,2,4,l,b),t(b,3,2,r,a),t(b,4,1,r,z)]). % Lafitte and Papazian #d macro(2), but it is hard work
31 | monster(31,[t(a,0,1,r,b),t(a,1,2,r,b),t(a,2,3,l,a),t(a,3,2,r,a),t(a,4,3,r,a),t(b,0,2,l,b),t(b,1,2,l,a),t(b,2,3,l,a),t(b,3,4,r,b),t(b,4,1,r,z)]). % Lafitte and Papazian #e macro(1) (!!)
32 | monster(32,[t(a,0,1,r,b),t(a,1,3,l,b),t(a,2,1,r,z),t(a,3,1,l,a),t(a,4,1,l,a),t(b,0,2,l,a),t(b,1,3,r,b),t(b,2,4,l,b),t(b,3,4,l,b),t(b,4,3,r,a)]). % Lafitte and Papazian #f macro(1) with macro(2) close
33 | monster(33,[t(a,0,1,r,b),t(a,1,3,r,a),t(a,2,1,l,a),t(a,3,1,l,b),t(a,4,3,l,b),t(b,0,2,l,a),t(b,1,4,l,b),t(b,2,3,r,a),t(b,3,2,r,b),t(b,4,1,r,z)]). % Lafitte and Papazian #g macro(1) (!!)
34 | monster(34,[t(a,0,1,r,b),t(a,1,3,r,a),t(a,2,4,l,b),t(a,3,2,r,a),t(a,4,3,l,a),t(b,0,2,l,a),t(b,1,2,l,z),t(b,2,4,r,b),t(b,3,4,r,b),t(b,4,2,l,b)]). % Lafitte and Papazian #h macro(1) (!!)
35 | monster(35,[t(a,0,1,r,b),t(a,1,3,l,b),t(a,2,4,l,b),t(a,3,4,l,a),t(a,4,2,r,a),t(b,0,2,l,a),t(b,1,4,l,z),t(b,2,3,r,b),t(b,3,4,r,a),t(b,4,3,r,b)]). % Lafitte and Papazian #i macro(1)(!!) with macro(2) close
36 | monster(36,[t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,1,l,a),t(a,3,4,l,a),t(a,4,1,r,a),t(b,0,2,l,b),t(b,1,2,r,a),t(b,2,1,r,z),t(b,3,0,r,a),t(b,4,0,r,b)]). % Lafitte and Papazian #j weird and has multiple regressors macro(3), macro(6), ...
37 | monster(37,[t(a,0,4,l,b),t(a,1,1,r,z),t(a,2,2,r,a),t(a,3,0,l,b),t(a,4,3,l,b),t(b,0,2,r,a),t(b,1,3,l,b),t(b,2,3,r,b),t(b,3,2,l,b),t(b,4,1,l,b)]). % Ligockis #a rework? macro(2), but 3 and 4 work
38 | monster(38,[t(a,0,4,r,b),t(a,1,2,l,a),t(a,2,4,l,a),t(a,3,4,r,a),t(a,4,3,l,a),t(b,0,1,l,a),t(b,1,4,l,a),t(b,2,4,r,a),t(b,3,3,r,b),t(b,4,3,r,z)]). % Ligockis #b rework? macro(2) but 1,2,3,5,6 work
39 | monster(39,[t(a,0,1,r,b),t(a,1,4,l,a),t(a,2,1,l,a),t(a,3,2,l,a),t(a,4,1,r,a),t(b,0,3,l,a),t(b,1,1,r,z),t(b,2,1,r,a),t(b,3,2,r,a),t(b,4,4,r,b)]). % Ligockis #c macro(2), but 1,3,4 work
40 | monster(40,[t(a,0,1,r,b),t(a,1,2,r,a),t(a,2,1,l,a),t(a,3,1,l,b),t(a,4,3,l,b),t(b,0,2,l,a),t(b,1,3,r,b),t(b,2,1,r,z),t(b,3,4,r,a),t(b,4,1,l,a)]). % Ligockis #d macro(2) but others work
41 | monster(41,[t(a,0,1,r,b),t(a,1,2,r,a),t(a,2,1,l,a),t(a,3,3,l,a),t(a,4,2,r,a),t(b,0,2,l,a),t(b,1,3,r,b),t(b,2,4,l,a),t(b,3,1,l,b),t(b,4,1,r,z)]). % Ligockis #e macro(1) but others work
42 | monster(42,[t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,1,l,a),t(a,3,0,l,b),t(a,4,1,r,a),t(b,0,2,l,a),t(b,1,4,l,b),t(b,2,4,l,a),t(b,3,1,r,a),t(b,4,1,r,z)]). % Ligockis #f macro(1) but others work
43 | monster(43,[t(a,0,1,r,b),t(a,1,1,r,z),t(a,2,4,l,a),t(a,3,4,l,b),t(a,4,2,r,a),t(b,0,2,l,b),t(b,1,2,r,b),t(b,2,3,r,b),t(b,3,2,r,a),t(b,4,0,r,b)]). % Ligockis #g macro(1) but others work
44 | monster(44,[t(a,0,1,r,b),t(a,1,3,r,b),t(a,2,3,r,a),t(a,3,1,r,z),t(a,4,2,l,b),t(b,0,2,l,a),t(b,1,4,r,a),t(b,2,4,r,b),t(b,3,2,l,b),t(b,4,0,r,a)]). % Ligockis #h macro(1) but others work
45 | monster(45,[t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,3,l,b),t(a,3,0,l,b),t(a,4,1,r,a),t(b,0,2,l,a),t(b,1,4,l,b),t(b,2,4,l,a),t(b,3,1,r,a),t(b,4,1,r,z)]). % Ligockis #i macro(1) but others work
46 | monster(46,[t(a,0,1,r,b),t(a,1,0,r,b),t(a,2,4,r,a),t(a,3,2,l,b),t(a,4,2,l,a),t(b,0,2,l,a),t(b,1,1,l,b),t(b,2,3,r,b),t(b,3,4,r,a),t(b,4,1,r,z)]). % Ligockis #j macro(1) but others work
47 | monster(47,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,4,r,a),t(a,3,1,l,b),t(a,4,2,l,a),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,3,r,b),t(b,3,2,r,a),t(b,4,1,r,z)]). % Ligockis #k macro(2) 1,3,4 work
48 | monster(48,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,4,r,a),t(a,3,2,l,b),t(a,4,2,l,a),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,3,r,b),t(b,3,4,r,a),t(b,4,1,r,z)]). % Ligockis #l macro(2) 1,4 work
49 | monster(49,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,4,r,a),t(a,3,2,l,b),t(a,4,2,l,a),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,3,r,b),t(b,3,1,r,a),t(b,4,1,r,z)]). % Ligockis #m macro(2) 1,4 work
50 | monster(50,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,a),t(a,3,2,l,b),t(a,4,2,l,a),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,3,r,b),t(b,3,4,r,a),t(b,4,1,r,z)]). % Ligockis #n macro(2) 1 works
51 | monster(51,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,1,l,b),t(c,0,0,l,f),t(c,1,1,l,d),t(d,0,1,r,a),t(d,1,0,l,e),t(e,0,0,r,a),t(e,1,1,l,c),t(f,0,1,r,e),t(f,1,1,r,z)]). % macro(3)
52 | monster(52,[t(a,0,1,r,b),t(a,1,1,r,a),t(b,0,1,l,c),t(b,1,1,l,b),t(c,0,0,r,f),t(c,1,1,l,d),t(d,0,1,r,a),t(d,1,0,l,e),t(e,0,1,l,z),t(e,1,1,l,f),t(f,0,0,l,a),t(f,1,0,l,c)]). % macro(4)
53 | monster(53,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,0,r,a),t(c,0,0,l,d),t(c,1,1,r,z),t(d,0,1,r,e),t(d,1,1,l,d),t(e,0,0,l,f),t(e,1,0,l,e),t(f,0,1,r,f),t(f,1,0,l,b)]). % macro(3)
54 | monster(54,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,0,r,e),t(c,0,1,l,d),t(c,1,0,l,f),t(d,0,0,l,b),t(d,1,1,l,c),t(e,0,1,r,b),t(e,1,1,r,a),t(f,0,1,r,b),t(f,1,1,r,z)]). % macro(4)
55 | monster(55,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,0,r,e),t(c,0,1,l,d),t(c,1,1,l,f),t(d,0,0,l,b),t(d,1,1,l,c),t(e,0,1,r,b),t(e,1,1,r,a),t(f,0,0,l,c),t(f,1,1,r,z)]). % macro(4)
56 | monster(56,[t(a,0,1,r,b),t(a,1,0,l,b),t(b,0,1,l,a),t(b,1,1,l,c),t(c,0,1,l,b),t(c,1,0,r,d),t(d,0,1,r,z),t(d,1,1,r,e),t(e,0,1,r,f),t(e,1,0,r,a),t(f,0,0,r,c),t(f,1,1,l,c)]). % ?? Correct when all otters only go to non-zero case ... faster with macro(2) than with macro(4)
57 | monster(57,[t(a,0,1,r,b),t(a,1,1,l,c),t(b,0,0,l,a),t(b,1,0,l,d),t(c,0,1,l,a),t(c,1,1,r,z),t(d,0,1,l,b),t(d,1,1,r,e),t(e,0,0,r,d),t(e,1,0,r,f),t(f,0,0,r,d),t(f,1,0,l,d)]). % macro(4)
58 | monster(58,[t(a,0,1,r,b),t(a,1,1,l,c),t(b,0,0,l,a),t(b,1,0,l,d),t(c,0,1,l,a),t(c,1,1,r,z),t(d,0,1,l,b),t(d,1,1,r,e),t(e,0,0,r,d),t(e,1,0,r,f),t(f,0,0,r,f),t(f,1,0,l,d)]). % macro(4)
59 | monster(59,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,r,d),t(c,0,1,r,d),t(c,1,1,l,c),t(d,0,1,r,e),t(d,1,1,l,f),t(e,0,0,r,a),t(e,1,1,r,b),t(f,0,1,r,z),t(f,1,0,l,d)]). % macro(4)
60 | monster(60,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,r,d),t(c,0,0,l,b),t(c,1,0,l,e),t(d,0,1,r,a),t(d,1,0,r,b),t(e,0,1,l,f),t(e,1,1,l,c),t(f,0,0,l,a),t(f,1,1,r,z)]). % macro(4)
61 | monster(61,[t(a,0,1,r,b),t(a,1,0,r,c),t(b,0,0,l,a),t(b,1,0,r,d),t(c,0,1,r,d),t(c,1,1,r,z),t(d,0,1,l,e),t(d,1,0,l,d),t(e,0,1,r,f),t(e,1,1,l,b),t(f,0,1,r,a),t(f,1,1,r,e)]). % macro(4)
62 | monster(62,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,r,d),t(c,0,0,l,b),t(c,1,0,l,e),t(d,0,1,r,a),t(d,1,0,r,b),t(e,0,1,l,f),t(e,1,1,l,c),t(f,0,1,r,d),t(f,1,1,r,z)]). % macro(4)
63 | monster(63,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,r,d),t(c,0,1,r,a),t(c,1,0,l,e),t(d,0,1,r,a),t(d,1,0,r,b),t(e,0,1,l,f),t(e,1,1,l,c),t(f,0,1,r,d),t(f,1,1,r,z)]). % macro(4)
64 | monster(64,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,l,d),t(c,0,1,r,d),t(c,1,0,r,c),t(d,0,0,l,b),t(d,1,0,r,e),t(e,0,1,r,c),t(e,1,1,l,f),t(f,0,1,l,e),t(f,1,1,r,z)]). % macro(4)
65 | monster(65,[t(a,0,1,r,b),t(a,1,0,l,c),t(b,0,1,l,a),t(b,1,1,r,c),t(c,0,1,r,a),t(c,1,0,l,d),t(d,0,1,l,e),t(d,1,1,l,c),t(e,0,1,r,f),t(e,1,1,r,z),t(f,0,1,r,a),t(f,1,1,r,e)]). % macro(4)
66 | monster(66,[t(a,0,1,r,b),t(a,1,0,l,b),t(b,0,1,l,c),t(b,1,0,r,e),t(c,0,1,r,e),t(c,1,0,l,d),t(d,0,1,l,a),t(d,1,1,l,a),t(e,0,0,r,a),t(e,1,0,r,f),t(f,0,1,r,e),t(f,1,1,r,z)]). % macro(4) about 24 seconds down to 8 seconds with history at 100
67 | monster(67,[t(a,0,1,r,b),t(a,1,0,l,b),t(b,0,0,r,c),t(b,1,1,l,b),t(c,0,1,r,d),t(c,1,0,l,a),t(d,0,1,l,e),t(d,1,1,l,f),t(e,0,1,l,a),t(e,1,0,l,d),t(f,0,1,r,z),t(f,1,1,l,e)]). % this one is a prick! Terminates with macro(3)!! In about 440 seconds at home Seems much quicker with 3 than 6 finds a lot more otters with history at 1000, but much faster with history at 100. macro(3) history 100 takes about 136 seconds at work improves greatly with history at 300 rather than 120
68 | monster(68,[t(a,0,1,r,b),t(a,1,0,l,f),t(b,0,0,r,c),t(b,1,0,r,d),t(c,0,1,l,d),t(c,1,1,r,e),t(d,0,0,l,e),t(d,1,0,l,d),t(e,0,0,r,a),t(e,1,1,r,c),t(f,0,1,l,a),t(f,1,1,r,z)]). % macro(6) in about 163 seconds at work with non-zero otter macro(2) in about 125 seconds macro(4) in about 170 seconds
69 | % marxens machine #r
70 | monster(69,[t(a,0,1,r,b),t(a,1,0,r,f),t(b,0,0,l,b),t(b,1,1,l,c),t(c,0,1,l,d),t(c,1,0,r,c),t(d,0,1,l,e),t(d,1,1,r,z),t(e,0,1,l,f),t(e,1,0,l,d),t(f,0,1,r,a),t(f,1,0,l,e)]). % Logicki #a macro(6) in about 87 seconds at work. Values are my answers
71 | monster(70,[t(a,0,1,r,b),t(a,1,0,l,e),t(b,0,1,l,c),t(b,1,0,r,a),t(c,0,1,l,d),t(c,1,0,r,c),t(d,0,1,l,e),t(d,1,0,l,f),t(e,0,1,l,a),t(e,1,1,l,c),t(f,0,1,l,e),t(f,1,1,r,z)]). % Logicki #b macro(4) in about 280 seconds. Values are my answers
72 | monster(71,[t(a,0,1,r,b),t(a,1,0,l,d),t(b,0,1,r,c),t(b,1,0,r,f),t(c,0,1,l,c),t(c,1,1,l,a),t(d,0,0,l,e),t(d,1,1,r,z),t(e,0,1,l,a),t(e,1,0,r,b),t(f,0,0,r,c),t(f,1,0,r,e)]). % Kropitz #a macro(?) in about 2616 seconds at work
73 | monster(72,[t(a,0,1,r,b),t(a,1,1,l,e),t(b,0,1,r,c),t(b,1,1,r,f),t(c,0,1,l,d),t(c,1,0,r,b),t(d,0,1,r,e),t(d,1,0,l,c),t(e,0,1,l,a),t(e,1,0,r,d),t(f,0,1,r,z),t(f,1,1,r,c)]). % Kropitz macro(6) in about 890 seconds at work
74 | monster(73,[t(a,0,1,r,b),t(a,1,2,l,c),t(a,2,0,l,c),t(a,3,0,r,a),t(b,0,3,l,c),t(b,1,2,r,c),t(b,2,1,l,b),t(b,3,0,r,c),t(c,0,1,r,a),t(c,1,0,l,b),t(c,2,1,r,z),t(c,3,0,r,b)]). % Ligockis 3x4 #a may need adaptive compression for this one ...
75 | monster(74,[t(a,0,1,r,b),t(a,1,1,l,a),t(a,2,1,l,b),t(a,3,1,r,a),t(b,0,0,l,a),t(b,1,2,r,b),t(b,2,2,l,c),t(b,3,1,r,z),t(c,0,3,r,b),t(c,1,2,l,b),t(c,2,1,r,c),t(c,3,0,r,c)]). % Ligockis 3x4 #b macro(1)
76 | monster(75,[t(a,0,1,r,b),t(a,1,3,r,b),t(a,2,2,l,c),t(a,3,3,l,a),t(b,0,0,r,c),t(b,1,1,r,z),t(b,2,2,r,c),t(b,3,1,l,b),t(c,0,1,l,b),t(c,1,2,l,a),t(c,2,3,r,c),t(c,3,2,l,c)]). % Ligockis 3x4 #c macro(2) history 150
77 | monster(76,[t(a,0,1,r,b),t(a,1,0,r,b),t(a,2,3,l,c),t(a,3,1,r,c),t(b,0,0,r,c),t(b,1,1,r,z),t(b,2,2,r,c),t(b,3,3,r,c),t(c,0,1,l,b),t(c,1,2,l,a),t(c,2,3,l,a),t(c,3,2,r,b)]). % Ligockis 3x4 #d
78 | monster(77,[t(a,0,1,r,b),t(a,1,3,l,a),t(a,2,3,r,c),t(a,3,1,r,a),t(b,0,2,r,c),t(b,1,1,l,a),t(b,2,1,r,z),t(b,3,2,r,b),t(c,0,1,l,c),t(c,1,1,r,b),t(c,2,1,l,b),t(c,3,2,r,a)]). % Ligockis 3x4 #e massive
79 | monster(78,[t(a,0,1,r,b),t(a,1,1,l,a),t(a,2,3,l,a),t(a,3,3,r,c),t(b,0,2,l,c),t(b,1,2,l,b),t(b,2,1,r,b),t(b,3,1,r,a),t(c,0,2,l,a),t(c,1,3,l,c),t(c,2,1,r,z),t(c,3,1,l,b)]). % Ligockis 3x4 #f massive
80 | monster(79,[t(a,0,1,r,b),t(a,1,2,l,b),t(a,2,2,r,a),t(a,3,1,l,a),t(b,0,2,l,a),t(b,1,1,r,c),t(b,2,0,l,b),t(b,3,2,r,a),t(c,0,1,r,b),t(c,1,3,l,c),t(c,2,1,l,a),t(c,3,1,r,z)]). % Ligockis 3x4 #g massive
81 | monster(80,[t(a,0,1,r,b),t(a,1,1,r,a),t(a,2,1,l,b),t(a,3,1,r,c),t(b,0,2,l,a),t(b,1,0,l,b),t(b,2,3,l,c),t(b,3,1,r,z),t(c,0,1,l,b),t(c,1,0,r,c),t(c,2,2,r,a),t(c,3,2,r,c)]). % Ligockis 3x4 #h massive
82 | monster(81,[t(a,0,1,r,b),t(a,1,1,r,a),t(a,2,2,l,b),t(a,3,3,l,a),t(b,0,2,l,a),t(b,1,0,l,b),t(b,2,1,l,c),t(b,3,1,l,b),t(c,0,3,r,b),t(c,1,3,r,c),t(c,2,1,r,z),t(c,3,1,l,c)]). % Ligockis 3x4 #i massive
83 | monster(82,[t(a,0,1,l,b),t(a,1,1,r,c),t(a,2,1,r,d),t(b,0,0,r,a),t(b,1,1,l,d),t(b,2,2,r,z),t(c,0,1,r,a),t(c,1,2,l,c),t(c,2,1,r,c),t(d,0,1,l,b),t(d,1,1,l,c),t(d,2,2,r,a)]). % Ligockis 4x3 #a reworked by me. This will have one less transition ...
84 | monster(83,[t(a,0,1,r,b),t(a,1,0,l,c),t(a,2,1,r,z),t(b,0,2,l,c),t(b,1,1,r,d),t(b,2,0,l,b),t(c,0,2,l,a),t(c,1,1,l,c),t(c,2,1,l,a),t(d,0,1,r,b),t(d,1,2,l,d),t(d,2,2,r,a)]). % Ligockis 4x3 #b massive
85 | monster(84,[t(a,0,1,r,b),t(a,1,2,r,c),t(a,2,1,r,a),t(b,0,2,l,c),t(b,1,1,l,a),t(b,2,1,l,b),t(c,0,2,l,d),t(c,1,0,l,b),t(c,2,0,r,c),t(d,0,0,r,d),t(d,1,1,r,z),t(d,2,0,r,a)]). % Ligockis 4x3 #c massive
86 | monster(85,[t(a,0,1,r,b),t(a,1,1,r,a),t(a,2,0,l,b),t(b,0,2,l,c),t(b,1,1,l,b),t(b,2,1,r,c),t(c,0,0,r,d),t(c,1,2,l,c),t(c,2,1,r,a),t(d,0,2,r,a),t(d,1,1,r,z),t(d,2,1,r,c)]). % Ligockis 4x3 #d massive
87 | monster(86,[t(a,0,1,r,b),t(a,1,1,l,a),t(a,2,1,r,d),t(b,0,2,l,c),t(b,1,0,r,a),t(b,2,1,l,b),t(c,0,2,l,a),t(c,1,0,l,b),t(c,2,0,r,d),t(d,0,2,r,c),t(d,1,1,r,z),t(d,2,0,l,c)]). % Ligockis 4x3 #e massive
88 | monster(87,[t(a,0,1,r,b),t(a,1,2,l,d),t(a,2,1,r,z),t(b,0,2,l,c),t(b,1,2,r,c),t(b,2,2,r,b),t(c,0,1,l,d),t(c,1,0,r,c),t(c,2,1,r,c),t(d,0,2,l,a),t(d,1,2,l,d),t(d,2,0,l,b)]). % Ligockis 4x3 #f massive
89 | monster(88,[t(a,0,1,r,b),t(a,1,1,l,d),t(a,2,1,r,z),t(b,0,1,r,c),t(b,1,2,l,b),t(b,2,2,l,d),t(c,0,1,l,c),t(c,1,2,r,a),t(c,2,0,r,d),t(d,0,1,r,c),t(d,1,1,l,a),t(d,2,0,l,a)]). % Ligockis 4x3 #g massive
90 | monster(89,[t(a,0,1,r,b),t(a,1,0,l,b),t(a,2,1,r,d),t(b,0,2,r,c),t(b,1,2,l,a),t(b,2,0,l,a),t(c,0,1,l,b),t(c,1,0,l,a),t(c,2,0,l,a),t(d,0,1,r,a),t(d,1,0,r,a),t(d,2,1,r,z)]). % Ligockis 4x3 #h massive
91 | monster(90,[t(a,0,1,r,b),t(a,1,1,r,z),t(a,2,2,r,c),t(b,0,2,l,c),t(b,1,2,r,d),t(b,2,0,l,c),t(c,0,1,r,a),t(c,1,2,r,b),t(c,2,0,l,b),t(d,0,1,l,b),t(d,1,0,l,d),t(d,2,2,r,c)]). % Ligockis 4x3 #i massive
92 | monster(91,[t(a,0,1,r,b),t(a,1,0,r,b),t(a,2,1,l,d),t(b,0,2,l,c),t(b,1,0,r,a),t(b,2,1,l,a),t(c,0,2,l,a),t(c,1,1,l,b),t(c,2,1,r,z),t(d,0,2,r,a),t(d,1,1,l,b),t(d,2,0,r,d)]). % Ligockis 4x3 #i reworked by me to avoid getting a blank tape after a few steps. This has 5 fewer steps (!!) then the other one.
93 | monster(92,[t(a,0,5,r,b),t(a,1,5,r,a),t(a,2,3,r,z),t(a,3,1,r,b),t(a,4,3,l,a),t(a,5,1,l,a),t(b,0,4,l,b),t(b,1,1,r,b),t(b,2,4,r,z),t(b,3,2,r,a),t(b,4,5,l,b),t(b,5,5,l,a)]). % Ligockis 2x6 #a macro(1)
94 | monster(93,[t(a,0,4,r,b),t(a,1,4,r,a),t(a,2,4,r,a),t(a,3,1,l,a),t(a,4,1,l,a),t(a,5,1,l,b),t(b,0,4,l,b),t(b,1,2,r,b),t(b,2,5,l,b),t(b,3,3,r,a),t(b,4,3,l,a),t(b,5,1,r,z)]). % Ligockis 2x6 #b macro(1) 2,3,4 work
95 | monster(94,[t(a,0,1,r,b),t(a,1,4,l,a),t(a,2,1,r,a),t(a,3,5,l,b),t(a,4,1,r,a),t(a,5,3,l,b),t(b,0,1,l,b),t(b,1,1,l,a),t(b,2,5,l,a),t(b,3,2,l,a),t(b,4,2,r,b),t(b,5,1,r,z)]). % Ligockis 2x6 #c macro(2), 1,3,4 work
96 | monster(95,[t(a,0,1,r,b),t(a,1,0,r,b),t(a,2,3,l,a),t(a,3,5,l,a),t(a,4,1,r,z),t(a,5,4,l,b),t(b,0,1,l,a),t(b,1,2,r,b),t(b,2,3,l,a),t(b,3,4,l,b),t(b,4,3,r,b),t(b,5,3,r,a)]). % Ligockis 2x6 #d macro(1) 2,4 work
97 | monster(96,[t(a,0,1,r,b),t(a,1,2,l,b),t(a,2,4,r,b),t(a,3,1,l,a),t(a,4,1,r,b),t(a,5,1,r,z),t(b,0,1,l,a),t(b,1,3,r,a),t(b,2,5,r,a),t(b,3,4,l,b),t(b,4,0,r,a),t(b,5,4,l,a)]). % Ligockis 2x6 #e massive
98 | monster(97,[t(a,0,1,r,b),t(a,1,1,l,b),t(a,2,3,r,a),t(a,3,4,l,a),t(a,4,2,l,a),t(a,5,4,l,b),t(b,0,2,l,a),t(b,1,2,r,b),t(b,2,3,l,b),t(b,3,1,l,a),t(b,4,5,r,a),t(b,5,1,r,z)]). % Ligockis 2x6 #f massive
99 | monster(98,[t(a,0,1,r,b),t(a,1,2,l,a),t(a,2,1,r,z),t(a,3,5,l,b),t(a,4,5,l,a),t(a,5,4,l,b),t(b,0,1,l,a),t(b,1,4,r,b),t(b,2,3,r,b),t(b,3,5,l,b),t(b,4,1,l,b),t(b,5,4,r,a)]). % Ligockis 2x6 #g massive
100 | % monster(99, [t(a,0,1,l,d),t(a,1,1,l,b),t(b,0,1,l,z),t(b,1,1,l,a),t(c,0,0,l,b),t(c,1,1,l,d),t(d,0,0,l,e),t(d,1,0,l,d),t(e,0,1,l,f),t(e,1,1,r,c),t(f,0,0,l,g),t(f,1,0,l,f),t(g,0,1,r,g),t(g,1,1,r,e)]). % Green 7x2 from 1964 paper
101 | monster(99, [t(a,0,1,r,b),t(a,1,1,r,d),t(b,0,0,r,e),t(b,1,0,r,b),t(c,0,0,r,d),t(c,1,1,r,b),t(d,0,1,r,z),t(d,1,1,r,a),t(e,0,1,r,f),t(e,1,1,l,c),t(f,0,0,r,g),t(f,1,0,r,f),t(g,0,1,l,g),t(g,1,1,l,e)]). % Green 7x2 from 1964 paper reworked by me.
102 | % monster(100, [t(a,0,1,l,b),t(a,1,1,r,z),t(b,0,0,l,c),t(b,1,1,l,c),t(c,0,0,l,d),t(c,1,0,l,c),t(d,0,1,l,e),t(d,1,1,r,a),t(e,0,0,l,f),t(e,1,0,l,e),t(f,0,1,l,g),t(f,1,1,r,d),t(g,0,0,l,h),t(g,1,0,l,g),t(h,0,1,r,h),t(h,1,1,r,f)]). % Green 8x2 from 1964 paper
103 | monster(100, [t(a,0,1,r,b),t(a,1,1,r,z),t(b,0,0,r,c),t(b,1,1,r,c),t(c,0,0,r,d),t(c,1,0,r,c),t(d,0,1,r,e),t(d,1,1,l,a),t(e,0,0,r,f),t(e,1,0,r,e),t(f,0,1,r,g),t(f,1,1,l,d),t(g,0,0,r,h),t(g,1,0,r,g),t(h,0,1,l,h),t(h,1,1,l,f)]). % Green 8x2 from 1964 paper reworked by me
104 |
105 | origin(1, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 2-state 4-symbol #a from P.Michel").
106 | origin(2, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 2-state 4-symbol #b from P.Michel").
107 | origin(3, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 2-state 4-symbol #c from P.Michel").
108 | origin(4, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 2-state 4-symbol #a from Ligocki & Ligocki rewritten into normal form").
109 | origin(5, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Brady #SB").
110 | origin(6, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Brady #b").
111 | origin(7, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Brady #c").
112 | origin(8, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Brady #d").
113 | origin(9, "http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Souris #a").
114 | origin(10,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Souris #b").
115 | origin(11,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte and Papazian #a").
116 | origin(12,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte and Papazian #b").
117 | origin(13,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte and Papazian #c").
118 | origin(14,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte and Papazian #d").
119 | origin(15,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte and Papazian #e").
120 | origin(16,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a").
121 | origin(17,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
122 | origin(18,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #1").
123 | origin(19,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #2").
124 | origin(20,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #3").
125 | origin(21,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #4").
126 | origin(22,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #5").
127 | origin(23,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #6").
128 | origin(24,"http://www.logique.jussieu.fr/~michel/ha.html#tm52", " Uhing").
129 | origin(25,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " 5-state record list #7").
130 | origin(26,"http://www.logique.jussieu.fr/~michel/ha.html#tm52", " Schult").
131 | origin(27,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #a").
132 | origin(28,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #b").
133 | origin(29,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #c").
134 | origin(30,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #d").
135 | origin(31,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #e").
136 | origin(32,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #f").
137 | origin(33,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #g").
138 | origin(34,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #h").
139 | origin(35,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #i").
140 | origin(36,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Lafitte & Papazian #j").
141 | origin(37,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a").
142 | origin(38,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
143 | origin(39,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #c").
144 | origin(40,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #d").
145 | origin(41,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #e").
146 | origin(42,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #f").
147 | origin(43,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #g").
148 | origin(44,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #h").
149 | origin(45,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #i").
150 | origin(46,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #j").
151 | origin(47,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #k").
152 | origin(48,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #l").
153 | origin(49,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #m").
154 | origin(50,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #n").
155 | origin(51,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " old 6-state list #1").
156 | origin(52,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " old 6-state list #2").
157 | origin(53,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #a").
158 | origin(54,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #b").
159 | origin(55,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #c").
160 | origin(56,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #d").
161 | origin(57,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #e").
162 | origin(58,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #g").
163 | origin(59,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #i").
164 | origin(60,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #j").
165 | origin(61,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #k").
166 | origin(62,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #l").
167 | origin(63,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #m").
168 | origin(64,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #n").
169 | origin(65,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #o").
170 | origin(66,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #p").
171 | origin(67,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #r").
172 | origin(68,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " new 6-state list #s").
173 | origin(69,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a").
174 | origin(70,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
175 | origin(71,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Kropitz #a").
176 | origin(72,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Kropitz #b").
177 | origin(73,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a").
178 | origin(74,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
179 | origin(75,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #c").
180 | origin(76,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #d").
181 | origin(77,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #e").
182 | origin(78,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #f").
183 | origin(79,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #g").
184 | origin(80,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #h").
185 | origin(81,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #i").
186 | origin(82,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a reworked by me. Mine has one less transition").
187 | origin(83,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
188 | origin(84,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #c").
189 | origin(85,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #d").
190 | origin(86,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #e").
191 | origin(87,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #f").
192 | origin(88,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #g").
193 | origin(89,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #h").
194 | origin(90,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #i").
195 | origin(91,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #i reworked by me to avoid blank tape. Mine has 5 less transitions").
196 | origin(92,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #a").
197 | origin(93,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #b").
198 | origin(94,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #c").
199 | origin(95,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #d").
200 | origin(96,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #e").
201 | origin(97,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #f").
202 | origin(98,"http://www.drb.insel.de/~heiner/BB/bbsimtab.html", " Ligocki & Ligocki #g").
203 | origin(99, "http://dl.acm.org/citation.cfm?id=1449643", " Green, from 1964 paper").
204 | origin(100,"http://dl.acm.org/citation.cfm?id=1449643", " Green, from 1964 paper").
205 |
206 | machine2d(1, [t(a,0,1,l,a), t(a,1,0,r,a)]). % Turk 1
207 | machine2d(2, [t(a,0,1,l,a), t(a,1,0,f,b),t(b,0,1,r,a),t(b,1,1,r,a)]). % Turk 2
208 | machine2d(3, [t(a,0,1,r,a), t(a,1,2,r,a),t(a,2,3,r,a),t(a,3,0,l,a)]). % Turk 3
209 | machine2d(4, [t(a,0,1,r,a), t(a,1,1,r,b),t(b,0,0,f,a),t(b,1,1,f,b)]). % Turmite from wikipedia
210 | machine2d(5, [t(a,0,1,l,a), t(a,1,0,f,a)]). % Pegg's binary counter
211 | machine2d(6, [t(a,0,1,r,a), t(a,1,0,l,a)]). % Langton's ant. Sinister sibling to machine 1.
212 | machine2d(7, [t(a,0,1,r,b), t(a,1,0,l,b),t(b,0,1,f,a),t(b,1,0,f,a)]). % Turmite from math games
213 | machine2d(8, [t(a,0,1,l,b), t(a,1,0,l,b),t(b,0,1,r,b),t(b,1,0,l,a)]). % Turmite from math games
214 | machine2d(9, [t(a,0,1,r,b), t(a,1,0,r,b),t(b,0,1,f,a),t(b,1,1,f,b)]). % Turmite from math games
215 |
216 | % transformed version of machine 6 is below
217 | % t(an,0,1,e,ae),t(an,1,0,w,aw),t(ae,0,1,s,as),t(ae,1,0,n,an),t(as,0,1,w,aw),t(as,1,0,e,ae),t(aw,0,1,n,an),t(aw,1,0,s,as)
218 |
219 | machine2dabs(1, [t(a,0,1,n,a), t(a,1,0,e,a)]). % Turk 1
220 |
221 | kellett([t(a,0,1,r,c),t(a,1,1,r,z),t(b,0,0,r,a),t(b,1,1,r,c),t(c,0,1,l,d),t(c,1,1,r,e),t(d,0,1,r,e),t(d,1,1,l,d),t(e,0,1,r,z),t(e,1,1,r,b)]).
222 |
--------------------------------------------------------------------------------
/bb/harland/search.pl:
--------------------------------------------------------------------------------
1 | % Search only, not generation as well
2 | % analyses(2,3,2,tnf,analyse,[small,medium,large]).
3 | % Designed to be used once the list of machines has been generated.
4 |
5 | process(States, Symbols, Dirs, Type, Mode, Args) :- process(States, Symbols, Dirs, abs, Type, Mode, Args). % For backwards compatibility ...
6 | process(States, Symbols, Dirs, Style, Type, Mode, Args) :-
7 | % files(States, Symbols, Dirs, Type, Number),
8 |
9 | initialise_counters(Counters),
10 | % format("About to iterate~n", []), flush_output,
11 | iterate_file(States, Symbols, Dirs, Type, Mode, Args, Counters, Final_Counters, 1), !,
12 |
13 | % format("Outputting summary~n", []), flush_output,
14 | % Now write summary file
15 | % beaver_output(Base2),
16 | directory(output,States,Symbols,Dirs,Style,Type,Base2), ensure_exists(Base2),
17 | filename(Base2, output, States, Symbols, Dirs, Style, Type, Mode, 1, Name, _),
18 | % format("Summary Filename is ~s~n", [Name]), flush_output,
19 | basename(Name, BaseName),
20 | summary_name(Mode, M), append(BaseName, M, "-summary.pl", RealName),
21 | % format("Summary is ~s~n", [RealName]), flush_output,
22 | atom_codes(File, RealName),
23 | % format("Outputting counters~n", []), flush_output,
24 |
25 | tell(File), output_counters(Final_Counters), told.
26 |
27 | iterate_file(States, Symbols, Dirs, Style, Type, Mode, Args, Counters, Final_Counters, N1) :-
28 | which_dir(Mode, States, Symbols, Dirs, Style, Type, Base1), % format("Calling filename~n",[]),
29 | mode_status(Mode, Status),
30 | filename(Base1, Status, States, Symbols, Dirs, Style, Type, Mode, N1, _Name, File),
31 | % format("Filename is ~s~n", [Name]),
32 | \+ exists_file(File),
33 |
34 | % When the Mode is refine, we need to refine the output Abort file. Otherwise update counters from the output Abort file, if any.
35 | % format("% Handling aborts~n", []), flush_output,
36 | handle_aborts(States, Symbols, Dirs, Style, Type, Mode, Args, Counters, Final_Counters),
37 | % format("% Aborts done~n", []), flush_output,
38 | true.
39 |
40 | iterate_file(States, Symbols, Dirs, Style, Type, Mode, Args, Counters, Final_Counters, N1) :-
41 | which_dir(Mode, States, Symbols, Dirs, Style, Type, Base1), % format("Calling filename again~n",[]),
42 | mode_status(Mode, Status),
43 | filename(Base1, Status, States, Symbols, Dirs, Style, Type, Mode, N1, _Name, File),
44 | % format("Filename is ~s~n", [Name]),
45 | exists_file(File), !,
46 |
47 | % format("Processing one file with ~k ~k ~n", [Type,Mode]),
48 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N1, Counters, NewCounters), !,
49 | NNew is N1 + 1, !,
50 | % output_counters(NewCounters),
51 | iterate_file(States, Symbols, Dirs, Type, Mode, Args, NewCounters, Final_Counters, NNew), !.
52 |
53 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
54 | Mode = analyse,
55 | directory(input, States, Symbols, Dirs, Style, Type, Base1), directory(output, States, Symbols, Dirs, Style, Type, Base2),
56 | ensure_exists(Base1), ensure_exists(Base2),
57 | filename(Base1, input, States, Symbols, Dirs, Style, Type, Mode, N, _Name, File),
58 | filename(Base2, output, States, Symbols, Dirs, Style, Type, Mode, N, NameOut, _),
59 | append_to_plfile(NameOut, "-out", OutName),
60 | append_to_plfile(NameOut, "-going", GoingName),
61 | open(File, read, Input),
62 | atom_codes(Out, OutName),
63 | tell(Out),
64 | atom_codes(GoingFile, GoingName),
65 | open(GoingFile, write, Go),
66 |
67 | initialise_local_counters(Counters, NewCounters),
68 | process_one_file1(States, Symbols, Dirs, Style, Input, analyse, Args, Go, NewCounters, Final_Counters), !,
69 | output_counters(Final_Counters),
70 |
71 | close(Input), close(Go), told.
72 |
73 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
74 | Mode = refine,
75 | % beaver_input(Base1), beaver_output(Base2),
76 | directory(output, States, Symbols, Dirs, Style, Type, Base2), ensure_exists(Base2),
77 | filename(Base2, input, States, Symbols, Dirs, Style, Type, Mode, N, _Name, File),
78 | filename(Base2, output, States, Symbols, Dirs, Style, Type, Mode, N, OutName, Out),
79 | append_to_plfile(OutName, "-going", GoingName),
80 | open(File, read, Input),
81 | tell(Out),
82 | atom_codes(GoingFile, GoingName),
83 | open(GoingFile, write, Go),
84 |
85 | initialise_local_counters(Counters, NewCounters),
86 | process_one_file1(States, Symbols, Dirs, Style, Input, analyse, Args, Go, NewCounters, Final_Counters), !,
87 | output_counters(Final_Counters),
88 |
89 | close(Input), close(Go), told.
90 |
91 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
92 | Mode = pseudouni,
93 | directory(input, States, Symbols, Dirs, Style, Type, Base1), directory(output, States, Symbols, Dirs, Style, Type, Base2),
94 | ensure_exists(Base1), ensure_exists(Base2),
95 | filename(Base1, input, States, Symbols, Dirs, Style, Type, Mode, N, _Name, File),
96 | filename(Base2, output, States, Symbols, Dirs, Style, Type, Mode, N, NameOut, _),
97 | append_to_plfile(NameOut, "-pseudo", OutName),
98 | open(File, read, Input),
99 | atom_codes(Out, OutName),
100 | tell(Out),
101 |
102 | initialise_local_counters(Counters, NewCounters),
103 | process_one_file1(States, Symbols, Dirs, Style, Input, pseudouni, Args, _Go, NewCounters, Final_Counters), !,
104 | output_counters(Final_Counters),
105 |
106 | close(Input), told.
107 |
108 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
109 | Mode = stats,
110 | directory(input, States, Symbols, Dirs, Style, Type, Base1), % output_dir(States, Symbols, Dirs, Base2),
111 | ensure_exists(Base1),
112 |
113 | filename(Base1, input, States, Symbols, Dirs, Style, Type, Mode, N, _, File),
114 | % filename(Base2, output, States, Symbols, Dirs, Type, Mode, N, NameOut, _),
115 | % add_to_plfile(NameOut, "-stats", OutName),
116 | open(File, read, Input),
117 | % atom_codes(Out, OutName),
118 | % tell(Out),
119 |
120 | initialise_local_counters(Counters, NewCounters),
121 | process_one_file1(States, Symbols, Dirs, Style, Input, stats, Args, _Go, NewCounters, Final_Counters), !,
122 | output_counters(Final_Counters),
123 |
124 | close(Input).
125 |
126 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
127 | Mode = status,
128 | directory(output, States, Symbols, Dirs, Style, Type, Base2), ensure_exists(Base2),
129 |
130 | filename(Base2, output, States, Symbols, Dirs, Style, Type, Mode, N, _, File),
131 | % filename(Base2, output, States, Symbols, Dirs, Type, Mode, N, NameOut, _),
132 | open(File, read, Input),
133 | % atom_codes(Out, OutName),
134 | % tell(Out),
135 |
136 | initialise_local_counters(Counters, NewCounters),
137 | process_one_file1(States, Symbols, Dirs, Style, Input, status, Args, _Go, NewCounters, Final_Counters), !,
138 | output_counters(Final_Counters),
139 |
140 | close(Input).
141 |
142 | process_one_file(States, Symbols, Dirs, Style, Type, Mode, Args, N, Counters, Final_Counters) :-
143 | Mode = convert(Format, Numbered), % format("Converting ... ~n", []),
144 | member(Format, [marxen]),
145 | directory(input, States, Symbols, Dirs, Style, Type, Base1),
146 | filename(Base1, input, States, Symbols, Dirs, Style, Type, Mode, N, _InName, InFile),
147 | filename(Base1, output, States, Symbols, Dirs, Style, Type, Mode, N, OutName, _OutFile),
148 | % format("Names done~n", []),
149 | open(InFile, read, Input),
150 | append(BaseName, ".pl", OutName), append(BaseName, ".txt", RealOutName),
151 | % format("RealOutName is ~s~n", [RealOutName]),
152 | atom_codes(Out, RealOutName),
153 | tell(Out),
154 |
155 | process_one_file1(States, Symbols, Dirs, Style, Input, convert(Format, Numbered), Args, _Go, Counters, Final_Counters),
156 |
157 | close(Input).
158 |
159 | process_one_file(_States, _Symbols, _Dirs, _Style, _Type, Mode, _Args, _N, Counters, Counters) :-
160 | Mode = convert(Format, _Numbered),
161 | \+ member(Format, [marxen]),
162 | !, true.
163 |
164 | process_one_file1(States, Symbols, Dirs, Style, Input, Mode, Args, GoFile, Counters, Final_Counters) :-
165 | read(Input, Term), !,
166 | process_one_file11(States, Symbols, Dirs, Style, Term, Input, Mode, Args, GoFile, Counters, Final_Counters).
167 |
168 | process_one_file11(_States, _Symbols, _Dirs, _Style, end_of_file, _Input, _Mode, _Args, _GoFile, Counters, Counters).
169 | process_one_file11(States, Symbols, Dirs, Style, Term, Input, Mode, Args, GoFile, Counters, Final_Counters) :-
170 | Term \== end_of_file,
171 | process_term(States, Symbols, Dirs, Style, Term, Mode, Args, GoFile, Counters, NCounters), !,
172 | process_one_file1(States, Symbols, Dirs, Style, Input, Mode, Args, GoFile, NCounters, Final_Counters).
173 |
174 | process_term(_,_,_,_,end_of_file, _, _, _, Counters, Counters) :- !.
175 | process_term(States, Symbols, Dirs, _Style, bb(N, Machine, Ones, Hops, Status), Mode, Args, GoFile, Counters, Final_Counters) :-
176 | Mode = analyse, \+ member(Status, [abort, abort(_)]),
177 | % format("% Analysing: ", []), bbinternalprint(bb, N, Machine, 0, 0, unknown),
178 | analyse(States, Symbols, Dirs, N, Machine, Ones, Hops, Status, Args, NewOnes, NewHops, NewStatus, _NewOutputs), !,
179 | bbinternalprint(bb, N, Machine, NewOnes, NewHops, NewStatus), !, flush_output,
180 | check_going(GoFile, N, Machine, NewOnes, NewHops, NewStatus), !, flush_output,
181 | update_counters(Machine, NewOnes, NewHops, NewStatus, Counters, Final_Counters), !.
182 | process_term(States, Symbols, Dirs, Style, bb(N, Machine, Ones, Hops, Status), Mode, _Args, _GoFile, Counters, Final_Counters) :-
183 | Mode = analyse, member(Status, [abort, abort(_)]),
184 | format("% Processing abort ~n", []),
185 | % First output original machine ...
186 | bbinternalprint(bb, N, Machine, Ones, Hops, Status), !, flush_output,
187 | update_counters(Machine, Ones, Hops, Status, Counters, Final_Counters),
188 | % Then find some more machines and write them to an 'extra' file.
189 | format("% Finding Files~n", []),
190 | directory(output, States, Symbols, Dirs, Style, tnf, Base), ensure_exists(Base),
191 | filename(Base, input, States, Symbols, Dirs, Style, tnf, abort, 1, _Name1, AbortInFile),
192 | format("% Found input~n", []),
193 | filename(Base, output, States, Symbols, Dirs, Style, tnf, abort, 1, _Name2, AbortOutFile),
194 | format("% Finding extras~n", []),
195 | find_extra_machines(States, Symbols, Dirs, Style, N, Machine, AbortInFile, AbortOutFile).
196 |
197 | process_term(_States, _Symbols, _Dirs, _Style, bb(N, Machine, _Ones, _Hops, _Status), Mode, _Args, _GoFile, Counters, Final_Counters) :-
198 | Mode = analyse, % In case analysis fails for some reason ...
199 | bbinternalprint(bb, N, Machine, 0, 0, unknown), !, flush_output,
200 | update_counters(Machine, 0, 0, unknown, Counters, Final_Counters), !.
201 |
202 | process_term(_States, _Symbols, _Dirs, _Style, bb(N, Machine, Ones, Hops, Status), Mode, Args, _GoFile, Counters, Final_Counters) :-
203 | Mode = pseudouni, !,
204 | pseudouni(Machine, Args, Ones, Hops, Status, NewOnes, NewHops, NewStatus), !,
205 | bbinternalprint(bb, N, Machine, NewOnes, NewHops, NewStatus), !,
206 | update_counters(Machine, NewOnes, NewHops, NewStatus, Counters, Final_Counters), !.
207 |
208 | process_term(_States, _Symbols, _Dirs, _Style, bb(_N, Machine, Ones, Hops, Status), Mode, _Args, _, Counters, Final_Counters) :-
209 | member(Mode, [stats,status]), !,
210 | % ( member(Status, [abort, abort(_)]) ->
211 | % ( directory(output, States, Symbols, Dirs, tnf, Base), ensure_exists(Base),
212 | % filename(Base, input, States, Symbols, Dirs, tnf, abort, 1, Name, AbortInFile),
213 | % open(AbortInFile, append, File),
214 | % write(File, bb(N, Machine, Ones, Hops, Status)), put_char(File, '.'), nl(File),
215 | % close(File)
216 | % )
217 | % ; true ),
218 | update_counters(Machine, Ones, Hops, Status, Counters, Final_Counters), !.
219 |
220 | process_term(States, Symbols, Dirs, _Style, bb(N, Machine, _Ones, _Hops, _Status), Mode, _Args, _GoFile, Counters, Counters) :-
221 | Mode = convert(Format, Numbered),
222 | % format("Converting ... ~n", []),
223 | convert_machine(Format, States, Symbols, Dirs, Machine, NewMachine),
224 | (Numbered == numbered -> ( format("~d", [N]), separator(S), format("~s", [S]) ) ; true ),
225 | format("~s~n", [NewMachine]), % NewMachine is a string, whatever format is used
226 | flush_output,
227 | !.
228 |
229 | process_term(_States, _Symbols, _Dirs, _Style, Term, _, _Args, _, Counters, Counters) :-
230 | Term \== bb(_N, _Machine, _Ones, _Hops, _Status),
231 | format("Unknown term ", []), display(Term), nl.
232 |
233 | separator(",").
234 | % separator(" ").
235 |
236 | append_to_plfile(Name, Suffix, NewName) :-
237 | append(RealName, ".pl", Name), append(RealName, Suffix, ".pl", NewName).
238 |
239 | prepend_to_plfile(Name, Prefix, NewName) :-
240 | split_file(Name, Dir, File), append(Prefix, File, NewFile), append(Dir, NewFile, NewName).
241 |
242 | split_file(Name, Dir, File) :-
243 | append(Dir, File, Name), append(_, "/", Dir), \+ member(47, File). % 47 is "/" but without the list type.
244 |
245 | find_extra_machines(States, Symbols, Dirs, Style, N, Machine, Raw, Refined) :-
246 | open(Raw, append, RawOutput),
247 | open(Refined, append, RefinedOutput),
248 | find_extra_machines1(States, Symbols, Dirs, Style, N, Machine, RawOutput, RefinedOutput),
249 | close(RawOutput), close(RefinedOutput).
250 |
251 | find_extra_machines1(States, Symbols, Dirs, _Style, N, Machine, RawOutput, RefinedOutput) :-
252 | find_trans(Machine, M),
253 | bound(States, Symbols, Dirs, abort, Bound, _),
254 | emulate_search(States, Symbols, Dirs, M, blank, Bound, search, [loop], [], NewMachine, Ones, Hops, Status, _),
255 | find_trans(NewMachine, NewTrans),
256 | write(RawOutput, bb(N, NewTrans, Ones, Hops, Status)), put_char(RawOutput, '.'), nl(RawOutput),
257 | analyse(States, Symbols, Dirs, N, NewMachine, Ones, Hops, Status, [], NewOnes, NewHops, NewStatus, _),
258 | write(RefinedOutput, bb(N, NewTrans, NewOnes, NewHops, NewStatus)), put_char(RefinedOutput, '.'), nl(RefinedOutput),
259 | %% Can't do counters here because of fail-driven loop. Ensure analyse and refine cases also used abort file for input and output.
260 | fail.
261 | find_extra_machines1(_States, _Symbols, _Dirs, _Style, _N, _Machine, _RawOutput, _RefinedOutput).
262 |
263 | % Status can be unknown, going, going(_), halts, meander, blank, loops(cycle), loops, loops(cycle(_)), loops(road_runner), loops(induction(_)), normal, pseudo, pseudo(_,_),
264 |
265 | initialise_counters(counters(local(0,0,0,0,0,0,0,0,0,0), global(0,0,0,0,0,0,0,0,0,0), records([]) ) ) :- true.
266 | initialise_local_counters(counters(_, Global, Records), counters(local(0,0,0,0,0,0,0,0,0,0), Global, Records) ) :- true.
267 | output_counters(counters(
268 | local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
269 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort),
270 | Records
271 | )) :-
272 | LSum is LocalUnknown + LocalGoing + LocalHalt + LocalMeander + LocalBlank + LocalCycle + LocalRoadRunner + LocalInduction + LocalPseudo + LocalAbort,
273 | GSum is GlobalUnknown + GlobalGoing + GlobalHalt + GlobalMeander + GlobalBlank + GlobalCycle + GlobalRoadRunner + GlobalInduction + GlobalPseudo + GlobalAbort,
274 | format("% Local: Unknown: ~d Going: ~d Halt: ~d Meander: ~d Blank: ~d Cycle: ~d RoadRunner: ~d Induction: ~d Pseudo: ~d Abort ~d Total: ~d~n", [LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort, LSum]),
275 | ( GSum > 0 ->
276 | (
277 | format("% Global: Unknown: ~d (~1f%)", [GlobalUnknown, 100*GlobalUnknown/GSum]),
278 | format("% Going: ~d (~1f%)", [GlobalGoing, 100*GlobalGoing/GSum]),
279 | format("% Halt: ~d (~1f%) ", [GlobalHalt, 100*GlobalHalt/GSum]),
280 | format("% Meander: ~d (~1f%) ", [GlobalMeander, 100*GlobalMeander/GSum]),
281 | format("% Blank: ~d (~1f%) ", [GlobalBlank, 100*GlobalBlank/GSum]),
282 | format("% Cycle: ~d (~1f%) ", [GlobalCycle, 100*GlobalCycle/GSum]),
283 | format("% RoadRunner: ~d (~1f%)", [GlobalRoadRunner, 100*GlobalRoadRunner/GSum]),
284 | format("% Induction: ~d (~1f%) ", [GlobalInduction, 100*GlobalInduction/GSum]),
285 | format("% Pseudo: ~d (~1f%) ", [GlobalPseudo, 100*GlobalPseudo/GSum]),
286 | format("% Abort ~d (~1f%) ", [GlobalAbort, 100*GlobalAbort/GSum]),
287 | format("% Total: ~d~n", [GSum]) )
288 | ;
289 | (
290 | format("% Global: Unknown: ~d ", [GlobalUnknown]),
291 | format("% Going: ~d ", [GlobalGoing]),
292 | format("% Halt: ~d ", [GlobalHalt]),
293 | format("% Meander: ~d ", [GlobalMeander]),
294 | format("% Blank: ~d ", [GlobalBlank]),
295 | format("% Cycle: ~d ", [GlobalCycle]),
296 | format("% RoadRunner: ~d ", [GlobalRoadRunner]),
297 | format("% Induction: ~d ", [GlobalInduction]),
298 | format("% Pseudo: ~d ", [GlobalPseudo]),
299 | format("% Abort ~d ", [GlobalAbort]),
300 | format("% Total: ~d~n", [GSum]) )
301 | ),
302 |
303 | Records = records(List),
304 | format("% Records: ~n", []),
305 | sort_records(List, SList), reverse(SList, FinalList), output_records(FinalList),
306 | true.
307 |
308 | update_counters(_Machine, _Ones, _Hops, Status,
309 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
310 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
311 | counters(local(NewLocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
312 | global(NewGlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
313 | member(Status, [unknown]),
314 | NewLocalUnknown is LocalUnknown + 1,
315 | NewGlobalUnknown is GlobalUnknown + 1,
316 | true.
317 | update_counters(_Machine, _Ones, _Hops, Status,
318 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
319 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
320 | counters(local(LocalUnknown, NewLocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
321 | global(GlobalUnknown, NewGlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
322 | member(Status, [going,going(_)]),
323 | NewLocalGoing is LocalGoing + 1,
324 | NewGlobalGoing is GlobalGoing + 1,
325 | true.
326 | update_counters(Machine, Ones, Hops, Status,
327 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
328 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), records(List)),
329 | counters(local(LocalUnknown, LocalGoing, NewLocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
330 | global(GlobalUnknown, GlobalGoing, NewGlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), records(NewList)) ) :-
331 | member(Status, [halts]),
332 | NewLocalHalt is LocalHalt + 1,
333 | NewGlobalHalt is GlobalHalt + 1,
334 | checkmax(List, Machine, Ones, Hops, NList), !, checkmin(NList, Machine, Ones, Hops, NewList), !,
335 | true.
336 | update_counters(_Machine, _Ones, _Hops, Status,
337 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
338 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
339 | counters(local(LocalUnknown, LocalGoing, LocalHalt, NewLocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
340 | global(GlobalUnknown, GlobalGoing, GlobalHalt, NewGlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
341 | member(Status, [meander]),
342 | NewLocalMeander is LocalMeander + 1,
343 | NewGlobalMeander is GlobalMeander + 1,
344 | true.
345 | update_counters(_Machine, _Ones, _Hops, Status,
346 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
347 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
348 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, NewLocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
349 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, NewGlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
350 | member(Status, [blank]),
351 | NewLocalBlank is LocalBlank + 1,
352 | NewGlobalBlank is GlobalBlank + 1,
353 | true.
354 | update_counters(_Machine, _Ones, _Hops, Status,
355 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
356 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
357 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, NewLocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
358 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, NewGlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
359 | member(Status, [loops,loops(cycle),loops(cycle(_))]),
360 | NewLocalCycle is LocalCycle + 1,
361 | NewGlobalCycle is GlobalCycle + 1,
362 | true.
363 | update_counters(_Machine, _Ones, _Hops, Status,
364 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
365 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
366 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, NewLocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
367 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, NewGlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
368 | member(Status, [loops(road_runner)]),
369 | NewLocalRoadRunner is LocalRoadRunner + 1,
370 | NewGlobalRoadRunner is GlobalRoadRunner + 1,
371 | true.
372 | update_counters(_Machine, _Ones, _Hops, Status,
373 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
374 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
375 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, NewLocalInduction, LocalPseudo, LocalAbort),
376 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, NewGlobalInduction, GlobalPseudo, GlobalAbort), Records) ) :-
377 | member(Status, [loops(induction(_,_,_))]),
378 | NewLocalInduction is LocalInduction + 1,
379 | NewGlobalInduction is GlobalInduction + 1,
380 | true.
381 | update_counters(_Machine, _Ones, _Hops, Status,
382 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
383 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
384 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, NewLocalPseudo, LocalAbort),
385 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, NewGlobalPseudo, GlobalAbort), Records) ) :-
386 | member(Status, [pseudo,pseudo(_)]),
387 | NewLocalPseudo is LocalPseudo + 1,
388 | NewGlobalPseudo is GlobalPseudo + 1,
389 | true.
390 | update_counters(_Machine, _Ones, _Hops, Status,
391 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, LocalAbort),
392 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, GlobalAbort), Records),
393 | counters(local(LocalUnknown, LocalGoing, LocalHalt, LocalMeander, LocalBlank, LocalCycle, LocalRoadRunner, LocalInduction, LocalPseudo, NewLocalAbort),
394 | global(GlobalUnknown, GlobalGoing, GlobalHalt, GlobalMeander, GlobalBlank, GlobalCycle, GlobalRoadRunner, GlobalInduction, GlobalPseudo, NewGlobalAbort), Records) ) :-
395 | member(Status, [abort, abort(_)]),
396 | NewLocalAbort is LocalAbort + 1,
397 | NewGlobalAbort is GlobalAbort + 1,
398 | true.
399 |
400 | update_counters(_Machine, _Ones, _Hops, Status, Counters, Counters) :-
401 | \+ member(Status, [unknown,going,going(_),halts,meander,blank,loops,loops(cycle),loops(cycle(_)),loops(road_runner),loops(induction),pseudo,pseudo(_),abort,abort(_)]),
402 | format("% Unknown status: ", []), write(Status), nl, !.
403 |
404 | handle_aborts(States, Symbols, Dirs, _Type, _Mode, _Args, Counters, Counters) :-
405 | format("Looking 1~n", []),
406 | directory(output, States, Symbols, Style, Dirs, tnf, Base),
407 | filename(Base, input, States, Symbols, Dirs, Style, tnf, abort, 1, _InName, AbortInFile),
408 | filename(Base, output, States, Symbols, Dirs, Style, tnf, abort, 1, _OutName, AbortOutFile),
409 |
410 | \+ exists_file(AbortInFile),
411 | \+ exists_file(AbortOutFile),
412 | format("No abort files~n", []),
413 | !. % No abort files, so nothing to do.
414 |
415 | handle_aborts(States, Symbols, Dirs, _Type, _Mode, Args, Counters, Final_Counters) :-
416 | format("Looking 2~n", []),
417 | directory(output, States, Symbols, Style, Dirs, tnf, Base),
418 | filename(Base, input, States, Symbols, Dirs, Style, tnf, abort, 1, _InName, AbortInFile),
419 | filename(Base, output, States, Symbols, Dirs, Style, tnf, abort, 1, OutName, AbortOutFile),
420 | exists_file(AbortInFile),
421 | \+ exists_file(AbortOutFile), !, % Can this happen??
422 |
423 | format("Abort input, but no output~n", []),
424 | append_to_plfile(OutName, "-going", GoingName),
425 |
426 | open(AbortInFile, read, Input),
427 | tell(OutName),
428 | atom_codes(GoingFile, GoingName),
429 | open(GoingFile, write, Go),
430 | process_one_file1(States, Symbols, Dirs, Input, analyse, Args, Go, Counters, Final_Counters), !,
431 | close(Input), close(Go), told,
432 | true.
433 |
434 | handle_aborts(States, Symbols, Dirs, Type, Mode, Args, Counters, Final_Counters) :-
435 | format("Looking 3~n", []),
436 | directory(output, States, Symbols, Style, Dirs, tnf, Base),
437 | filename(Base, input, States, Symbols, Dirs, Style, tnf, abort, 1, _InName, AbortInFile),
438 | filename(Base, output, States, Symbols, Dirs, Style, tnf, abort, 1, _OutName, AbortOutFile),
439 | exists_file(AbortInFile),
440 | exists_file(AbortOutFile), !,
441 | format("Abort input and output found~n", []),
442 | handle_aborts1(States, Symbols, Dirs, Type, Mode, Args, AbortInFile, AbortOutFile, Counters, Final_Counters).
443 |
444 | handle_aborts1(States, Symbols, Dirs, _Type, Mode, _Args, _AbortInFile, AbortOutFile,Counters, Final_Counters) :-
445 | member(Mode, [analyse,status]),
446 | open(AbortOutFile, read, Input),
447 | process_one_file1(States, Symbols, Dirs, Input, stats, [], _GoFile, Counters, Final_Counters),
448 | close(Input),
449 | true.
450 | handle_aborts1(States, Symbols, Dirs, _Type, Mode, Args, _AbortInFile, AbortOutFile, Counters, Final_Counters) :-
451 | Mode == refine,
452 |
453 | atom_codes(AbortOutFile, OutName),
454 | append_to_plfile(OutName, "-going", GoingName),
455 | append_to_plfile(OutName, "-out", Out),
456 |
457 | open(AbortOutFile, read, Input),
458 | tell(Out),
459 | atom_codes(GoingFile, GoingName),
460 | open(GoingFile, write, Go),
461 |
462 | process_one_file1(States, Symbols, Dirs, Input, analyse, Args, Go, Counters, Final_Counters), !,
463 | output_counters(Final_Counters),
464 |
465 | close(Input), close(Go), told.
466 |
467 | handle_aborts1(States, Symbols, Dirs, _Type, Mode, Args, AbortInFile, _AbortOutFile,Counters, Final_Counters) :-
468 | Mode == pseudouni,
469 |
470 | atom_codes(AbortInFile, InName),
471 | append_to_plfile(InName, "-pseudo", OutName),
472 | open(AbortInFile, read, Input),
473 | atom_codes(Out, OutName),
474 | tell(Out),
475 |
476 | process_one_file1(States, Symbols, Dirs, Input, pseudouni, Args, _Go, Counters, Final_Counters), !,
477 | output_counters(Final_Counters),
478 |
479 | close(Input), told.
480 |
481 | handle_aborts1(States, Symbols, Dirs, _Type, Mode, Args, AbortInFile, _AbortOutFile, Counters, Final_Counters) :-
482 | Mode == stats,
483 | open(AbortInFile, read, Input),
484 | process_one_file1(States, Symbols, Dirs, Input, stats, Args, _Go, Counters, Final_Counters), !,
485 | output_counters(Final_Counters),
486 | close(Input).
487 |
488 | % filename(Base1, generate, States, Symbols, Dirs, Type, Mode, 1, Name, File),
489 | filename(Base, Dir, States, Symbols, Dirs, Style, Type, Mode, Start, RealName, File) :-
490 |
491 | % Dependence on Style is this: if Style = abs, no change. Otherwise put "rel" in the right spot ...
492 |
493 | number_string(States,S1), number_string(Symbols,S2), number_string(Dirs,S3), number_string(Start,S4),
494 | % format("Dir is ~k, Type is ~k~n", [Dir,Type]),
495 | typecode(Dir, Type, T1), modecode(Dir, Mode, T2), extracode(Dir, Mode, Extra), precode(Dir, Mode, Pre), stylecode(Dirs, Style, StyleCode),
496 | % format("Appending 0 ... T1 is ~s~n", [T1]),
497 | % format("T2 is ~s~n", [T2]), ttyflush,
498 | % format("S1 is ~s~n", [S1]), ttyflush,
499 | % format("S2 is ~s~n", [S2]), ttyflush,
500 | % format("S3 is ~s~n", [S3]), ttyflush,
501 | string_concat(S1,S2,Temp01), string_concat(Temp01, S3, Temp11), string_concat(Temp11, StyleCode, Temp1),
502 | % format("Appended~n", []), format("~s ", [T1]), format("~s ~n", [T2]),
503 | string_concat(T1, T2, Temp2),
504 | % format("Appended 2~n", []),
505 | % format("Temp1 is ~s~n", [Temp1]), ttyflush,
506 | % format("Temp2 is ~s~n", [Temp2]), ttyflush,
507 | % format("Appending 1 ... ~n", []), ttyflush,
508 | string_concat(Pre, "busybeaver", Prefix),
509 | % format("Appending 2 ...Prefix is ~s~n", [Prefix]), ttyflush,
510 | % format("Temp1 is ~s~n", [Temp1]),
511 | % format("Temp2 is ~s~n", [Temp2]),
512 | string_concat(Prefix, Temp1, Temp12), string_concat(Temp12, Temp2, Temp3),
513 | % format("Appending 3 ... Base is ~s~n", [Base]), ttyflush,
514 | % format("Temp3 is ~s~n", [Temp3]),
515 | string_concat(Base, Temp3, Name),
516 | % format("Appending 4 ... Name is ~s~n", [Name]), ttyflush,
517 | partcode(Mode, S4, Temp45),
518 | string_concat(Name, Temp45, Temp4),
519 | % format("Appending 5 ... Temp4 is ~s~n", [Temp4]), ttyflush,
520 | % format("Extra is ~s~n", [Extra]),
521 | string_concat(Temp4, Extra, Temp9), string_concat(Temp9, ".pl", RealName),
522 | % format("Appending 6 ... RealName is ~s~n", [RealName]),
523 | atom_codes(File, RealName).
524 |
525 | checkmax(List, M, Ones, Hops, NewList) :-
526 | \+ member(max(Ones, _, _), List), !,
527 | append([max(Ones, M, Hops)], List, NewList), !.
528 | checkmax(List, _M, Ones, Hops, List) :-
529 | member(max(Ones, _M1, H1), List),
530 | H1 >= Hops, !.
531 | checkmax(List, M, Ones, Hops, NewList) :-
532 | member(max(Ones, M1, H1), List),
533 | H1 < Hops,!,
534 | delete(List, max(Ones, M1, H1), NL),
535 | append([max(Ones, M, Hops)], NL, NewList), !.
536 |
537 | checkmin(List, M, Ones, Hops, NewList) :-
538 | \+ member(min(Ones, _, _), List),!,
539 | append([min(Ones, M, Hops)], List, NewList),!.
540 | checkmin(List, _M, Ones, Hops, List) :-
541 | member(min(Ones, _M1, H1), List),
542 | H1 =< Hops, !.
543 | checkmin(List, M, Ones, Hops, NewList) :-
544 | member(min(Ones, M1, H1), List),
545 | H1 > Hops,!,
546 | delete(List, min(Ones, M1, H1), NL),
547 | append([min(Ones, M, Hops)], NL, NewList), !.
548 |
549 | basename(Name, BaseName) :- append(BaseName, Suffix, Name), append("-", _, Suffix).
550 |
551 | % Utilities
552 |
553 | append(W,X,Y,Z) :- append(W,X,T), append(T,Y,Z).
554 |
555 | bbinternalprint(Pred, N, M, O, H, Status) :-
556 | format("~k(~d,[", [Pred,N]),!,
557 | printint(M), !,
558 | format("],~d,~d,", [O,H]),!,
559 | write(Status), !,
560 | format(").~n", []), !.
561 |
562 | sort_records([], []).
563 | sort_records(List, List) :- length(List, 1).
564 | sort_records(List, SortedList) :-
565 | length(List, N), N >= 2,
566 | divide(List, First, Second),
567 | sort_records(First, Fs),
568 | sort_records(Second, Ss),
569 | merge_records(Fs, Ss, SortedList).
570 |
571 | merge_records([], Ys, Ys).
572 | merge_records(Ys, [], Ys).
573 |
574 | merge_records([S1|Fs], [S2|Ss], [S1|Ys]) :-
575 | less_equal(S1, S2), merge_records(Fs, [S2|Ss], Ys).
576 |
577 | merge_records([S1|Fs], [S2|Ss], [S2|Ys]) :-
578 | \+ less_equal(S1, S2), merge_records([S1|Fs], Ss, Ys).
579 |
580 | divide(List, First, Second) :-
581 | length(List, N), Half is N // 2,
582 | length(First, Half),
583 | append(First, Second, List).
584 |
585 | less_equal(max(O1,_,_), min(O2,_,_)) :- O1 < O2.
586 | less_equal(min(O1,_,_), max(O2,_,_)) :- O1 < O2.
587 | less_equal(min(O1,_,_), min(O2,_,_)) :- O1 < O2.
588 | less_equal(max(O1,_,_), max(O2,_,_)) :- O1 < O2.
589 | less_equal(min(O1,_,_), max(O2,_,_)) :- O1 == O2.
590 |
591 | output_records([]) :- !.
592 | output_records([max(O, M, H)|Rest]) :-
593 | !, format("% ", []), bbinternalprint(maximum, 5, M, O, H, halts),
594 | output_records(Rest).
595 | output_records([min(O, M, H)|Rest]) :-
596 | !, format("% ", []), bbinternalprint(minimum, 5, M, O, H, halts),
597 | output_records(Rest).
598 |
599 | printint([]) :- !.
600 | printint([A]) :- format("~k", [A]), !.
601 | printint(Arg) :- Arg = [A1|Temp], Temp = [A2|Rest], !, format("~k,", [A1]), !, printint([A2|Rest]).
602 |
603 | % bbsortout(Pred, N, M) :-
604 | % format("~k(~d, [", [Pred,N]),
605 | % sortmachine(N, a, 0, [], M, M1), !,
606 | % printint(M1),
607 | % format("]).~n", []).
608 |
609 | sortmachine(_N, _States, _Symbols, _State, _Input, Done, [], M) :- reverse(Done, M),!.
610 | sortmachine(N, States, Symbols, State, Input, Done, Todo, Result) :-
611 | length(Todo, T), T > 0,
612 | member(t(State, Input, Output, Dir, NewState), Todo), !,
613 | % format("% Found~n", []),
614 | delete(Todo, t(State, Input, Output, Dir, NewState), Rest),
615 | % format("% Incrementing ~k ~k~n", [State,Input]),
616 | (Rest \== [] -> increment(States, Symbols, State, Input, NS, NI); (NS = State, NI = Input) ), !,
617 | % format("% Incremented~n", []),
618 | sortmachine(N, States, Symbols, NS, NI, [t(State, Input, Output, Dir, NewState)|Done], Rest, Result).
619 |
620 | sortmachine(N, States, Symbols, State, Input, Done, Todo, Result) :-
621 | length(Todo, T), T > 0,
622 | \+ member(t(State, Input, _Output, _Dir, _NewState), Todo), !,
623 | % format("% Not found~n", []),
624 | (Todo \== [] -> increment(States, Symbols, State, Input, NS, NI); (NS = State, NI = Input) ), !,
625 | % format("% Incremented~n", []),
626 | sortmachine(N, States, Symbols, NS, NI, Done, Todo, Result).
627 |
628 | padmachine(States, Symbols, _Dirs, M, PadM) :-
629 | length(M, L), L is States * Symbols, !, PadM = M.
630 | padmachine(States, Symbols, Dirs, M, PadM) :-
631 | length(M, L), L < States * Symbols, !,
632 | states_list(States, StatesList),
633 | symbols_list1(Symbols, SymbolsList),
634 | once( missing(StatesList, SymbolsList, M, S1, Sym1) ), halt_state(Halt),
635 | append(M, [t(S1, Sym1, Sym1, r, Halt)], NewM),
636 | padmachine(States, Symbols, Dirs, NewM, PadM),!.
637 |
638 | increment(_States, Symbols, State, Symbol, State, NSym) :-
639 | % If we can increment the symbol, do it ....
640 | NSym is Symbol+1,
641 | symbols_list1(Symbols, List), member(NSym, List), !.
642 |
643 | increment(States, _Symbols, State, _Symbol, NState, 0) :-
644 | % Otherwise symbol is 0 and take the next state (if it exists)
645 | states_list(States, List),
646 | next_state(State, NState), !,
647 | member(NState, List).
648 |
649 | convert_machine(marxen, States, Symbols, Dirs, machine(List, _, _), NewM) :- convert_machine(States, Symbols, Dirs, List, NewM).
650 | convert_machine(marxen, States, Symbols, Dirs, M, NewM) :- M \== machine(_,_,_), convert_machine0(States, Symbols, Dirs, M, NewM).
651 | convert_machine(Format, _States, _Symbols, _Dirs, _M, NewM) :- \+ member(Format, [marxen]), NewM = "".
652 |
653 | convert_machine0(States, Symbols, Dirs, M, NewM) :-
654 | % format("% Padding~n", []),
655 | padmachine(States, Symbols, Dirs, M, PadM),
656 | % sortmachine(Symbols, a,0,[], PadM, SortM),
657 | % format("% Sorting ", []), writeln(PadM),
658 | sortmachine(0, States, Symbols, a, 0, [], PadM, SortM),
659 | % format("% Converting~n", []),
660 | convert_machine1(SortM, [], NewM). % NewM is a string representing the Marxen representation of the machine.
661 |
662 | convert_machine1([], SoFarNewM, SoFarNewM).
663 | convert_machine1([t(_S,_I,O,D,NS)|Rest], SoFarNewM, NewM) :-
664 | atom_codes(O, NewO),
665 | atom_codes(D, NewD),
666 | atom_codes(NS, NewNS),
667 | append(NewO,NewD,Temp), append(Temp, NewNS, NewTrans),
668 | append(SoFarNewM, NewTrans, NewSoFarNewM),
669 | convert_machine1(Rest, NewSoFarNewM, NewM).
670 |
671 | duplicates(InFile) :-
672 | atom_codes(InFile, I),
673 | append(Name, ".pl", I),
674 | append(Name, "-duplicates.pl", OutName),
675 | % string2term(OutName, OutFile),!,
676 | atom_codes(OutFile, OutName),!,
677 | open(InFile, read, Input),
678 | tell(OutFile),
679 | read(Input, Term1),
680 | copies(Term1, Input),
681 | close(Input),
682 | told.
683 |
684 | copies(end_of_file, _).
685 | copies(Current, Input) :-
686 | Current \== end_of_file,
687 | read(Input, Term2),
688 | process_copy(Current, Term2),!,
689 | copies(Term2, Input).
690 |
691 | process_copy(_, end_of_file).
692 | process_copy(Term1, Term2) :-
693 | Term1 = bb(N1, M1, O1, H1, S1),
694 | Term2 = bb(N2, M2, O2, H2, S2),
695 | M1 = M2, !,
696 | format("% Duplicates:~n", []),
697 | bbinternalprint(bb, N1, M1, O1, H1, S1),
698 | bbinternalprint(bb, N2, M2, O2, H2, S2),
699 | format("%%%%%~n", []),
700 | true.
701 | process_copy(Term1, Term2) :-
702 | Term1 = bb(_N1, M1, _O1, _H1, _S1),
703 | Term2 = bb(_N2, M2, _O2, _H2, _S2),
704 | M1 \= M2, !,
705 | %format("% Non-duplicates:~n", []),
706 | %bbinternalprint(bb, N1, M1, O1, H1, S1),
707 | %bbinternalprint(bb, N2, M2, O2, H2, S2),
708 | %format("%%%%%~n", []),
709 | true.
710 | process_copy(Term1, Term2) :-
711 | (Term1 \= bb(_N1, _M1, _O1, _H1, _S1); Term2 \= bb(_N2, _M2, _O2, _H2, _S2)).
712 |
713 | % [abort,abort(_),unknown,going,going(_),halts,meander,blank,loops,loops(cycle),loops(cycle(_)),loops(road_runner),loops(induction),pseudo,pseudo(_)]),
714 |
715 | check_going(Going, N, Machine, Ones, Hops, going) :- !, write(Going, bb(N, Machine, Ones, Hops, going)), put_char(Going, '.'), nl(Going), !.
716 | check_going(Going, N, Machine, Ones, Hops, going(S)) :- !, write(Going, bb(N, Machine, Ones, Hops, going(S))), put_char(Going, '.'), nl(Going), !.
717 | check_going(Going, N, Machine, Ones, Hops, unknown) :- !, write(Going, bb(N, Machine, Ones, Hops, unknown)), put_char(Going, '.'), nl(Going), !.
718 | check_going(_Going, _N,_Machine, _Ones, _Hops, Status) :- member(Status, [abort,abort(_),halts,meander,blank,loops,loops(_),pseudo,pseudo(_)]), !.
719 |
720 | typecode(_, free, "free").
721 | typecode(_, all, "all").
722 | typecode(_, tnf, "tnf").
723 | % typecode(_, newtnf, "newtnf").
724 |
725 | modecode(output, raw, "raw").
726 | modecode(output, analyse, "").
727 | modecode(output, refine, "").
728 | modecode(output, pseudouni, "").
729 | modecode(output, stats, "").
730 | modecode(output, status, "").
731 | modecode(output, abort, "").
732 | modecode(output, convert(F,N), Name) :- atom_codes(F, FName), atom_codes(N, NName), string_concat(FName, NName, Temp), string_concat(Temp, "raw", Name).
733 | modecode(input, raw, "raw").
734 | modecode(input, analyse, "raw").
735 | modecode(input, refine, "").
736 | modecode(input, status, "").
737 | modecode(input, pseudouni, "raw").
738 | modecode(input, stats, "raw").
739 | modecode(input, number, "raw").
740 | modecode(input, abort, "raw").
741 | modecode(input, convert(_,_), "raw").
742 | modecode(generate, _, "raw").
743 |
744 | stylecode(2, abs, "").
745 | stylecode(2, rel, "rel").
746 | stylecode(Dirs, abs, "abs") :- Dirs > 2.
747 | stylecode(Dirs, rel, "rel") :- Dirs > 2.
748 |
749 | extracode(input, M, "") :- \+ member(M, [refine, status]).
750 | extracode(input, refine, "-going").
751 | extracode(input, status, "-out").
752 | extracode(output, M, "") :- \+ member(M, [abort, refine, status]).
753 | extracode(output, refine, "-going-out").
754 | extracode(output, status, "-out").
755 | extracode(output, abort, "-out"). % ~~~??
756 | extracode(generate, _, "").
757 |
758 | mode_status(status, output).
759 | mode_status(Mode, input) :- Mode \= status.
760 |
761 | precode(_, input, "").
762 | precode(_, output, "").
763 | precode(_, number, "").
764 | precode(_, analyse, "").
765 | precode(_, abort, "").
766 | precode(_, refine, "").
767 | precode(_, stats, "").
768 | precode(_, status, "").
769 | precode(_, convert(_,_), "").
770 | precode(_, pseudoni, "").
771 | precode(_, raw, "temp-").
772 |
773 | partcode(Mode, S4, Code) :- Mode \== abort, string_concat("-part", S4, Code).
774 | partcode(abort, _, "abort").
775 |
776 | summary_name(analyse, "analyse").
777 | summary_name(abort, "abort").
778 | summary_name(refine, "refine").
779 | summary_name(raw, "").
780 | summary_name(number, "").
781 | summary_name(pseudouni, "pseudouni").
782 | summary_name(stats, "stats").
783 | summary_name(status, "status").
784 | summary_name(convert(_,_), "convert").
785 |
786 | % Parameters. These need to be rationalised!
787 |
788 | compress_length(10). % Was 5, but then found long(4,1,M) and then example(3,M).
789 |
790 | beaver(input, "/Users/power/fun/twitchcoq/bb/harland/raw/"). % Directory for input
791 | beaver(output, "/Users/power/fun/twitchcoq/bb/harland/results/"). % Directory where results get written.
792 |
793 | which_dir(Mode,States,Symbols,Dirs,Style,Type,Directory) :- member(Mode,[refine,status]), directory(output,States,Symbols,Dirs,Style,Type,Directory).
794 | which_dir(Mode,States,Symbols,Dirs,Style,Type,Directory) :- \+ member(Mode, [refine, status]), directory(input,States,Symbols,Dirs,Style,Type,Directory).
795 |
796 | directory(Mode, States, Symbols, Dirs, _Style, Type, Directory) :-
797 | Dimension is States * Symbols * Dirs,
798 | ((Dimension < 16); (Dimension == 16, Type \== all)),
799 | beaver(Mode, Base), Directory = Base.
800 | directory(Mode, States, Symbols, Dirs, Style, Type, Directory) :-
801 | Dimension is States * Symbols * Dirs,
802 | ((Dimension > 16);(Dimension == 16, Type == all)), % Use subdirectory for larger cases. 16 is file unless Type is all
803 | beaver(Mode, Base),
804 | number_string(States,S1), number_string(Symbols,S2), number_string(Dirs,S3),
805 | % append(S1,S2,S3,Temp1),
806 | % append("busybeaver", Temp1, "/", Temp3),
807 | % append(Base, Temp3, Directory).
808 | (Style = rel -> string_concat(S3,"rel", S4); S4 = S3),
809 | string_concat(S1,S2,Temp0), string_concat(Temp0, S4, Temp1),
810 | string_concat("busybeaver", Temp1, Temp2),
811 | string_concat(Temp2, "/", Temp3),
812 | string_concat(Base, Temp3, Directory).
813 |
814 | ensure_exists(Directory) :- atom_codes(Real, Directory), exists_directory(Real).
815 | ensure_exists(Directory) :- atom_codes(Real, Directory), \+ exists_directory(Real), make_directory(Real).
816 |
817 | compare(File1, File2) :-
818 | open(File1, read, Input1),
819 | open(File2, read, Input2),
820 |
821 | read(Input1, Term1),
822 | read(Input2, Term2),
823 |
824 | process_compare(Term1, Term2, 1, Input1, Input2),
825 |
826 | close(Input1),
827 | close(Input2),
828 | true.
829 |
830 | process_compare(end_of_file, end_of_file, N, _Input1, _Input2) :- format("Both done after ~d lines~n", [N]).
831 | process_compare(end_of_file, Term2, N,_Input1, _Input2) :-
832 | Term2 \== end_of_file,
833 | format("File 1 ended first at line ~d~n", [N]),
834 | true.
835 |
836 | process_compare(Term1, end_of_file, N,_Input1, _Input2) :-
837 | Term1 \== end_of_file,
838 | format("File 2 ended first at line ~d~n", [N]),
839 | true.
840 |
841 | process_compare(Term1, Term2, N, _Input1, _Input2) :-
842 | Term1 \== end_of_file, Term2 \== end_of_file,
843 | \+ (Term1 = bb(N, M, _Ones1, _Hops1, _Status1), Term2 = bb(N, M, _Ones2, _Hops2, _Status2)),!,
844 | format("Mismatch at line~d: ~n", [N]), write(Term1), nl, write(Term2), nl,
845 | true.
846 |
847 | process_compare(Term1, Term2, N, Input1, Input2) :-
848 | Term1 \== end_of_file, Term2 \== end_of_file,
849 | Term1 = bb(N, M, Ones1, Hops1, Status1), Term2 = bb(N, M, Ones2, Hops2, Status2), !,
850 | % ( (0 is N mod 10000) -> (format("Line ~d: ", [N]), write(Term1), format(" and~nLine ~d: ", [N]), write(Term2), nl) ; true),
851 | % ( (N > 999990) -> (format("Line ~d: ", [N]), write(Term1), format(" and~nLine ~d: ", [N]), write(Term2), nl) ; true),
852 | \+ (Ones1 = Ones2, Hops1 = Hops2, Status1 = Status2),
853 | format("Different results at line ~d: ~d ~d ~k versus ~d ~d ~k~n", [Ones1,Hops1,Status1,Ones2,Hops2,Status2]),
854 | read(Input1, NewTerm1), read(Input2, NewTerm2), N1 is N+1,
855 | process_compare(NewTerm1, NewTerm2, N1, Input1, Input2),
856 | true.
857 |
858 | process_compare(Term1, Term2, N, Input1, Input2) :-
859 | Term1 \== end_of_file, Term2 \== end_of_file,
860 | \+ (
861 | Term1 = bb(N, M, Ones1, Hops1, Status1), Term2 = bb(N, M, Ones2, Hops2, Status2), \+ (Ones1 = Ones2, Hops1 = Hops2, Status1 = Status2)
862 | ),
863 | read(Input1, NewTerm1), read(Input2, NewTerm2), N1 is N+1,
864 | process_compare(NewTerm1, NewTerm2, N1, Input1, Input2),
865 | true.
866 |
867 | special_check(File) :-
868 | open(File, read, Input),
869 | initialise_counters(Counters),
870 | read(Input, Term),
871 | stats_check(Input, Term, Counters, FinalCounters), % Or others ....
872 | output_counters(FinalCounters),
873 | close(Input).
874 |
875 | check_terms1(N, _, end_of_file) :- format("Number of terms found: ~d~n", [N-1]).
876 | check_terms1(N, Input, Term) :-
877 | Term \== end_of_file,
878 | Term = bb(_, _M, _Ones, _Hops, _Status),!,
879 | N1 is N+1,
880 | read(Input, NewTerm),
881 | check_terms1(N1, Input, NewTerm).
882 | check_terms1(N, Input, Term) :-
883 | Term \== end_of_file,
884 | Term \= bb(_, _M, _Ones, _Hops, _Status),!,
885 | format("Non-term found at ~d: ", [N]), write(Term), nl,
886 | read(Input, NewTerm),
887 | check_terms1(N, Input, NewTerm).
888 |
889 | meander_check1(_, end_of_file) :- !.
890 | meander_check1(Input, Term) :-
891 | Term \== end_of_file,
892 | Term = bb(_, _M, _Ones, _Hops, Status), \+ member(Status, [meander]), !,
893 | read(Input, NewTerm),
894 | meander_check1(Input, NewTerm).
895 | meander_check1(Input, Term) :-
896 | Term \== end_of_file,
897 | Term = bb(N, M, _Ones, _Hops, Status), member(Status, [meander]), !,
898 | emulate_bb(M, 10000, flex, [loop,escape,blank,otter], _NewOnes, _NewHops, NewStatus, _NewOutputs),
899 | format("Machine ~d: ",[N]), write(M), format(" meander and ", []), write(NewStatus), nl,
900 |
901 | read(Input, NewTerm),
902 | meander_check1(Input, NewTerm).
903 |
904 | meander_check2(_, end_of_file) :- !.
905 | meander_check2(Input, Term) :-
906 | Term \== end_of_file,
907 | Term = bb(N, M, _Ones, _Hops, Status), !,
908 |
909 | ( (meandering(M), member(Status, [halts])) -> (format("Machine ~d: ",[N]), write(M), format(" meander and ", []), write(Status), nl); true),
910 |
911 | read(Input, NewTerm),
912 | meander_check2(Input, NewTerm).
913 |
914 | induction_check(Number, Max, Total, _Input, end_of_file) :- format("Number is ~d, Max is ~d, Average is ~1f~n", [Number, Max, Total/Number]), true.
915 | induction_check(Number, Max, Total, Input, Term) :-
916 | Term \== end_of_file,
917 | Term = bb(_, _M, _Ones, _Hops, Status),
918 | \+ member(Status, [loops(induction(_,_,_))]),
919 | read(Input, NewTerm),
920 | induction_check(Number, Max, Total, Input, NewTerm).
921 | induction_check(Number, Max, Total, Input, Term) :-
922 | Term \== end_of_file,
923 | Term = bb(_, _M, _Ones, Hops, Status),
924 | member(Status, [loops(induction(_Config,_Diffs,_Hopses))]),
925 |
926 | Number1 is Number + 1,
927 | NewMax is max(Hops, Max),
928 | NewTotal is Total + Hops,
929 | read(Input, NewTerm),
930 | induction_check(Number1, NewMax, NewTotal, Input, NewTerm).
931 |
932 |
933 | stats_check(_Input, end_of_file, Counters, Counters).
934 | stats_check(Input, Term, Counters, FinalCounters) :-
935 | Term \== end_of_file,
936 | Term = bb(_, M, Ones, Hops, Status),
937 | update_counters(M, Ones, Hops, Status, Counters, NewCounters),
938 | read(Input, NewTerm),
939 | stats_check(Input, NewTerm, NewCounters, FinalCounters).
940 |
941 | final(File) :-
942 | open(File, read, Input),
943 | read(Input, Term),tell('Output2.pl'),
944 | final_few(Input, Term),
945 | close(Input).
946 |
947 | final_few(_Input, end_of_file).
948 | final_few(Input, Term) :-
949 | Term \== end_of_file,
950 | Term = bb(Number, M, _, _, Status),
951 | format("~d: ~k: ", [Number, Status]), write(M), nl,
952 | emulate_bb(M, 1000, flex, [otter,otrace,trace(980),final], _Ones, _Hops, _NewStatus, _Outputs),
953 | format("Done ~n", []),
954 | read(Input, NewTerm),
955 | final_few(Input, NewTerm).
956 |
957 |
--------------------------------------------------------------------------------
/bb/harland/top.pl:
--------------------------------------------------------------------------------
1 | create(States, Symbols, Dirs, Type) :- create(States, Symbols, Dirs, abs, Type). % For backwards compatibility ...
2 | create(States, Symbols, Dirs, Style, Type) :-
3 | format("% Creating ~d ~d ~d ~k ~k case ... ", [States, Symbols, Dirs, Style, Type]),
4 | get_time(T1),
5 | create_machines(States, Symbols, Dirs, Style, Type), !,
6 | get_time(T2), Time is T2-T1,
7 | format("took ~2f seconds~n", [Time]), flush_output, !.
8 |
9 | create_bilby :-
10 | create(2,2,2,tnf), !,
11 | create(3,2,2,tnf), !,
12 | create(2,3,2,tnf), !,
13 | true.
14 | create_elephant :-
15 | create(4,2,2,tnf), !,
16 | create(2,4,2,tnf), !,
17 | true.
18 | create_whale :-
19 | create(3,3,2,tnf), !, flush_output,
20 | create(5,2,2,tnf), !, flush_output,
21 | create(2,5,2,tnf), !, flush_output,
22 | true.
23 | create_duck :-
24 | create(6,2,2,tnf), !, flush_output,
25 | create(4,3,2,tnf), !, flush_output,
26 | create(3,4,2,tnf), !, flush_output,
27 | create(2,6,2,tnf), !, flush_output,
28 | true.
29 |
30 | create_bilby_extra :-
31 | create(2,2,2,free), !,
32 | create(3,2,2,free), !,
33 | create(2,3,2,free), !,
34 | create(2,2,2,all), !,
35 | create(3,2,2,all), !,
36 | create(2,3,2,all), !,
37 | true.
38 | create_elephant_extra :- create(4,2,2,free), create(2,4,2,free).
39 |
40 | create622 :- tell('622.txt'), create(6,2,2,tnf), told.
41 | create432 :- tell('432.txt'), create(4,3,2,tnf), told.
42 | create342 :- tell('342.txt'), create(3,4,2,tnf), told.
43 | create262 :- tell('262.txt'), create(2,6,2,tnf), told.
44 |
45 | papertable :- tell('papertable.txt'), create_bilby, create_bilby_extra, create_elephant, create_elephant_extra, told.
46 | whaletable :- tell('whaletable.txt'), create_whale, told.
47 | bag :- tell('creation.txt'), create_bilby, create_elephant, create_whale, told.
48 | extra :- tell('extra.txt'), create_bilby_extra, create_elephant_extra, told.
49 |
50 | batch :-
51 | create_machines(5,2,2,abs,tnf),
52 | create_machines(2,5,2,abs,tnf),
53 | process(2,4,2,tnf,analyse,[]),
54 | process(3,3,2,tnf,analyse,[]),
55 | process(5,2,2,tnf,analyse,[]),
56 | process(2,5,2,tnf,analyse,[]),
57 | true.
58 |
59 | bilby :-
60 | process(2,2,2,tnf,analyse,[]),
61 | process(3,2,2,tnf,analyse,[]),
62 | process(2,3,2,tnf,analyse,[]),
63 | true.
64 |
65 | bilby_all :-
66 | process(2,2,2,tnf,analyse,[]),
67 | process(2,2,2,free,analyse,[]),
68 | process(2,2,2,all,analyse,[]),
69 | process(3,2,2,tnf,analyse,[]),
70 | process(3,2,2,free,analyse,[]),
71 | process(3,2,2,all,analyse,[]),
72 | process(2,3,2,tnf,analyse,[]),
73 | process(2,3,2,free,analyse,[]),
74 | process(2,3,2,all,analyse,[]),
75 | true.
76 |
77 | elephant :-
78 | process(4,2,2,tnf,analyse,[]),
79 | process(2,4,2,tnf,analyse,[]),
80 | true.
81 |
82 | elephant_free :-
83 | process(4,2,2,free,analyse,[]),
84 | process(2,4,2,free,analyse,[]),
85 | true.
86 |
87 | whale :-
88 | process(3,3,2,tnf,analyse,[nomonster]),
89 | process(5,2,2,tnf,analyse,[nomonster]),
90 | process(2,5,2,tnf,analyse,[nomonster]),
91 | true.
92 |
93 | convert_bilby :-
94 | process(2,2,2,tnf,convert(marxen,numbered), []),
95 | process(3,2,2,tnf,convert(marxen,numbered), []),
96 | process(2,3,2,tnf,convert(marxen,numbered), []),
97 | true.
98 | convert_elephant :-
99 | process(4,2,2,tnf,convert(marxen,numbered), []),
100 | process(2,4,2,tnf,convert(marxen,numbered), []),
101 | true.
102 | convert_whale :-
103 | process(3,3,2,tnf,convert(marxen,numbered), []),
104 | process(5,2,2,tnf,convert(marxen,numbered), []),
105 | process(2,5,2,tnf,convert(marxen,numbered), []),
106 | true.
107 |
108 |
109 |
110 | % tell('SixTwentyTwo'), time(test6(22,6,[otter], Ones, Hops, Status, Outputs)), told.
111 | % tell('SixTwentyOne'), time(test6(21,6,[otter], Ones, Hops, Status, Outputs)), told.
112 | % tell('SixTwenty'), time(test6(20,4,[otter], Ones, Hops, Status, Outputs)), told.
113 | % tell('SixNineteen'), time(test6(19,6,[otter], Ones, Hops, Status, Outputs)), told.
114 |
115 | label(N,M,L) :- format("Monster ~d (~d x ~d): ", [N,M,L]).
116 |
117 | test(Num, Bound, Macro) :-
118 | time(( monster(Num,M), emulate_bb(M,Bound,macro(Macro), [otter], _, _, _, _) )).
119 |
120 | test1(Num, Bound, Macro) :-
121 | get_time(T1),
122 | monster(Num,M), emulate_bb(M,Bound,macro(Macro), [otter,final], _, _, _, _),
123 | % format("Emulation Done ... ", []), flush_output,
124 | get_time(T2), Time is T2-T1,
125 | format("Took ~f seconds~n", [Time]).
126 |
127 | test2(Num, Bound, Macro, Options) :-
128 | get_time(T1),
129 | monster(Num,M), emulate_bb(M,Bound,macro(Macro), Options, _, _, _, _),
130 | get_time(T2), Time is T2-T1,
131 | format("Took ~f seconds~n", [Time]).
132 |
133 | test3(Num, Bound) :-
134 | get_time(T1),
135 | monster(Num,M), emulate_bb(M,Bound,flex, [otter,final,optcom], _, _, _, _),
136 | get_time(T2), Time is T2-T1,
137 | format("Took ~f seconds~n", [Time]).
138 |
139 | test4(Num, Bound, Options) :-
140 | get_time(T1),
141 | monster(Num,M), emulate_bb(M,Bound,flex, Options, _, _, _, _),
142 | get_time(T2), Time is T2-T1,
143 | format("Took ~f seconds~n", [Time]).
144 |
145 | test5(Num, _Bound) :-
146 | get_time(T1),
147 | monster(Num,M), analyse(M, 0, 0, going, [], Ones, Hops, Status, _Outputs),
148 | get_time(T2), Time is T2-T1,
149 | format("Status: ", []), write(Status), format(" Ones: ~d Hops: ~d~n", [Ones, Hops]),
150 | format("Time: ~f seconds~n", [Time]).
151 |
152 |
153 |
154 |
155 |
156 | % monster(30,M), emulate_general(M, config([grp([3,3],v(1,0)), grp([0,1],1)], b, grp([3,3],v(1,0)),l, []), 100, macro(2), [target([config([grp([3,3],v(1,5)), grp([0,1],1)],b,grp([3,3],v(1,-4)), l, [])])], [trace], Hops, Status, Outputs)
157 |
--------------------------------------------------------------------------------
/bb/run.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # 6 possible states
4 | # 2 values
5 | # 2 moves
6 | # 6*2*2 = 24
7 | # 24^10 possible for sigma(5, 2)
8 |
9 | # See Tree Normal Form from Bra66
10 |
11 | #t0 = "B1L A1L C1R B1R A1L D1R A1L E1R H1L C0R".split(" ")
12 | t0 = "B1L C1R C1L B1L D1L E0R A1R D1R H1L A0R".split(" ")
13 |
14 | def run(t0, ms=-1):
15 | t = [0]*30000
16 | pos = 15000
17 | s = "A"
18 |
19 | cnt = 0
20 | halt = True
21 | while 1:
22 | assert pos > 0
23 | assert pos < len(t)
24 | #if cnt%1000 == 0:
25 | # print(cnt, s, pos)
26 | ns = ord(s) - ord("A")
27 | if t[pos] == 0:
28 | tt = t0[ns*2+0]
29 | elif t[pos] == 1:
30 | tt = t0[ns*2+1]
31 | s = tt[0]
32 | t[pos] = int(tt[1])
33 | if tt[2] == "L":
34 | pos -= 1
35 | else:
36 | pos += 1
37 | cnt += 1
38 | if s == "H":
39 | break
40 | if ms != -1 and cnt > ms:
41 | halt = False
42 | break
43 | return halt, cnt, sum(t)
44 |
45 | def draw(t0):
46 | import matplotlib.pyplot as plt
47 | import networkx as nx
48 | G = nx.DiGraph()
49 |
50 | for i,x in enumerate(t0):
51 | ts = chr(ord("A") + i//2)
52 | ns = x[0]
53 | lbl = str(i%2)+x[1:]
54 | G.add_edge(ts, ns, label=lbl)
55 |
56 | pos = nx.spring_layout(G)
57 | nx.draw_networkx(G, pos)
58 | edge_labels = nx.get_edge_attributes(G, 'label')
59 | nx.draw_networkx_edge_labels(G, pos, edge_labels = edge_labels)
60 | plt.show()
61 |
62 |
63 | if __name__ == "__main__":
64 | print(run(t0))
65 | #draw(t0)
66 |
--------------------------------------------------------------------------------
/bb/search.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | MS = 4
4 | MAXS = 120
5 |
6 | hcount = -1
7 | mcount = -1
8 | mss = -1
9 | mst = -1
10 |
11 | def mprint(m):
12 | # match https://catonmat.net/busy-beaver
13 | s = []
14 | for k,v in sorted(m.items()):
15 | s.append(k[0]+str(k[1])+" -> "+v[2]+str(v[0])+str(v[1]))
16 | return ' '.join(s)
17 |
18 | def run(M, s, t, h, steps):
19 | global mss, mst, mcount, hcount
20 | # step count or head escape to end
21 | while steps < MAXS and h > 1 and h < len(t)-1:
22 | # state adder, kick off with recursion
23 | if s not in M:
24 | # jump to all current states possible
25 | nsp = sorted(list(set([k[0] for k in M]+[s[0]])))
26 | if len(nsp) < MS:
27 | # not at the limit, add one more state
28 | nsp.append(chr(ord('a')+len(nsp)))
29 | else:
30 | # seen all, now we can halt
31 | nsp.append('H')
32 | #print("missing", s)
33 | for w in [0, 1]:
34 | for d in ['l', 'r']:
35 | for ns in nsp:
36 | # copy M and t here, and kick off all the new machines
37 | Mp = M.copy()
38 | Mp[s] = (w,d,ns)
39 | #print(mprint(Mp))
40 | run(Mp, s, t[:], h, steps)
41 |
42 | # this machine was incomplete, don't keep running
43 | # also doesn't count toward machines
44 | return
45 |
46 | # s in M
47 | w,d,ns = M[s]
48 |
49 | # update the tape and head position
50 | t[h] = w
51 | if d == 'l':
52 | h -= 1
53 | else:
54 | h += 1
55 |
56 | s = (ns, t[h])
57 | steps += 1
58 |
59 | # check for halt
60 | if s[0] == 'H':
61 | mss = max(steps, mss)
62 | mst = max(sum(t), mst)
63 | print("halt", steps, sum(t), mss, mst) #, mprint(M))
64 | hcount += 1
65 | break
66 | mcount += 1
67 |
68 |
69 | t = [0]*(MAXS*2)
70 | M = {}
71 | M[('a', 0)] = (1, 'r', 'b')
72 | run(M, ('a', 0), t, MAXS, 0)
73 | print(mss, mst, hcount, mcount)
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/bb/skelet/.gitignore:
--------------------------------------------------------------------------------
1 | bbfind
2 | bbfind.o
3 | *.txt
4 |
--------------------------------------------------------------------------------
/bb/tnf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # https://sci-hub.tw/10.1109/PGEC.1966.264572
4 | # Hmm, the tree normal form description is kind of annoying, it's a graph, right?
5 | # Oh, "Attacking the Busy Beaver 5" has a clearer description
6 | # Does the first move need to print a one?
7 |
8 | # A0 = B1L looks like the default start in "Attacking the Busy Beaver 5"
9 | # E0 | E1 = H1L is the final one
10 |
11 | # They even seem to be reasoning about the machines while they generate them
12 | # This is a little annoying as the function can only be computed in order
13 |
14 | # Hmm https://arxiv.org/pdf/1610.03184.pdf
15 |
16 | from run import run
17 |
18 | # 4*2*2 = 16
19 | # 16^6 possible for sigma(3, 2)
20 |
21 | def gen(x,b=3):
22 | e = (b+1)*2*2
23 | ret = []
24 | for i in range(b*2):
25 | t = x%e
26 | ss = "L" if t%2 else "R"
27 | t //= 2
28 | ss = ("0" if t%2 else "1") + ss
29 | t //= 2
30 | if t==b:
31 | ss = "H" + ss
32 | else:
33 | ss = chr(ord("A") + t) + ss
34 | ret.append(ss)
35 | x //= e
36 | return ret
37 |
38 | if __name__ == "__main__":
39 | b = 3
40 | all_s = 0
41 | all_sigma = 0
42 | for m in range(((b+1)*2*2)**(b*2)):
43 | mm = gen(m, b)
44 | halt, s, sigma = run(mm, ms=100)
45 | print(mm, halt, s, sigma, all_s, all_sigma)
46 | if halt:
47 | all_s = max(s, all_s)
48 | all_sigma = max(sigma, all_sigma)
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/bb/zany.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | clang++ --std=c++17 zanyzoo.cc
3 | ./a.out
4 |
5 |
--------------------------------------------------------------------------------
/bb/zanyzoo.cc:
--------------------------------------------------------------------------------
1 | // (State, Input, Output, Direction, NewState)
2 | #include
3 | #include
4 | #include
5 | #include
6 | using std::vector;
7 | using std::min;
8 | using std::max;
9 | using std::thread;
10 | using std::priority_queue;
11 |
12 | #define DEBUG
13 |
14 | // total 2x2 -- 3*2*2*4 = 48
15 |
16 | // for 2x3, we expect 2764
17 | // for 3x2, we expect 3508 (228 for the first)
18 | // for 4x2, we expect 511145, we get 637433
19 |
20 | #define N 2
21 | #define M 4
22 |
23 | #define STATE_HALT -1
24 | #define STATE_UNDEFINED -2
25 |
26 | #define S(x) (x-'a')
27 | #define D(x) (x == 'r' ? 1 : -1)
28 |
29 | #define rS(x) (x == -1 ? 'h' : (x+'a'))
30 | #define rD(x) (x == 1 ? 'r' : 'l')
31 |
32 | class transition {
33 | public:
34 | transition() {
35 | output = -1;
36 | direction = 0;
37 | new_state = -2;
38 | }
39 | transition(int o, int d, int ns) :
40 | output(o), direction(d), new_state(ns)
41 | {
42 | }
43 |
44 | int output;
45 | int direction;
46 | int new_state;
47 | };
48 |
49 | class tape {
50 | public:
51 | int& operator[](int l) {
52 | if (l >= 0) {
53 | if (fwd.size() < (l+1)) { fwd.resize(l+1, 0); }
54 | return fwd.data()[l];
55 | } else {
56 | l = (-l)-1;
57 | if (bwd.size() < (l+1)) { bwd.resize(l+1, 0); }
58 | return bwd.data()[l];
59 | }
60 | }
61 |
62 | bool is_blank() {
63 | for (auto s : fwd) { if (s != 0) return false; }
64 | for (auto s : bwd) { if (s != 0) return false; }
65 | return true;
66 | }
67 |
68 | // these are copied when we copy the tape
69 | vector fwd;
70 | vector bwd;
71 | };
72 |
73 | class machine {
74 | public:
75 | machine() {
76 | cs = S('a');
77 | cp = 0;
78 | steps = 0;
79 | card = 0;
80 | num_states = 0;
81 | num_symbols = 0;
82 | }
83 |
84 | bool will_go_undefined() {
85 | transition &ttf = tf[cs][t[cp]];
86 | return ttf.new_state == STATE_UNDEFINED;
87 | }
88 |
89 | void add_tf(int n, int m, int output, int direction, int new_state) {
90 | num_states = max(num_states, n+1);
91 | num_symbols = max(num_symbols, m+1);
92 |
93 | num_states = max(num_states, new_state+1);
94 | num_symbols = max(num_symbols, output+1);
95 |
96 | assert(new_state != STATE_UNDEFINED);
97 | card += (tf[n][m].new_state == STATE_UNDEFINED);
98 |
99 | tf[n][m].output = output;
100 | tf[n][m].direction = direction;
101 | tf[n][m].new_state = new_state;
102 | }
103 |
104 | bool is_full() {
105 | //printf("is_full %d %d\n", num_states, num_symbols);
106 | return (num_states == N && num_symbols == M);
107 | }
108 |
109 | void print() {
110 | //printf("%4d: ", steps);
111 | for (int n = 0; n < N; n++) {
112 | for (int m = 0; m < M; m++) {
113 | if (tf[n][m].new_state == STATE_UNDEFINED) {
114 | printf("___ ");
115 | } else {
116 | printf("%d%c%c ", tf[n][m].output,
117 | rD(tf[n][m].direction),
118 | rS(tf[n][m].new_state));
119 | }
120 | }
121 | }
122 | printf("\n");
123 | }
124 |
125 | bool operator <(const machine& m) const {
126 | return steps > m.steps;
127 | }
128 |
129 | bool run() {
130 | steps++;
131 | transition &ttf = tf[cs][t[cp]];
132 | t[cp] = ttf.output;
133 | cp += ttf.direction;
134 | cs = ttf.new_state;
135 | return cs == STATE_HALT;
136 | }
137 |
138 | // Definition 23
139 | bool is_zdex() {
140 | int cnt = 0;
141 | for (int n = 0; n < N; n++) {
142 | if (tf[n][0].new_state != STATE_UNDEFINED) {
143 | cnt += (tf[n][0].direction == 1);
144 | }
145 | }
146 | return cnt == N;
147 | }
148 |
149 | int used_states;
150 | int used_symbols;
151 | int num_states;
152 | int num_symbols;
153 | int card;
154 |
155 | tape t;
156 | int cs;
157 | int cp;
158 | transition tf[N][M];
159 | int steps;
160 | };
161 |
162 | // thread safe?
163 | priority_queue ms;
164 | vector out;
165 |
166 | void init() {
167 | machine mm;
168 |
169 | // step 1
170 | // note that {'a', 'b'} and {'0', '1'} are in all machines
171 | mm.add_tf(S('a'), 0, 1, D('r'), S('b'));
172 |
173 | /*mm.add_tf(S('b'), 0, 1, D('l'), S('a')); ms.push(mm);
174 | return;*/
175 |
176 | // step 2
177 | int mM = min(mm.num_symbols+1, M);
178 | for (int m = 0; m < mM; m++) {
179 | mm.add_tf(S('b'), 0, m, D('l'), S('a')); ms.push(mm);
180 | mm.add_tf(S('b'), 0, m, D('l'), S('b')); ms.push(mm);
181 | }
182 |
183 | if (N >= 3) {
184 | for (int m = 0; m < mM; m++) {
185 | mm.add_tf(S('b'), 0, m, D('l'), S('c')); ms.push(mm);
186 | mm.add_tf(S('b'), 0, m, D('r'), S('c')); ms.push(mm);
187 | }
188 | }
189 | }
190 |
191 | void add_queue(machine &mm) {
192 | ms.push(mm);
193 | }
194 |
195 | void add_out(machine &mm) {
196 | out.push_back(mm);
197 | }
198 |
199 | void generate() {
200 | machine mm;
201 | int bc = 0;
202 |
203 | // step 3
204 | while (true) {
205 | if (ms.size() == 0) {
206 | break;
207 | }
208 | mm = ms.top();
209 | ms.pop();
210 |
211 | // step 3: execute M on the blank input until...
212 | while (true) {
213 | #ifdef DEBUG
214 | if (bc % 10000 == 0) {
215 | transition &ttf = mm.tf[mm.cs][mm.t[mm.cp]];
216 | printf("%lu -- %lu %lu -- %d: %d %d=%d x out:%d dir:%d ns:%d\n",
217 | 1+out.size()+ms.size(),
218 | out.size(), ms.size(),
219 | mm.steps, mm.cs, mm.cp, mm.t[mm.cp],
220 | ttf.output, ttf.direction, ttf.new_state);
221 | }
222 | #endif
223 | bc++;
224 |
225 | // bound on number of exec steps exceeded
226 | if (mm.steps > 200) {
227 | add_out(mm);
228 | break;
229 | }
230 |
231 | // failed blank tape test, output the irrelevant machine
232 | if (mm.steps > 0 && mm.t.is_blank()) {
233 | add_out(mm);
234 | break;
235 | }
236 |
237 | // step 4: about to go to an undefined place! add possible branches
238 | if (mm.will_go_undefined()) {
239 | // potentially add the halting state
240 | if (mm.is_full()) {
241 | // add halt state and halt
242 | mm.add_tf(mm.cs, mm.t[mm.cp], 1, D('r'), STATE_HALT);
243 | // this will terminate this step, just let it run
244 | if (!mm.is_zdex()) {
245 | add_out(mm);
246 | }
247 | }
248 | // add the other states
249 | for (int n = 0; n < min(mm.num_states+1, N); n++) {
250 | for (int m = 0; m < min(mm.num_symbols+1, M); m++) {
251 | for (int d : {-1, 1}) {
252 | // need to make an early copy for the num_
253 | machine cmm = mm;
254 | cmm.add_tf(cmm.cs, cmm.t[cmm.cp], m, d, n);
255 | if (!cmm.is_zdex()) {
256 | add_queue(cmm);
257 | }
258 | }
259 | }
260 | }
261 | break;
262 | }
263 |
264 | // step 5: 9 steps? halt with the 10th
265 | if (mm.card == N*M-1) {
266 | // add halting to the missing state
267 | for (int n = 0; n < N; n++) {
268 | for (int m = 0; m < M; m++) {
269 | if (mm.tf[n][m].new_state == STATE_UNDEFINED) {
270 | mm.add_tf(n, m, 1, D('r'), STATE_HALT);
271 |
272 | // this is unknown if it halts, but it's complete
273 | add_out(mm);
274 |
275 | // don't return to main queue
276 | //add_queue(mm);
277 | }
278 | }
279 | }
280 | break;
281 | }
282 |
283 | if (mm.run()) {
284 | // halted
285 | add_out(mm);
286 | break;
287 | }
288 | }
289 | }
290 | }
291 |
292 | int main() {
293 | #ifdef DEBUG
294 | printf("running on %d %d\n", N, M);
295 | #endif
296 | init();
297 | generate();
298 |
299 | #ifdef DEBUG
300 | printf("looking at %lu machines\n", out.size());
301 | #else
302 | for (auto mm : out) {
303 | mm.print();
304 | }
305 | #endif
306 | }
307 |
308 |
309 |
--------------------------------------------------------------------------------
/coq/go.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from lark import Lark
4 |
5 | l = Lark(open("grammar.g").read())
6 | p = l.parse(open("stl/peano.v").read())
7 |
8 | def handle_inductive(x):
9 | xx = x.children[0]
10 | print(dir(xx))
11 | print(xx)
12 | print(xx.pretty())
13 |
14 | def handle_definition(x):
15 | pass
16 |
17 | def handle_assertion(x):
18 | pass
19 |
20 |
21 | for x in p.children:
22 | xx = x.children[0] # skip sentence
23 | print(xx.pretty())
24 | """
25 | stype = xx.data
26 | if stype == "inductive":
27 | handle_inductive(xx)
28 | exit(0)
29 | if stype == "definition":
30 | handle_definition(xx)
31 | if stype == "assertion":
32 | handle_assertion(xx)
33 | """
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/coq/grammar.g:
--------------------------------------------------------------------------------
1 | start : sentence+
2 |
3 | sentence : inductive
4 | | assertion
5 | | definition
6 | | stupid
7 |
8 | stupid : "Declare" /(.)+/
9 | | "Set" /(.)+/
10 | | "Reserved" /(.)+/
11 | | "Notation" /(.)+/
12 | | "Print" /(.)+/
13 |
14 | // ident
15 | FIRST_LETTER : ("a".."z") | ("A".."Z") | "_"
16 | SUBSEQUENT_LETTER : ("a".."z") | ("A".."Z") | ("0".."9") | "'" | "_"
17 | IDENT : FIRST_LETTER SUBSEQUENT_LETTER*
18 | access_ident : "." IDENT
19 | name : IDENT | "_"
20 |
21 | // term
22 | qualid : IDENT | qualid access_ident
23 | arg : term
24 | | "(" IDENT ":=" term ")"
25 | sort : "Prop" | "Set" | "Type"
26 |
27 | match_item : term ["as" name] ["in" qualid [pattern]*]
28 | return_type : "return" term
29 |
30 | pattern : qualid
31 | mult_pattern : pattern // broken
32 | equation : mult_pattern "=>" term
33 |
34 | // "exists" and "=" are not a part of the language
35 | term : "forall" binders "," term
36 | | "match" match_item [return_type] "with" ["|" equation ["|" equation]* ] "end"
37 | | "if" term "then" term "else" term
38 | | "(" term ")"
39 | | term "->" term // fake, this notation is defined
40 | | term arg+ // function call
41 | | sort
42 | | qualid
43 |
44 | // this is really wrong
45 | tactic : "exact" term "."
46 |
47 | proof : "Proof." tactic* ("Qed." | "Abort.")
48 |
49 | // binder (is wrong but closer)
50 | binder : name
51 | | name+ [":" term]
52 | | "(" name+ [":" term] ")"
53 | | "(" name [":" term] ":=" term ")"
54 | binders : binder+
55 |
56 | ind_body : IDENT [binders] ":" term ":=" [["|"] IDENT [binders] [":" term]] ("|" IDENT [binders] [":" term])*
57 | inductive : "Inductive" ind_body "."
58 |
59 | definition : "Definition" IDENT [binders] [":" term] ":=" term "."
60 |
61 | // TODO: does proof belong here?
62 | assertion : assertion_keyword IDENT [binders] ":" term "." proof
63 | assertion_keyword : "Theorem" | "Lemma"
64 |
65 | %ignore " "
66 | %ignore "\n"
67 |
68 | COMMENT : "(*" /(.|\n)+?/ "*)"
69 | %ignore COMMENT
70 |
71 |
--------------------------------------------------------------------------------
/coq/stl/peano.v:
--------------------------------------------------------------------------------
1 | (** this makes intros work *)
2 | Declare ML Module "ltac_plugin".
3 | Set Default Proof Mode "Classic".
4 |
5 | (** annoying without this *)
6 | Reserved Notation "x -> y" (at level 99, right associativity, y at level 200).
7 |
8 | (** for all x of type T, P *)
9 | (** the variable in the forall is _, so this is a non dependent product *)
10 | Notation "A -> B" := (forall _ : A, B).
11 |
12 | (** unit/empty is like True/False, but it's a Set, not a Prop *)
13 | (**Inductive unit : Set := tt.
14 | Inductive empty : Set :=.*)
15 |
16 | (** bool has two items *)
17 | (** the bool' was impiled on the type of the items *)
18 | Inductive bool' : Set :=
19 | | true : bool'
20 | | false : bool'.
21 |
22 | (** False has no items *)
23 | Inductive False : Prop :=.
24 | Definition not (A:Prop) := A -> False.
25 |
26 | (** True has one item *)
27 | Inductive True : Prop := I : True.
28 |
29 | (** Prop is better than Type *)
30 | Inductive eqb' (x : bool') : bool' -> Prop :=
31 | | eqb'_refl : eqb' x x.
32 |
33 | Theorem true_is_true : eqb' true true.
34 | Proof.
35 | exact (eqb'_refl true).
36 | Qed.
37 |
38 | Definition check (e : bool') : Prop :=
39 | match e with
40 | | true => True
41 | | false => False
42 | end.
43 |
44 | Theorem true_is_not_false : not (eqb' true false).
45 | Proof.
46 | exact (eqb'_ind true check I false).
47 | Qed.
48 |
49 | Theorem false_implies_true : False -> True.
50 | Proof.
51 | intros.
52 | induction H.
53 | Qed.
54 |
55 | Theorem true_not_implies_false : not (True -> False).
56 | Proof.
57 | unfold not.
58 | intros.
59 | assert True.
60 | exact I.
61 | apply H in H0.
62 | apply H0.
63 | Qed.
64 |
65 |
66 | (** print the theorems *)
67 | Print true_is_true.
68 | Print true_is_not_false.
69 | Print false_implies_true.
70 |
71 | (** can we prove to here in twitchcoq? CHALLENGE *)
72 |
73 | (**Inductive nat' : Set :=
74 | | zero : nat'
75 | | succ : nat' -> nat'.
76 |
77 |
78 | Definition eqb'' (x y : bool') := match x,y with
79 | | true, true => True
80 | | false, false => True
81 | | _, _ => False
82 | end.
83 |
84 | Inductive eqn' (x : nat') : nat' -> Prop :=
85 | | eqn'_refl : eqn' x x.
86 |
87 | Definition andb' (b1 b2 : bool') : bool' :=
88 | match b1 with
89 | | true => b2
90 | | false => false
91 | end.
92 | Definition orb' (b1 b2 : bool') : bool' :=
93 | match b1 with
94 | | true => true
95 | | false => b2
96 | end.
97 | Definition notb' (b1 : bool') : bool' :=
98 | match b1 with
99 | | true => false
100 | | false => true
101 | end.
102 | *)
103 |
104 | (**Theorem demorgan : forall a b : bool', eqb' (notb' (orb' a b)) (andb' (notb' a) (notb' b)).
105 | Proof.
106 | intros a b.
107 | destruct a; destruct b; simpl; reflexivity.
108 | Qed.*)
109 |
110 | (**Theorem eqb_is_good : forall x y : bool', (eqb'' x y) -> (eqb' x y).
111 | Proof.
112 | intros.
113 | destruct x.
114 | destruct y.
115 | reflexivity.
116 | unfold eqb'' in H.
117 | contradiction.
118 | destruct y.
119 | unfold eqb'' in H.
120 | contradiction.
121 | reflexivity.
122 | Qed.
123 |
124 | Theorem eqb_is_also_good : forall x y : bool', (eqb' x y) -> (eqb'' x y).
125 | Proof.
126 | intros.
127 | destruct x; destruct y.
128 | reflexivity.
129 | unfold eqb''.*)
130 |
131 | (**
132 | specialize (eqb'_ind true).
133 | intros.
134 | specialize (eqb'_ind true (fun e : bool' => e)).
135 | assert (eqb' true true).
136 | reflexivity.
137 | specialize (bool'_ind (eqb' true)).
138 | intros.
139 | Abort.
140 |
141 | Theorem dummy : forall b : bool', eqb' true b -> False.
142 | Proof.
143 | *)
144 |
145 |
146 | (**
147 | intros.
148 | inversion H.
149 | Qed.*)
150 |
151 | (** note, exists is hard to make work *)
152 | (**Theorem all_have_succ : forall x : nat', ex (eqn' (succ x) y).
153 | Proof.
154 | intros x.
155 | exists (succ x).
156 | reflexivity.
157 | Qed.
158 | *)
159 |
160 |
161 |
--------------------------------------------------------------------------------
/coq/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | coqtop -noinit -l stl/peano.v
3 |
4 |
--------------------------------------------------------------------------------
/coq/twoplustwo.v:
--------------------------------------------------------------------------------
1 | Inductive nat' : Set :=
2 | | Z : nat'
3 | | S : nat' -> nat'.
4 |
5 | Inductive eqn' (x : nat') : nat' -> Prop :=
6 | | eqn'_refl : eqn' x x.
7 |
8 | Theorem one_ne_zero : eqn' (S Z) Z -> False.
9 | Proof.
10 | intros.
11 | inversion H.
12 | Qed.
13 |
14 | Fixpoint plus' (x y : nat') : nat' :=
15 | match x with
16 | | Z => y
17 | | S w => S (plus' w y)
18 | end.
19 |
20 | Theorem two_plus_two_eq_four : eqn' (plus' (S (S Z)) (S (S Z))) (S (S (S (S Z)))).
21 | Proof.
22 | apply eqn'_refl.
23 | Qed.
24 |
25 |
--------------------------------------------------------------------------------
/harrison/chap1.ml:
--------------------------------------------------------------------------------
1 | type expression =
2 | Var of string
3 | | Const of int
4 | | Add of expression * expression
5 | | Mul of expression * expression;;
6 |
7 | (*
8 | Add(Mul(Const 2, Var "x"), Var ("y"));;
9 | *)
10 |
11 | let simplify1 expr =
12 | match expr with
13 | Add(Const(m),Const(n)) -> Const(m + n)
14 | | Mul(Const(m),Const(n)) -> Const(m * n)
15 | | Add(Const(0),x) -> x
16 | | Add(x,Const(0)) -> x
17 | | Mul(Const(0),x) -> Const(0)
18 | | Mul(x,Const(0)) -> Const(0)
19 | | Mul(Const(1),x) -> x
20 | | Mul(x,Const(1)) -> x
21 | | _ -> expr;;
22 |
23 |
24 | let rec simplify expr =
25 | match expr with
26 | Add(e1,e2) -> simplify1(Add(simplify e1,simplify e2))
27 | | Mul(e1,e2) -> simplify1(Mul(simplify e1,simplify e2))
28 | | _ -> simplify1 expr;;
29 |
30 | let e = Add(Mul(Add(Mul(Const(0),Var "x"),Const(1)),Const(3)), Const(12));;
31 |
32 |
--------------------------------------------------------------------------------
/harrison/full.ml:
--------------------------------------------------------------------------------
1 | (*
2 |
3 | I think this exercise might be worth doing, but ugh this ocaml is gross. Write in Haskell?
4 |
5 | Question: Why doesn't programming have axioms like this?
6 |
7 | metamath set.mm begins with an implementation of this in an even more minimal language
8 |
9 | And I think all this is just for first order logic. Can metamath do more?
10 |
11 | *)
12 |
13 | type term = Var of string
14 | | Fn of string * term list;;
15 | type fol = R of string * term list;;
16 |
17 | type ('a)formula = False
18 | | True
19 | | Atom of 'a
20 | | Not of ('a)formula
21 | | And of ('a)formula * ('a)formula
22 | | Or of ('a)formula * ('a)formula
23 | | Imp of ('a)formula * ('a)formula
24 | | Iff of ('a)formula * ('a)formula
25 | | Forall of string * ('a)formula
26 | | Exists of string * ('a)formula;;
27 |
28 | (*
29 | So this is just the typing, not the inference rules.
30 | *)
31 |
32 | module type Proofsystem =
33 | sig type thm
34 | val modusponens : thm -> thm -> thm
35 | val gen : string -> thm -> thm
36 | val axiom_addimp : fol formula -> fol formula -> thm
37 | val axiom_distribimp : fol formula -> fol formula -> fol formula -> thm
38 | val axiom_doubleneg : fol formula -> thm
39 | val axiom_allimp : string -> fol formula -> fol formula -> thm
40 | val axiom_impall : string -> fol formula -> thm
41 | val axiom_existseq : string -> term -> thm
42 | val axiom_eqrefl : term -> thm
43 | val axiom_funcong : string -> term list -> term list -> thm
44 | val axiom_predcong : string -> term list -> term list -> thm
45 | val axiom_iffimp1 : fol formula -> fol formula -> thm
46 | val axiom_iffimp2 : fol formula -> fol formula -> thm
47 | val axiom_impiff : fol formula -> fol formula -> thm
48 | val axiom_true : thm
49 | val axiom_not : fol formula -> thm
50 | val axiom_and : fol formula -> fol formula -> thm
51 | val axiom_or : fol formula -> fol formula -> thm
52 | val axiom_exists : string -> fol formula -> thm
53 | val concl : thm -> fol formula
54 | end;;
55 |
56 | (* Helper functions (need exists and itlist2) *)
57 |
58 | let mk_eq s t = Atom(R("=",[s;t]));;
59 |
60 | let rec occurs_in s t =
61 | s = t or
62 | match t with
63 | Var y -> false
64 | | Fn(f,args) -> exists (occurs_in s) args;;
65 |
66 | let rec free_in t fm =
67 | match fm with
68 | False
69 | | True -> false
70 | | Atom(R(p,args)) -> exists (occurs_in t) args
71 | | Not(p) -> free_in t p
72 | | And(p,q)|Or(p,q)|Imp(p,q)|Iff(p,q) -> free_in t p or free_in t q
73 | | Forall(y,p)|Exists(y,p) -> not(occurs_in (Var y) t) & free_in t p;;
74 |
75 | (*
76 | Hmm, I don't exactly understand this. Need to learn ocaml syntax, this is like a class for the type?
77 | Seems like it.
78 | *)
79 |
80 | module Proven : Proofsystem =
81 | struct
82 | type thm = fol formula
83 | let modusponens pq p =
84 | match pq with
85 | Imp(p',q) when p = p' -> q
86 | | _ -> failwith "modusponens"
87 | let gen x p = Forall(x,p)
88 | let axiom_addimp p q = Imp(p,Imp(q,p))
89 | let axiom_distribimp p q r =
90 | Imp(Imp(p,Imp(q,r)),Imp(Imp(p,q),Imp(p,r)))
91 | let axiom_doubleneg p = Imp(Imp(Imp(p,False),False),p)
92 | let axiom_allimp x p q =
93 | Imp(Forall(x,Imp(p,q)),Imp(Forall(x,p),Forall(x,q)))
94 | let axiom_impall x p =
95 | if not (free_in (Var x) p) then Imp(p,Forall(x,p))
96 | else failwith "axiom_impall: variable free in formula"
97 | let axiom_existseq x t =
98 | if not (occurs_in (Var x) t) then Exists(x,mk_eq (Var x) t)
99 | else failwith "axiom_existseq: variable free in term"
100 | let axiom_eqrefl t = mk_eq t t
101 | let axiom_funcong f lefts rights =
102 | itlist2 (fun s t p -> Imp(mk_eq s t,p)) lefts rights
103 | (mk_eq (Fn(f,lefts)) (Fn(f,rights)))
104 | let axiom_predcong p lefts rights =
105 | itlist2 (fun s t p -> Imp(mk_eq s t,p)) lefts rights
106 | (Imp(Atom(R(p,lefts)),Atom(R(p,rights))))
107 | let axiom_iffimp1 p q = Imp(Iff(p,q),Imp(p,q))
108 | let axiom_iffimp2 p q = Imp(Iff(p,q),Imp(q,p))
109 | let axiom_impiff p q = Imp(Imp(p,q),Imp(Imp(q,p),Iff(p,q)))
110 | let axiom_true = Iff(True,Imp(False,False))
111 | let axiom_not p = Iff(Not p,Imp(p,False))
112 | let axiom_and p q = Iff(And(p,q),Imp(Imp(p,Imp(q,False)),False))
113 | let axiom_or p q = Iff(Or(p,q),Not(And(Not(p),Not(q))))
114 | let axiom_exists x p = Iff(Exists(x,p),Not(Forall(x,Not p)))
115 | let concl c = c
116 | end;;
117 |
118 | let print_thm th =
119 | open_box 0;
120 | print_string "|-"; print_space();
121 | open_box 0; print_formula print_atom 0 (concl th); close_box();
122 | close_box();;
123 |
124 | #install_printer print_thm;;
125 |
126 |
--------------------------------------------------------------------------------
/harrison/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rlwrap ocaml -init full.ml
3 |
4 |
--------------------------------------------------------------------------------
/metamath/.gitignore:
--------------------------------------------------------------------------------
1 | metamath-test
2 |
--------------------------------------------------------------------------------
/metamath/cc/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | a.out
3 | *.o
4 | .sconsign.dblite
5 |
--------------------------------------------------------------------------------
/metamath/cc/Math.g:
--------------------------------------------------------------------------------
1 | grammar Math;
2 |
3 | start : outermost_scope_stmt* ;
4 | outermost_scope_stmt : constant_stmt | stmt ;
5 | constant_stmt : '$c' constant+ '$.' ;
6 |
7 | stmt : block | variable_stmt | disjoint_stmt | hypothesis_stmt | assert_stmt ;
8 | block : '${' stmt* '$}' ;
9 |
10 | variable_stmt : '$v' variable+ '$.' ;
11 | disjoint_stmt : '$d' variable variable variable* '$.' ;
12 | hypothesis_stmt : floating_stmt | essential_stmt ;
13 |
14 | floating_stmt : LABEL '$f' typecode variable '$.' ;
15 | essential_stmt : LABEL '$e' typecode math_symbol* '$.' ;
16 |
17 | assert_stmt : axiom_stmt | provable_stmt ;
18 |
19 | axiom_stmt : LABEL '$a' typecode math_symbol* '$.' ;
20 | provable_stmt : LABEL '$p' typecode math_symbol* '$=' proof '$.' ;
21 |
22 | proof : uncompressed_proof | compressed_proof ;
23 | uncompressed_proof : math_symbol+ ; // LABEL or ?
24 | compressed_proof : MATHWORD LABEL* MATHWORD math_symbol+ ;
25 | // note, this has to verify by hand, LABEL/MATHWORD are too forgiving
26 |
27 | typecode : constant ;
28 |
29 | constant : math_symbol ;
30 | variable : math_symbol ;
31 |
32 | math_symbol : (LABEL | MATHWORD) ;
33 |
34 | fragment LCHAR : ('a'..'z') | ('A'..'Z') | ('0'..'9') | '.' | '-' | '_' ;
35 | fragment CHAR : LCHAR | '\'' | '|' | '+' | '*' | '=' | '<' | '>' | '(' | ')' | ':' | ',' | '\\' | '[' | ']' | '/' | '~' | '!' | '?' | '@' | '&' | '{' | '}' | '^' | '`' | '"' | ';' | '#' ;
36 |
37 | LABEL : LCHAR+ ;
38 | MATHWORD : CHAR+ ;
39 |
40 | COMMENT : '$(' .*? '$)' -> skip ;
41 | WHITESPACE : (' ' | '\n' | '\t' | '\r')+ -> skip ;
42 |
43 |
44 |
--------------------------------------------------------------------------------
/metamath/cc/README:
--------------------------------------------------------------------------------
1 | someone did this
2 | https://github.com/naipmoro/gramm/blob/master/src/main/antlr4/naipmoro/gramm/MM.g4
3 |
--------------------------------------------------------------------------------
/metamath/cc/SConstruct:
--------------------------------------------------------------------------------
1 | env = Environment(CCFLAGS="-std=c++17", CPPPATH='/usr/local/Cellar/antlr4-cpp-runtime/4.7.2/include/antlr4-runtime')
2 |
3 | ANTLR_FILES = env.Command(
4 | target=["out/MathParser.cpp", "out/MathLexer.cpp", "out/MathBaseListener.cpp", "out/MathListener.cpp"],
5 | source="Math.g",
6 | action = env.Action(
7 | "java -jar ~/Downloads/antlr-4.7.2-complete.jar -o out -Dlanguage=Cpp Math.g",
8 | "Generating antlr"))
9 | SOURCE_FILES = ["main.cc"]
10 | env.Program('a.out', SOURCE_FILES+ANTLR_FILES, LIBS='antlr4-runtime')
11 |
12 |
--------------------------------------------------------------------------------
/metamath/cc/main.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "antlr4-runtime.h"
5 | #include "out/MathLexer.h"
6 | #include "out/MathParser.h"
7 | #include "out/MathBaseListener.h"
8 |
9 | using namespace antlr4;
10 |
11 | /*class TreeShapeListener : public MathBaseListener {
12 | public:
13 | void enterStart(ParserRuleContext *ctx) override {
14 | printf("here\n");
15 | }
16 | };*/
17 |
18 | int main(int argc, const char* argv[]) {
19 | std::ifstream stream;
20 | stream.open(argv[1]);
21 |
22 | ANTLRInputStream input(stream);
23 | MathLexer lexer(&input);
24 | CommonTokenStream tokens(&lexer);
25 | MathParser parser(&tokens);
26 |
27 | tree::ParseTree *tree = parser.start();
28 | std::cout << tree->toStringTree() << std::endl;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/metamath/check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | echo -e "VERIFY PROOF *\nshow proof theorem1" | \
3 | ~/build/metamath/metamath miu2.mm
4 |
--------------------------------------------------------------------------------
/metamath/lean/.gitignore:
--------------------------------------------------------------------------------
1 | lean-3.4.2
2 |
--------------------------------------------------------------------------------
/metamath/lean/main.lean:
--------------------------------------------------------------------------------
1 | import system.io
2 |
3 | open list
4 | open string
5 |
6 | inductive stmt : Type
7 | | constant_stmt : list string -> stmt
8 | | variable_stmt : list string -> stmt
9 | | disjoint_stmt : list string -> stmt
10 | | floating_stmt : string -> string -> string -> stmt
11 | | essential_stmt : string -> string -> (list string) -> stmt
12 | | axiom_stmt : string -> string -> (list string) -> stmt
13 | | provable_stmt : string -> string -> (list string) -> (list string) -> stmt
14 | | scope_stmt : (list stmt) -> stmt
15 | | include_stmt : string -> stmt
16 | | parse_error : (list string) -> stmt
17 |
18 | def stmt_to_string : stmt -> string
19 | | (stmt.constant_stmt l) := "constant_stmt: " ++ (list.to_string l)
20 | | (stmt.variable_stmt l) := "variable_stmt: " ++ (list.to_string l)
21 | | (stmt.disjoint_stmt l) := "disjoint_stmt: " ++ (list.to_string l)
22 | | (stmt.floating_stmt name typecode var) := "floating_stmt: " ++ name ++ " " ++ typecode ++ " " ++ var
23 | | (stmt.essential_stmt name typecode ms) := "essential_stmt: " ++ name ++ " " ++ typecode ++ " " ++ (list.to_string ms)
24 | | (stmt.axiom_stmt name typecode ms) := "axiom_stmt: " ++ name ++ " " ++ typecode ++ " " ++ (list.to_string ms)
25 | | (stmt.provable_stmt name typecode ms proof) := "provable_stmt: " ++ name ++ " " ++ typecode ++ " " ++ (list.to_string ms) ++ " " ++ (list.to_string proof)
26 | | (stmt.scope_stmt (a::lst)) := (stmt_to_string a) ++ "\n" ++ (stmt_to_string (stmt.scope_stmt lst))
27 | | (stmt.scope_stmt []) := "}"
28 | | (stmt.include_stmt l) := "include_stmt: " ++ l
29 | | (stmt.parse_error lst) := "PARSE ERROR: " ++ (lst.take 10).to_string
30 |
31 | instance : has_to_string stmt := ⟨stmt_to_string⟩
32 |
33 | def consume_until (s : string) : list string → (list string) × (list string) :=
34 | prod.map id tail ∘ span (≠ s)
35 |
36 | def parser_core : nat -> list string -> list stmt
37 | | 0 := λ x, [(stmt.parse_error x)]
38 | | (n+1) := let pc := (parser_core n) in λ x, match x with
39 | | ("$c" :: l) := let (x, rest) := consume_until "$." l in (stmt.constant_stmt x) :: (pc rest)
40 | | ("$v" :: l) := let (x, rest) := consume_until "$." l in (stmt.variable_stmt x) :: (pc rest)
41 | | ("$d" :: l) := let (x, rest) := consume_until "$." l in (stmt.disjoint_stmt x) :: (pc rest)
42 | | (name :: "$f" :: typecode :: var :: "$." :: l) := (stmt.floating_stmt name typecode var) :: (pc l)
43 | | (name :: "$e" :: typecode :: l) := let (x, rest) := consume_until "$." l in
44 | (stmt.essential_stmt name typecode x) :: (pc rest)
45 | | (name :: "$a" :: typecode :: l) := let (x, rest) := consume_until "$." l in
46 | (stmt.axiom_stmt name typecode x) :: (pc rest)
47 | | (name :: "$p" :: typecode :: l) := let (x, rest) := consume_until "$=" l in
48 | let (y, rest2) := consume_until "$." rest in
49 | (stmt.provable_stmt name typecode x y) :: (pc rest2)
50 | | ("${" :: l) := let (x, rest) := consume_until "$}" l in
51 | (stmt.scope_stmt ((parser_core n) x)) :: (pc rest)
52 | -- comments go nowhere
53 | | ("$(" :: l) := let (x, rest) := consume_until "$)" l in (pc rest)
54 | | ("$[" :: filename :: "$]" :: rest) := stmt.include_stmt filename :: pc rest
55 | | [] := []
56 | | l := [(stmt.parse_error l)]
57 | end
58 |
59 | def parser (s : list string) : list stmt := parser_core (length s) s
60 |
61 | def whitespace : char -> bool
62 | | ' ' := true
63 | | '\n' := true
64 | | default := false
65 |
66 | def lexer := filter (≠ "") ∘ split whitespace
67 |
68 | -- IO crap below this line
69 | open io
70 |
71 | def parse_from (directory : string) (file : string) : io stmt :=
72 | do s ← fs.read_file (directory ++ file),
73 | let p := parser $ lexer s.to_string,
74 | match p with
75 | | stmt.include_stmt db_file :: rest :=
76 | do db ← fs.read_file (directory ++ db_file),
77 | -- lean harassed about recursion, so this only supports one import.
78 | return $ stmt.scope_stmt $ parser (lexer db.to_string) ++ rest
79 | | _ := return $ stmt.scope_stmt p
80 | end
81 |
82 | def main : io unit :=
83 | do let dir := "../", -- doesn't work with eval, but "lean -- run main.lean" is fine
84 | let file := "twoplustwo.mm",
85 | parse_from dir file >>= print_ln -- uses to_string instance
86 |
87 | #eval parse_from "/Users/smooth/build/twitchcoq/metamath/" "miu2.mm" >>= print_ln
88 |
--------------------------------------------------------------------------------
/metamath/lib/peano.mm:
--------------------------------------------------------------------------------
1 | $(
2 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
3 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
4 | Metamath source file: axioms for Peano arithmetic
5 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
6 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
7 | $)
8 |
9 | $( Copyright (GPL) 2004 Robert Solovay, PO Box 5949, Eugene OR, 97405 $)
10 | $( Comments welcome; email to: solovay at gmail dot com $)
11 |
12 | $( Version of 20-January-07 $)
13 | $( Replaces prior version of 13-July-04 $)
14 | $( 7-Oct-2004 (N. Megill) - Minor fixes to conform to strict Metamath spec $)
15 | $( 11-Oct-2004 (N. Megill) - "$a implies" --> "$a |- implies" at line 224 $)
16 | $( 24-Jun-2006 (N. Megill) - Made label and math symbol names spaces
17 | disjoint, as required by the 24-Jun-2006 modification of the Metamath
18 | specification. Specifically, the labels binop, logbinop, binpred,
19 | and quant were changed to binop_, logbinop_, binpred_, and quant_
20 | respectively. $)
21 | $( 11-Nov-2014 (N. Megill) - updated R. Solovay's email address $)
22 |
23 | $( This file is a mixture of two sorts of things:
24 |
25 | 1) Formal metamath axioms and supporting material. [$f and $d
26 | statements for example.]
27 |
28 | 2) Informal metamathematical arguments that show our axioms suffice to
29 | "do Peano in metamath".
30 |
31 | All our metamathematical arguments are quite constructive and
32 | certainly could be formalized in Primitive Recursive Arithmetic. $)
33 |
34 | $( We shall slightly deviate from the treatment in Appendix C of the
35 | metamath book. We assume that for each constant c an infinite subset
36 | of the variables is preassigned to that constant.
37 |
38 | In particular we will have a constant var. Among our other constants
39 | will be all the symbols of Peano arithmetic except the variables. The
40 | variables of the formal language of Peano Arithmetic will be
41 | identified with the variables attached to the constant symbol var. In
42 | this way each well formed formula or term of PA will *be* a certan
43 | metamath expression. $)
44 |
45 | $(
46 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
47 | Syntax
48 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
49 | $)
50 |
51 | $c |- wff term var $.
52 |
53 | $( The next set of axioms will give the inductive definition of
54 | terms. We will be using Polish notation in our formal development of
55 | the syntax of PA. $)
56 |
57 | $v s t u s0 s1 t0 t1 $.
58 |
59 | ts $f term s $.
60 | tt $f term t $.
61 | tu $f term u $.
62 | ts0 $f term s0 $.
63 | ts1 $f term s1 $.
64 | tt0 $f term t0 $.
65 | tt1 $f term t1 $.
66 |
67 | $v v x y z $.
68 | varv $f var v $.
69 | varx $f var x $.
70 | vary $f var y $.
71 | varz $f var z $.
72 |
73 | $c 0 S + * $.
74 |
75 | $( It is often possible to treat + and * in parallel. The following
76 | device allows us to do this. $)
77 |
78 | $c BINOP $.
79 | $v binop $.
80 | binop_ $f BINOP binop $.
81 | binop_plus $a BINOP + $.
82 | binop_times $a BINOP * $.
83 |
84 | tvar $a term v $.
85 | tzero $a term 0 $.
86 | tsucc $a term S s $.
87 | tbinop $a term binop s t $.
88 |
89 | $( The next set of axioms will give the inductive definition of wff $)
90 |
91 | $c not or and implies iff $.
92 | $c LOGBINOP $.
93 | $v logbinop $.
94 | logbinop_ $f LOGBINOP logbinop $.
95 | logbinopor $a LOGBINOP or $.
96 | logbinopand $a LOGBINOP and $.
97 | logbinopimplies $a LOGBINOP implies $.
98 | logbinopiff $a LOGBINOP iff $.
99 |
100 | $c = < $.
101 | $c BINPRED $.
102 | $v binpred $.
103 | binpred_ $f BINPRED binpred $.
104 | binpred_equals $a BINPRED = $.
105 | binpred_less_than $a BINPRED < $.
106 |
107 | $c forall exists $.
108 | $c QUANT $.
109 | $v quant $.
110 | quant_ $f QUANT quant $.
111 | quant_all $a QUANT forall $.
112 | quant_ex $a QUANT exists $.
113 |
114 | $v phi psi chi $.
115 | wff_phi $f wff phi $.
116 | wff_psi $f wff psi $.
117 | wff-chi $f wff chi $.
118 |
119 | wff_atom $a wff binpred s t $.
120 | wff_not $a wff not psi $.
121 | wff_logbinop $a wff logbinop psi phi $.
122 | wff_quant $a wff quant v phi $.
123 |
124 | $( This completes our description of the syntactic categories of wff
125 | and term $)
126 |
127 | $(
128 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
129 | "Correct" axioms
130 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
131 | $)
132 |
133 | $( In the various sections of this file we will be adding various
134 | axioms [$a statements]. The crucial correctness property that they
135 | will have is the following:
136 |
137 | Consider a substitution instance of the axiom such that the only
138 | variables remaining in the instance [in either hypothesis or
139 | conclusion] are of type var. Then if all the hypotheses [$e
140 | statements] have the form
141 | |- phi
142 | [where phi is a theorem of PA] then the conclusion is also a
143 | theorem of PA.
144 |
145 | The verification that the various axioms we add are correct in
146 | this sense will be "left to the reader". Usually the proof that I
147 | have in mind is a semantic one based upon the consideration of
148 | models of PA. $)
149 | $( I will give a discussion at the end of this document as to why
150 | sticking with this correctness condition on axioms suffices to
151 | guarantee that only correct theorems of Peano arithmetic are
152 | proved.
153 | $)
154 |
155 | $(
156 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
157 | Propositional logic
158 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
159 | $)
160 |
161 | $( We follow closely the treatment in set.mm. We do have to change the
162 | axioms "into Polish". $)
163 |
164 | ax-1 $a |- implies phi implies psi phi $.
165 |
166 | ax-2 $a |- implies
167 | implies phi implies psi chi
168 | implies
169 | implies phi psi
170 | implies phi chi $.
171 | ax-3 $a |- implies
172 | implies not phi not psi
173 | implies psi phi $.
174 |
175 | $( Modus ponens: $)
176 | ${
177 | min $e |- phi $.
178 | maj $e |- implies phi psi $.
179 | ax-mp $a |- psi $.
180 | $}
181 |
182 | bi1 $a |- implies
183 | iff phi psi
184 | implies phi psi $.
185 | bi2 $a |- implies
186 | iff phi psi
187 | implies psi phi $.
188 | bi3 $a |- implies
189 | implies phi psi
190 | implies
191 | implies psi phi
192 | iff phi psi $.
193 | df-an $a |- iff
194 | and phi psi
195 | not implies phi not psi $.
196 | df-or $a |- iff
197 | or phi psi
198 | implies not phi psi $.
199 |
200 | $( Equality axioms $)
201 |
202 | $( From here on out, I won't make an effort to cordinate labels
203 | between my axioms and those of set.mm $)
204 |
205 | eq-refl $a |- = t t $.
206 | eq-sym $a |- implies = s t = t s $.
207 | eq-trans $a |- implies
208 | and = s t = t u
209 | = s u $.
210 | eq-congr $a |- implies
211 | and = s0 s1 = t0 t1
212 | iff binpred s0 t0 binpred s1 t1 $.
213 |
214 | $( The next two axioms were missing in the previous draft of
215 | peano.mm. They are definitely needed. $)
216 |
217 | eq-suc $a |- implies
218 | = s t
219 | = S s S t $.
220 | eq-binop $a |- implies
221 | and = s0 s1 = t0 t1
222 | = binop s0 t0 binop s1 t1 $.
223 |
224 | $( Lemma 1 $)
225 |
226 | $( Lemma 1 of the 2004 version of this document was not needed in the
227 | subsequent development and has been deleted. I decided not to change
228 | the numbering of subsequent lemmas. $)
229 |
230 |
231 | $(
232 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
233 | Free and bound variables; alpha equivalence
234 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
235 | $)
236 |
237 | $( It will be useful to warm up with some familiar concepts. Let PHI
238 | be a well-formed formula of Peano arithmetic. Then Phi is a finite
239 | sequence of symbols, s_1 ... s_n.
240 |
241 | Following Shoenfield's treatment in "Mathematical Logic" we use the
242 | term "designator" for a sequence of symbols that is either a term
243 | or a wff. A basic result says that each s_i is the initial symbol
244 | of precisely one subsequence of s_1 ... s_n which is a designator.
245 |
246 | Suppose that s_i is a variable. We say that s_i is bound in PHI if
247 | there is a subformula of PHI containing s_i whose initial symbol is
248 | a quantifier and whose second symbol is the same variable as s_i.
249 |
250 | [Otherwise s_i is *free* in PHI.]
251 |
252 | If s_i is a bound variable, then there is a shortest subformula of
253 | PHI in which s_i is bound. The quantifier beginning this subformula
254 | is the quantifier that *binds* s_i. $)
255 |
256 | $( alpha equivalence $)
257 |
258 | $( Let Phi_1 and Phi_2 be well-formed formulas of PA. Say Phi_1 is s_1
259 | ... s_n and Phi_2 is t_1 ... t_m.
260 |
261 | We say that Phi_1 and Phi_2 are alpha-equialent if:
262 |
263 | 1) n = m.
264 |
265 | 2) Let 1 <= i <= n. Then s_i is a constant iff t_i is; in that case,
266 | they are the *same* constant.
267 |
268 | 3) Let 1 <= i <= n. Suppose that s_i is a variable. [So t_i is a
269 | variable as well.] Then s_i is free in Phi_1 iff t_i is free in
270 | Phi_2. If s_i is free in Phi_1, then s_i = t_i.
271 |
272 | 4) Let 1 <= i <= n. Suppose that s_i is a variable that is bound in
273 | Phi_1. [It follows that t_i is a variable that is bound in Phi_2.]
274 | Let s_j be the quantifier that binds s_i. Then t_j is the
275 | quantifier that binds t_i.
276 |
277 | [This ends the definition of alpha-equivalence.]
278 |
279 | It is indeed true that alpha-equivalence is an equivalence relation.
280 | $)
281 |
282 | $( Trim formulas $)
283 |
284 | $( The following concept is non-standard. A well-formed formula of PA
285 | is *trim* if:
286 |
287 | 1) No variable occurs both free and bound in Phi.
288 |
289 | 2) Distinct quantifiers bind distinct variables.
290 |
291 | [So
292 | exists x exists x = x x
293 | is not trim since the two quantifiers both bind the variable x.]
294 |
295 | Clearly every formula is alpha-equivalent to some trim
296 | formula. Moreover, we can assume that the bound variables of this
297 | trim equivalent avoid some specified finite set of variables.
298 | $)
299 |
300 | $( Here is the next Lemma we are heading toward. We can add a finite
301 | number of correct axioms to our file so that once this is done, if
302 | Phi_1 and Phi_2 are alpha-equivalent formulas then [subject to the
303 | requirement that any pair of distinct variables appearing in Phi_1 or
304 | Phi_2 is declared disjoint]
305 |
306 | |- iff Phi_1 Phi_2
307 | is a theorem of Metmath [i.e. follows from the given axioms].
308 |
309 | In view of the remarks about trim formulas, we are reduced to the
310 | following special case: Phi_2 is trim and no bound variable of Phi_2
311 | appears [free or bound] in Phi_1.
312 |
313 | We fix Phi_1 and Phi_2 subject to this restriction. We will develop
314 | the axioms we need in the course of the proof. Of course, the reader
315 | should verify that we could have specified them in advance. In
316 | particular the additional axioms we list will not depend on Phi_1 or Phi_2. $)
317 |
318 | $( Our proof strategy is as follows;
319 |
320 | To each subformula Psi of Phi_1, we shall attach a claim C(Psi) [which
321 | will also be a well-formed formula of PA]. We will prove in Metamath
322 | the various claims C(Psi). The construction of these proofs will be an
323 | inductive one [by induction on the length of the subformula,
324 | say]. From the claim C(Phi_1), the desired equivalence of Phi_1 and
325 | Phi_2 will easily follow. $)
326 |
327 | $( Weak alpha-equivalence $)
328 |
329 | $( Before describing the claims C(Psi), I need to introduce the notion
330 | of weak alpha-equivalence. Let Psi_1 and Psi_2 be two well-formed
331 | formulas of PA.
332 |
333 | Say Psi_1 is s_1 ... s_m and Psi_2 is t_1 ... t_n.
334 |
335 | Then Psi_1 and Psi_2 are weakly alpha equivalent iff:
336 |
337 | 1) m = n;
338 |
339 | 2) Let 1 <= i <= n. Then s_i is a constant iff t_i is; in that case,
340 | they are the *same* constant.
341 |
342 | 3) Let 1 <= i <= n. Suppose that s_i is a variable. [So t_i is a
343 | variable as well.] Then s_i is free in Psi_1 iff t_i is free in
344 | Psi_2.
345 |
346 | 3a) Let 1 <= i < j <= n. Suppose that s_i and s_j are variables free
347 | in Psi_1. [It follows that t_i and t_j are free variables in Psi_2.]
348 | Then s_i = s_j iff t_i = t_j.
349 |
350 | 4) Let 1 <= i <= n. Suppose that s_i is a variable that is bound in
351 | Psi_1. [It follows that t_i is a variable that is bound in Psi_2.]
352 | Let s_j be the quantifier that binds s_i. Then t_j is the
353 | quantifier that binds t_i.
354 |
355 | [This ends the definition of weak alpha-equivalence.] $)
356 |
357 | $( I need a pedantic fact:
358 |
359 | Proposition 2.1. Let Phi_1 = s_1,..., s_m and Phi_2 = t_1...t_m be
360 | as above. Let 1 <= i <= j <= m. Then s_i ... s_j is a term
361 | [formula] iff t_i ... t_j is.
362 |
363 | The proof is by induction on j - i and is straightforward. [It
364 | splits into cases according to what s_i is.] $)
365 |
366 | $( The following explains the importance of "weak alpha equivalence":
367 |
368 | Proposition 2.2.
369 | Let Psi_1 be a subformula of Phi_1, and Psi_2 the corresponding
370 | subformula of Phi_2. (Cf. the "pedantic fact" just above.) Then
371 | Psi_1 and Psi_2 are weakly alpha equivalent.
372 |
373 | Only clause 3a) of the definition of weak alpha equivalence
374 | requires discussion:
375 |
376 | Say Psi_1 occupies positions i ... j of Phi_1. Let i <= a < b <= j
377 | and let s_a and s_b be the same variable x. We suppose that s_a and
378 | s_b are free in Psi_1. We shall show that t_a = t_b. {This will
379 | prove one direction of the iff; the other direction is proved
380 | similarly.}
381 |
382 | If s_a and s_b are both free in Phi_1 then our claim is clear since
383 | Phi_1 and Phi_2 are alpha equivalent. If not, let Theta_1 be the
384 | smallest subformula of Phi_1 in which one of s_a and s_b is
385 | bound. Then both s_a and s_b are bound by the quantifer that begins
386 | Theta_1.
387 |
388 | Let Theta_2 be the subformula of Phi_2 that corresponds to
389 | Theta_1. Using the alpha equivalence of Phi_1 and Phi_2 we see that
390 | both t_a and t_b are bound by the quantifer that begins
391 | Theta_2. Hence t_a = t_b.
392 |
393 | $)
394 |
395 | $( We are now able to begin the definition of C(Psi_1) for Psi_1 a
396 | subformula of Phi_1. It will have the form
397 |
398 | implies H(Psi_1)
399 | iff Psi_1 Psi_2
400 |
401 | where Psi_2 is the subformula of Phi_2 that corresponds to Psi_1.
402 |
403 | It remains to describe H(Psi_1):
404 |
405 | Let w be a variable that does not appear [free or bound] in either
406 | Phi_1 or Phi_2. Let x_1 ... x_r be the free variables appearing in
407 | Psi_1 [listed without repetitions]. Because Psi_1 is weakly alpha
408 | equivalent to Psi_2, we can define a bijection between the free
409 | variables of Psi_1 and those of Psi_2 thus. If x_i appears freely in
410 | position j of Psi_1 then the corresponding free variable of Psi_2,
411 | say y_i, appears in position j of Psi_2.
412 |
413 | H(Psi_1) is the conjunction of the following equalities:
414 |
415 | 1) = w w ;
416 |
417 | 2) = x_i y_i (for i = 1 ... r).
418 |
419 | This completes our description of C(Psi_1). $)
420 |
421 | $( Consider first C(Phi_1). Because Phi_1 is alpha equivalent to
422 | Phi_2, H(Phi_1) is the conjunction of equalities of the form = a a .
423 | Hence Metamath can prove H(Phi_1) and can see that C(Phi_1) is
424 | equivalent to the equivalence:
425 |
426 | iff Phi_1 Phi_2
427 | $)
428 |
429 | $( So it will be sufficient to see that Metamath [after enrichment with
430 | some additional correct axioms] can prove C(Psi_1) for every
431 | subformula Psi_1 of Phi_1. The proof of this proceeds by induction on
432 | the length of Psi_1.
433 |
434 | If Psi_1 is atomic, our claim is easily proved using the equality
435 | axioms.
436 |
437 | The cases when Psi_1 is built up from smaller formulas using propositional
438 | connectives are easily handled since Metamath knows propositional
439 | logic.
440 |
441 | $)
442 |
443 | $( It remains to consider the case when Psi_1 has the form Q x Chi_1
444 | where Q is a quantifier.
445 |
446 | It is clear that Psi_2 has the form Q y Chi_2 [where Chi_2 is the
447 | subformula of Phi_2 that corresponds to Chi_1]. We will consider two
448 | cases;
449 |
450 | Case A: x = y;
451 |
452 | Case B: x != y. $)
453 |
454 | $( To handle Case A we adjoin the following axiom [which the reader
455 | should verify is correct]. $)
456 |
457 | ${ $d phi x $.
458 | alpha_hyp1 $e |- implies phi
459 | iff psi chi $.
460 | alpha_1 $a |- implies phi
461 | iff quant x psi
462 | quant x chi $. $}
463 |
464 | $( We apply this axiom with H(Psi_1) in the role of phi and Q in the
465 | role of quant. Chi_1 is in the role of psi and Chi_2 is in the role of
466 | chi.
467 |
468 | To see that the needed instance of alpha_hyp1 holds, note that
469 | H(Chi_1) is either H(Psi_1) [up to a possible rearrangement of
470 | conjuncts] or the conjunction of H(Psi_1) with the conjunct
471 | = x x
472 |
473 | So our needed instance follows from C(Chi_1), equality axioms and
474 | propositional logic $)
475 |
476 | $( We turn to case B. It is worthwhile to remind the reader that Phi_2
477 | has been chosen so that no bound variable of Phi_2 appears either free
478 | or bound in Phi_1.
479 |
480 | Proposition 2.3. y does not appear [free or bound] in Psi_1. x does
481 | not appear [free or bound] in Psi_2.
482 |
483 | Proof: y appears bound in Psi_2. Hence it doesn't even appear [free or
484 | bound] in Phi_1.
485 |
486 | Suppose that x appears in Psi_2. Then this appearence must be free in
487 | Phi_2. {Otherwise, x would not appear in Phi_1 but it is the second
488 | symbol of Psi_1.} So at the same spot in Psi_1 x also appears, and
489 | this occurrence is free in Phi_1. {This follows from the fact that
490 | Phi_1 and Phi_2 are alpha equivalent.} But clearly this occurrence of
491 | x in Psi_1 will be bound by the quantifier that starts
492 | Psi_1. Contradiction! $)
493 |
494 | $( Proposition 2.3 has the following immediate consequence:
495 |
496 | Proposition 2.4: Neither of the variables x or y occurs in H(Psi_1).
497 |
498 | Also it is easy to check that [up to propositional logic]
499 | H(Chi_1) is either H(Psi_1) or the conjunction of H(Psi_1)
500 | with
501 | = x y
502 |
503 | It follows that from C(Chi_1) one can deduce [using propositonal
504 | logic] the following:
505 |
506 | (A) implies H(Psi_1)
507 | implies = x y
508 | iff Chi_1 Chi_2 $)
509 |
510 | $( Next we introduce the following Metamath axiom [which the reader
511 | should verify is correct] $)
512 |
513 | ${ $d phi x $.
514 |
515 | alpha_hyp2 $e |- implies phi chi $.
516 | alpha_2 $a |- implies phi forall x chi $.
517 | $}
518 |
519 | $( Using this axiom we can deduce from (A) and Proposition 2.4
520 | the following:
521 |
522 | (B) implies H(Psi_1)
523 | forall x forall y implies = x y
524 | iff Chi_1 Chi_2
525 | $)
526 |
527 | $( We need to introduce another axiom [which the reader should verify
528 | is correct] $)
529 |
530 | ${ $d phi y $.
531 | $d psi x $.
532 | $d x y $.
533 | alpha_3 $a |- implies forall x forall y implies = x y
534 | iff phi psi
535 | iff quant x phi quant y psi $.
536 | $}
537 |
538 | $( From this axiom, (B) and Proposition 2.3 we easily deduce:
539 |
540 | (C) implies H(Psi_1)
541 | iff Psi_1 Psi_2
542 |
543 | which is C(Psi_1) $)
544 |
545 | $( The following lemma should now be clear to the reader:
546 |
547 | Lemma 2. Let Phi and Phi* be alpha equivalent formulas of PA. Then
548 | using the axioms so far introduced, we can prove in Metamath the
549 | sequence
550 |
551 | |- iff Phi_1 Phi_2
552 |
553 | from the disjointness assumption that all the distinct variables
554 | appearing in Phi_1 or Phi_2 are asserted to be distinct in a $d
555 | assumption. $)
556 |
557 | $(
558 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
559 | Axioms and inference rules of predicate logic
560 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
561 | $)
562 |
563 | $( Our next task is to prove the rule of inference and the axiom
564 | associated to the "forall" quantifier. $)
565 |
566 | $( Let's start with the rule of inference. We have to show that if
567 |
568 | |- implies phi chi
569 |
570 | and phi does not contain x free then also
571 |
572 | |- implies phi forall x chi.
573 |
574 | But this is easy. In view of what we have just shown, it is ok to
575 | replace phi by an alpha-equivalent formula that does not contain x
576 | at all. {In both our hypothesis and conclusion.}
577 |
578 | But then we just need to invoke the axiom alpha_2. $)
579 |
580 | $( We now turn to the axiom of "forall elimination". To state it we
581 | introduce the familiar notion of substituting a term for the free
582 | occurrences of a variable. So let phi be a formula, x a variable and t
583 | a term. By phi[t/x] we mean the formula obtained by simultaneously
584 | replacing each free occurrence of x in phi by a copy of the term t. {A
585 | more rigorous definition would proceed by induction on the structure
586 | of phi.}
587 |
588 | We say that t is substitutable for x at the free occurrence of x in
589 | phi [or just "substitutable" if we are being terse] if no variable
590 | occuring in t falls under the scope of any quantifer of
591 | phi. {Again, I am presuming this notion known; otherwise, I'd be
592 | more careful with this definition.}
593 |
594 | The final group of axioms of predicate calculus that we need to
595 | derive have the following form:
596 |
597 | (*) implies
598 | forall x phi
599 | phi[t/x]
600 |
601 | **where** t is substitutable for x in phi.
602 |
603 | Our next step is to show that it suffices to prove the following
604 | special case of this axiom. phi x and t satisfy the following three
605 | conditions:
606 |
607 |
608 | (1) The variable x does not appear in the term t.
609 |
610 | (2) No bound variable of phi appears in t.
611 |
612 | (3) The variable x does not appear bound in phi.
613 |
614 | We can see this as follows. We can clearly find a formula
615 | forall y psi
616 | which is alpha equivalent to forall x phi such that:
617 | (1') The variable y does not appear in the term t;
618 | (2') No bound variable of psi appears in t;
619 | (3') The variable y does not appear bound in psi.
620 |
621 | Using the fact that t is substitutable for x in phi we easily see that
622 | phi[t/x] is alpha equivalent to psi[t/y]. It follows that (*) is
623 | alpha-equivalent to:
624 | (**) implies
625 | forall y psi
626 | psi[t/y]
627 |
628 | Hence Metamath can prove the equivalence of (*) and (**). But in view
629 | of (1') through (3'), the instance (**) of for all elimination meets
630 | our additional requirements (1) through (3).
631 |
632 | In the remainder of our discussion we shall assume then that phi, x
633 | and t meet the requirements (1) through (3). Note that it follows from
634 | (2) that t is substitutable for x in phi.
635 |
636 | [N.B. We cannot assume that the variables appearing in t do not appear
637 | in phi.]
638 |
639 | Here is the key idea of our approach: The formula phi[t/x] (under the
640 | hypotheses (1) -- (3) just given) is equivalent to:
641 |
642 | forall x implies
643 | = x t
644 | phi
645 |
646 | $)
647 |
648 | $( We start by adding the following [correct!] axiom $)
649 |
650 | ${ $d x t $.
651 | all_elim $a |- implies
652 | forall x phi
653 | forall x implies
654 | = x t
655 | phi $.
656 | $}
657 |
658 | $( Using this axiom we can reduce our proof that Metamath proves all
659 | instances of "all elimination" to the following lemma:
660 |
661 | Lemma 3. Let t be a term of PA and phi a formula of PA. We assume:
662 | 1) The variable x does not occur in t;
663 | 2) No bound variable of phi appears in t.
664 | 3) The variable x does not occur bound in phi.
665 |
666 | Then [after adding finitely many additional correct axioms whose
667 | choice does not depend on phi] we can prove in Metamath:
668 |
669 | |- iff
670 | forall x implies
671 | = x t
672 | phi
673 | phi[t/x]
674 |
675 | $)
676 |
677 | $( We shall need a preliminary result:
678 |
679 | Proposition 3.1 Let phi t and x obey our standing hypotheses 1) --
680 | 3). Let psi be a subformula of phi.
681 |
682 | Then [after adding finitely many additional correct axioms whose
683 | choice does not depend on phi] we can prove in Metamath:
684 |
685 | |- implies = x t
686 | iff psi psi[t/x]
687 |
688 | The construction of such proofs [like many previous arguments] is by
689 | induction on the tree of subformulas of phi. $)
690 |
691 | $( The first case is when psi is atomic. This case is easily handled
692 | using the equality axioms.
693 |
694 | The second case is when the principal connective of psi is a
695 | propositional connective. This case follows easily using propositional
696 | logic from our inductive hypotheses concerning the subformulas of psi.
697 |
698 | $)
699 |
700 | $( The final case is when the principal connective of psi is a
701 | quantifier. This case is handled using the following axiom: $)
702 |
703 | ${ $d x y $.
704 | $d y t $.
705 | all_elim_hyp2 $e |- implies = x t
706 | iff phi chi $.
707 | all_elim2 $a |- implies = x t
708 | iff quant y phi
709 | quant y chi $.
710 | $}
711 |
712 | $( The proof of Proposition 3.1 is now complete. We apply it to phi
713 | and get that Metamath proves:
714 | |- implies = x t
715 | iff phi phi[t/x]
716 |
717 | Here phi and t stand for the particular wff and term of t under
718 | discussion and are not literal metavariables of Metamath.
719 |
720 | We also know at this point that Metamath proves:
721 |
722 | |- implies forall x phi
723 | forall x implies = x t
724 | phi
725 |
726 | We would be done if we could prove in Metamath:
727 |
728 | |- implies forall x implies = x t
729 | phi
730 | phi[t/x]
731 |
732 | But this will follow easily from the next axiom [which is inelegant
733 | but correct].
734 |
735 | $)
736 |
737 | ${
738 | $d x chi $.
739 | $d x t $.
740 |
741 | all_elim3_hyp1 $e |- implies = x t
742 | iff phi chi $.
743 | all_elim3 $a |- implies forall x implies = x t
744 | phi
745 | chi $. $}
746 |
747 | $( This completes our discussion of "forall-elimination". $)
748 | $( It is time to introduce the definition of the
749 | "exists" quantifier $)
750 |
751 | exists_def $a |- iff
752 | exists x phi
753 | not forall x not phi $.
754 |
755 | $( Of course, the axiom and rule of inference for "exists" follow from
756 | this definition and the corresponding inference rule or axiom scheme
757 | for "forall". $)
758 |
759 | $(
760 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
761 | The non-logical axioms of Peano Arithmetic
762 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
763 | $)
764 |
765 | $( At this point, we know that Metamath can prove any logically valid
766 | wff of PA. It remains to add the axioms of PA. $)
767 |
768 | $( First we give the particular axioms of PA. Then we discuss the
769 | induction scheme $)
770 |
771 | pa_ax1 $a |- not = 0 S x $.
772 | pa_ax2 $a |- implies = S x S y
773 | = x y $.
774 | pa_ax3 $a |- = x
775 | + x 0 $.
776 | pa_ax4 $a |- = S + x y
777 | + x S y $.
778 | pa_ax5 $a |- = 0
779 | * x 0 $.
780 | pa_ax6 $a |- = + * x y x
781 | * x S y $.
782 | pa_ax7 $a |- iff
783 | < x y
784 | exists z = y + x S z $.
785 |
786 | $( It suffices to give the induction axiom for the case when phi does
787 | not contain x free. For the usual form of the axiom follows from this
788 | special case by first order logic. $)
789 |
790 | ${
791 | $d phi x $.
792 | $d x y $.
793 | induction $a
794 | |- implies
795 | and forall y implies = y 0 phi
796 | forall x implies forall y implies = y x phi
797 | forall y implies = y S x phi
798 | forall x forall y implies = y x phi $.
799 | $}
800 |
801 | $(
802 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
803 | Discussion of correctness
804 | #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
805 | $)
806 |
807 | $(
808 | Let's agree that when I say "Metamath proves PHI" I mean "Metamath"
809 | enriched with all the preceding axioms in this document.
810 |
811 | The issue is the following. For what formulas Phi is there a proof in
812 | Metamath from no $e type assumptions of the sequencce
813 | |- Phi.
814 |
815 | (Recall that I am identifying the well-formed formulas of Peano with
816 | certain of the Metamath strings of symbols. This is done by
817 | identifying the object variables of our language with the
818 | metavariables of type var.)
819 |
820 | The claim is that these are precisely those Phi which are theorems of
821 | the usual formulation of Peano Arithmetic.
822 |
823 | One direction should be clear by this point. We have developed the
824 | first order predicate calculus within Metamath and included the usual
825 | axioms of Peano arithmetic [or equivalents]. So any theorem of Peano
826 | Arithmetic [as usually formulated] can be proved in Metamath.
827 |
828 | To go in the other direction, suppose that there is a proof in
829 | Metamath of |- Phi. So the final line of the proof contains only
830 | variables of type var. But there might well be variables of other
831 | kinds in the body of the proof. For example, there might be a variable
832 | phi of kind wff.
833 |
834 | The critical such variables are those that appear in lines of the
835 | proof beginning with |-. What we do is replace such variables (of
836 | kind different than var) [one by one] by sequences of constants of the
837 | same type. (So phi might be replaced by the three symbol string "= 0
838 | 0".) It is not hard to see that after this substitution the result can
839 | be massaged to a correct proof. There are two points to notice.
840 |
841 | a) Since the string by which we replaced the variable contains no
842 | variables itself the process converges and no disjointness
843 | conditions [$d restrictions] are violated.
844 |
845 | b) We may have to add a trivial few lines to prove the "type
846 | assertion". In our example, the line "wff phi" will be replaced
847 | by the line "wff = 0 0". This line is no longer immediate but
848 | must be proved by a four line argument.
849 |
850 | At the end, there results a proof where all the lines that begin with
851 | "|-" contain only variables of type var. But now our correctness
852 | assumptions allow us to verify step by step that each such line is a
853 | theorem of Peano arithmetic.
854 | $)
855 |
856 | $( For Emacs $)
857 | $( Local Variables: $)
858 | $( eval:'(show-paren-mode t) $)
859 | $( End: $)
860 |
--------------------------------------------------------------------------------
/metamath/miu2.mm:
--------------------------------------------------------------------------------
1 | $c M I U |- wff $.
2 | $v x y $.
3 |
4 | wx $f wff x $.
5 | wy $f wff y $.
6 |
7 | we $a wff $.
8 | wM $a wff x M $.
9 | wI $a wff x I $.
10 | wU $a wff x U $.
11 |
12 | ax $a |- M I $.
13 |
14 | ${
15 | Ia $e |- x I $.
16 | I_ $a |- x I U $.
17 | $}
18 |
19 | ${
20 | IIa $e |- M x $.
21 | II $a |- M x x $.
22 | $}
23 |
24 | ${
25 | IIIa $e |- x I I I y $.
26 | III $a |- x U y $.
27 | $}
28 |
29 | ${
30 | IVa $e |- x U U y $.
31 | IV $a |- x y $.
32 | $}
33 |
34 | trivial $p |- M I $=
35 | ax
36 | $.
37 |
38 | lesstrivial $p |- M I I $=
39 | we wI ax II
40 | $.
41 |
42 | theorem1 $p |- M U I I U $=
43 | we wM wU wI we wI wU
44 | we wU wI wU
45 | we wM we wI wU
46 | we wM wI wI wI
47 | we wI wI
48 | we wI ax II
49 | II
50 | I_
51 | III
52 | II
53 | IV
54 | $.
55 |
56 |
--------------------------------------------------------------------------------
/metamath/mm.g:
--------------------------------------------------------------------------------
1 | start : outermost_scope_stmt*
2 | outermost_scope_stmt : include_stmt | constant_stmt | stmt
3 |
4 | include_stmt : "$[" MATH_SYMBOL "$]"
5 | constant_stmt : "$c" constant+ "$."
6 |
7 | stmt : block | variable_stmt | disjoint_stmt | hypothesis_stmt | assert_stmt
8 | block : "${" stmt* "$}"
9 |
10 | variable_stmt : "$v" variable+ "$."
11 | disjoint_stmt : "$d" variable variable variable* "$."
12 | hypothesis_stmt : floating_stmt | essential_stmt
13 |
14 | floating_stmt : LABEL "$f" typecode variable "$."
15 | essential_stmt : LABEL "$e" typecode MATH_SYMBOL* "$."
16 |
17 | assert_stmt : axiom_stmt | provable_stmt
18 |
19 | axiom_stmt : LABEL "$a" typecode MATH_SYMBOL* "$."
20 | provable_stmt : LABEL "$p" typecode MATH_SYMBOL* "$=" proof "$."
21 |
22 | proof : uncompressed_proof | compressed_proof
23 | uncompressed_proof : (LABEL | "?")+
24 | compressed_proof : "(" LABEL* ")" COMPRESSED_PROOF_BLOCK+
25 |
26 | typecode : constant
27 |
28 | constant : MATH_SYMBOL
29 | variable : MATH_SYMBOL
30 |
31 | LCHAR : ("a".."z") | ("A".."Z") | ("0".."9") | "." | "-" | "_"
32 | CHAR : LCHAR | "'" | "|" | "+" | "*" | "=" | "<" | ">" | "(" | ")" | ":" | "," | "\\" | "[" | "]" | "/" | "~" | "!" | "?" | "@" | "&" | "{" | "}" | "^" | "`" | "\"" | ";" | "#"
33 |
34 | LABEL : LCHAR+
35 | MATH_SYMBOL : CHAR+
36 | COMPRESSED_PROOF_BLOCK : (("A".."Z") | "?")+
37 |
38 | COMMENT : "$(" /(.|\n)+?/ "$)"
39 | WHITESPACE : (" " | "\n" | "\t" | "\r")+
40 |
41 | %ignore WHITESPACE
42 | %ignore COMMENT
43 |
44 |
--------------------------------------------------------------------------------
/metamath/realtwoplustwo.mm:
--------------------------------------------------------------------------------
1 | $[ twoplustwo.mm $]
2 |
3 | $(
4 | We're going to replicate most of the work done for one_ne_zero
5 | for the other axioms, so that we can have terms instead of vars.
6 | $)
7 |
8 | ${
9 | $( phi |- A. x phi $)
10 | gen.1 $e |- phi $.
11 | $( This is an axiom in set.mm, but here it has a (somewhat convoluted) proof. $)
12 | gen $p |- forall x phi $=
13 | ( quant_all tzero binpred_equals wff_quant eq-refl eq-sym ax-mp logbinopiff
14 | wff_atom alpha_2 wff_logbinop logbinopimplies ax-1 bi3 alpha_1 bi1 ) ADEEFL
15 | ZGZADBGZTUAEHZATTEEIMJKUBUANZOUBUANTUDUCADTTBKBTNZOUETNOTBNZUETUFUCTBPJOBTN
16 | ZOUEUFNBUGCBTPJTBQJJUETPJRJUAUBSJJ $.
17 | $}
18 |
19 | ${
20 | $d x psi $. $d x t $.
21 | $( x = t -> (A <-> B), A |- B $)
22 | var_to_term.1 $e |- implies = x t iff phi psi $.
23 | var_to_term.2 $e |- phi $.
24 | $(
25 | This is the main theorem needed for the var/term transformations.
26 | In set.mm it's called vtocl for "var to class", but here it's more
27 | like var to term.
28 | $)
29 | var_to_term $p |- psi $=
30 | ( quant_all logbinopimplies tvar binpred_equals wff_atom wff_quant all_elim
31 | wff_logbinop gen ax-mp all_elim3 ) BGHCBIAJKNLZDBGCLRBCFOABCMPABCDEQP $.
32 | $}
33 |
34 | $( Oops, ran out of variables. let's make some new wffs. $)
35 | $v psi2 chi2 $.
36 | wpsi2 $f wff psi2 $.
37 | wchi2 $f wff chi2 $.
38 |
39 | biid $p |- iff phi phi $=
40 | ( logbinopimplies wff_logbinop logbinopiff id bi3 ax-mp ) BAACZDAACZAEZHBIHC
41 | JAAFGG $.
42 |
43 | biidd $p |- implies phi iff psi psi $=
44 | ( logbinopiff wff_logbinop logbinopimplies biid ax-1 ax-mp ) CBBDZEIADBFIAGH
45 | $.
46 |
47 | eqidd $p |- implies phi = t t $=
48 | ( binpred_equals wff_atom logbinopimplies wff_logbinop eq-refl ax-1 ax-mp )
49 | AACDZEJBFAGJBHI $.
50 |
51 | eqeq1 $p |- implies = s t iff = s u = t u $=
52 | ( wff_atom logbinopimplies wff_logbinop logbinopiff eq-trans logbinopand
53 | andL binpred_equals exp eq-sym syl andR andId bi3 mpd ) ABKDZEACKDZBCKDZFZGUA
54 | TFZSUATABCHLSEUATFEUCUBFSTUAITSFZITBAKDZFUAUDUETUDSUESTJABMNSTOPBACHNLTUAQNR
55 | $.
56 |
57 | ${
58 | $( A -> (B1 <-> B2), A -> (C1 <-> C2) |- A -> ((B1 -> C1) <-> (B2 -> C2)) $)
59 | imbid.1 $e |- implies phi iff psi psi2 $.
60 | imbid.2 $e |- implies phi iff chi chi2 $.
61 | imbid $p |- implies phi iff implies psi chi implies psi2 chi2 $=
62 | ( logbinopimplies wff_logbinop logbinopiff bi1 syl imim2 com12 bi2 mpd bi3
63 | ) AHHCBIZHEDIZIZJSRIZAHHEBIZSIZTAHDBIZUCAJDBIZUDFBDKLSUDUBBDEMNLAHRUBIZHTUC
64 | IAHCEIZUFAJECIZUGGCEOLBECMLSUBRMLPAHSRIZHUATIAHHCDIZRIZUIAHBDIZUKAUEULFBDOL
65 | RULUJDBCMNLAHSUJIZHUIUKIAHECIZUMAUHUNGCEKLDCEMLRUJSMLPRSQLP $.
66 | $}
67 |
68 | ${
69 | $( A -> (B <-> C), A -> (C <-> D) |- A -> (B <-> D) $)
70 | bitrd.1 $e |- implies phi iff psi psi2 $.
71 | bitrd.2 $e |- implies phi iff psi2 chi $.
72 | bitrd $p |- implies phi iff psi chi $=
73 | ( logbinopimplies wff_logbinop logbinopiff bi2 syl imim2 mpd bi1 bi3 ) AGBC
74 | HZICBHZAGDCHZPAICDHZRFDCJKAGBDHZGPRHAIDBHZTEBDJKCDBLKMAGCBHZGQPHAGDBHZUBAUA
75 | UCEBDNKAGCDHZGUBUCHASUDFDCNKBDCLKMBCOKM $.
76 | $}
77 |
78 | ${
79 | $( A -> (B <-> C) |- A -> (C <-> B) $)
80 | bicomd.1 $e |- implies phi iff psi chi $.
81 | bicomd $p |- implies phi iff chi psi $=
82 | ( logbinopiff wff_logbinop logbinopimplies bi1 bi2 bi3 syl mpd ) AECBFZEBCF
83 | ZDMGCBFZNBCHMGBCFGNOFBCICBJKLK $.
84 | $}
85 |
86 | ${
87 | $( A -> (B1 <-> B2), A -> (C1 <-> C2) |- A -> ((B1 <-> C1) <-> (B2 <-> C2)) $)
88 | bibid.1 $e |- implies phi iff psi psi2 $.
89 | bibid.2 $e |- implies phi iff chi chi2 $.
90 | bibid $p |- implies phi iff iff psi chi iff psi2 chi2 $=
91 | ( logbinopimplies logbinopiff wff_logbinop logbinopand andL syl andR bicomd
92 | bitrd exp bi3 mpd ) AHICBJZIEDJZJZIUATJZAUATKUAAJZBCDUDAIDBJZAUALZFMUDDCEAU
93 | ANUDCEUDAIECJZUFGMOPPQAHUATJHUCUBJATUAKTAJZDEBUHBDUHAUEATLZFMOUHBECATNUHAUG
94 | UIGMPPQTUARMS $.
95 | $}
96 |
97 | ${
98 | $d x y z s $. $d x y z t $. $d x y u $.
99 | $( 0 != S t $)
100 | pa_ax1_term $p |- not = 0 S t $=
101 | ( tzero tsucc binpred_equals wff_atom wff_not logbinopiff wff_logbinop
102 | eq-suc varx tvar eqeq2 syl notbi pa_ax1 var_to_term ) AJBJKZCZDEZFZBACZDEZFZQ
103 | ADEZGUBSHZGUCTHUDRUADEUEQAIRUABLMSUBNMJOP $.
104 |
105 | $( S s = S t -> s = t $)
106 | pa_ax2_term $p |- implies = S s S t = s t $=
107 | ( vary logbinopimplies binpred_equals wff_atom tsucc wff_logbinop
108 | logbinopiff varx tvar eq-suc eqeq2 syl imbid eqeq1 pa_ax2 var_to_term ) BCDAC
109 | KZEFZAGZSGZEFZHZDABEFZUABGZEFZHSBEFZUCTUGUEUHUBUFEFIUGUCHSBLUBUFUAMNSBAMOAJDJ
110 | KZSEFZUIGZUBEFZHUDUIAEFZULUJUCTUMUKUAEFIUCULHUIALUKUAUBPNUIASPOJCQRR $.
111 |
112 | $( s + 0 = s $)
113 | pa_ax3_term $p |- = + s 0 s $=
114 | ( varx tzero binop_plus tbinop binpred_equals wff_atom tvar eqeq1
115 | logbinopiff wff_logbinop logbinopand id logbinopimplies eq-refl ax-1 ax-mp
116 | andId eq-binop syl eqeq2 bitrd pa_ax3 var_to_term eq-sym ) AACDEZFGZUFAFGABBH
117 | ZUHCDEZFGZUGUHAFGZUJUGAUIFGZUHAUIIUKUIUFFGZJUGULKUKLCCFGZUKKUMUKUKUNUKMUNNUNU
118 | KKCOUNUKPQRUHACCDSTUIUFAUATUBBUCUDAUFUEQ $.
119 |
120 | $( s + S t = S (s + t) $)
121 | pa_ax4_term $p |- = + s S t S + s t $=
122 | ( vary varx binop_plus tbinop tsucc binpred_equals wff_atom tvar
123 | wff_logbinop logbinopiff logbinopand eqidd id andId eq-binop syl eq-suc eqeq1
124 | eqeq2 pa_ax4 bitrd var_to_term eq-sym ax-mp ) ABEFZGZABGZEFZHIZUJUHHIBCACJZEF
125 | ZGZAULGZEFZHIZUKULBHIZUQUKUHUPHIZURUNUHHIZLUSUQKURUMUGHIZUTURMURAAHIZKVAURVBU
126 | RAURNZUROPAAULBEQRUMUGSRUNUHUPTRURUPUJHIZLUKUSKURMUOUIHIZVBKVDURVBVEVCULBSPAA
127 | UOUIEQRUPUJUHUARUCADDJZULEFZGZVFUOEFZHIZUQVFAHIZVJUQUNVIHIZVKVHUNHIZLVLVJKVKV
128 | GUMHIZVMVKMULULHIZVKKVNVKVKVOVKOZULVKNPVFAULULEQRVGUMSRVHUNVITRVKVIUPHIZLUQVL
129 | KVKMUOUOHIZVKKVQVKVKVRVPUOVKNPVFAUOUOEQRVIUPUNUARUCDCUBUDUDUHUJUEUF $.
130 |
131 | $( s * 0 = 0 $)
132 | pa_ax5_term $p |- = * t 0 0 $=
133 | ( varx tzero binop_times binpred_equals wff_atom tvar logbinopiff
134 | logbinopand tbinop wff_logbinop eqidd andId eq-binop syl eqeq2 pa_ax5
135 | var_to_term eq-sym id ax-mp ) CACDJZEFZUBCEFABCBGZCDJZEFZUCUDAEFZUEUBEFZHUCUF
136 | KUGICCEFZUGKUHUGUGUIUGTCUGLMUDACCDNOUEUBCPOBQRCUBSUA $.
137 |
138 | $( s * S t = s * t + s $)
139 | pa_ax6_term $p |- = * s S t + * s t s $=
140 | ( vary varx binop_times tbinop binop_plus binpred_equals wff_atom
141 | logbinopiff tsucc tvar wff_logbinop logbinopand eqidd id andId eq-binop syl
142 | eqeq1 eq-suc eqeq2 bitrd pa_ax6 var_to_term eq-sym ax-mp ) ABEFZAGFZABKZEFZHI
143 | ZUKUIHIBCACLZEFZAGFZAUMKZEFZHIZULUMBHIZURULUIUQHIZUSUOUIHIZJUTURMUSNAAHIZUNUH
144 | HIZMVAUSVCVBUSNUSVBMVCUSVBUSAUSOZUSPQAAUMBERSVDQUNUHAAGRSUOUIUQTSUSUQUKHIZJUL
145 | UTMUSNUPUJHIZVBMVEUSVBVFVDUMBUAQAAUPUJERSUQUKUIUBSUCADDLZUMEFZVGGFZVGUPEFZHIZ
146 | URVGAHIZVKURUOVJHIZVLVIUOHIZJVMVKMVLNVLVHUNHIZMVNVLVOVLVLNUMUMHIZVLMVOVLVLVPV
147 | LPZUMVLOQVGAUMUMERSVQQVHUNVGAGRSVIUOVJTSVLVJUQHIZJURVMMVLNUPUPHIZVLMVRVLVLVSV
148 | QUPVLOQVGAUPUPERSVJUQUOUBSUCDCUDUEUEUIUKUFUG $.
149 |
150 | $( s < t <-> (E. x, t = s + S x) $)
151 | pa_ax7_term $p |- iff < s t exists x = t + s S x $=
152 | ( varz vary logbinopiff quant_ex binop_plus binpred_equals wff_atom
153 | wff_quant tvar tbinop binpred_less_than wff_logbinop logbinopand eqidd id
154 | andId syl tsucc eq-congr eqeq1 alpha_1 bibid eq-binop eqeq2 pa_ax7
155 | var_to_term ) BDFCGDLZACLUAZHMZIJZKZAUJNJZOZFCGBULIJZKZABNJZOUJBIJZUOUNUSURUT
156 | PUTAAIJZOFUSUOOUTVAUTAUTQUTRSAAUJBNUBTCGUTUMUQUJBULUCUDUEAEFCGUJELZUKHMZIJZKZ
157 | VBUJNJZOUPVBAIJZVFVEUOUNVGPUJUJIJZVGOFUOVFOVGVGVHVGRZUJVGQSVBAUJUJNUBTCGVGVDU
158 | MVGVCULIJZFUMVDOVGPUKUKIJZVGOVJVGVGVKVIUKVGQSVBAUKUKHUFTVCULUJUGTUDUEEDCUHUIU
159 | I $.
160 | $}
161 |
162 | ${
163 | $( A -> (B1 <-> B2), A -> (C1 <-> C2) |- A -> ((B1 <-> C1) <-> (B2 <-> C2)) $)
164 | eqtri.1 $e |- = s t $.
165 | eqtri.2 $e |- = t u $.
166 | eqtri $p |- = s u $=
167 | ( logbinopand binpred_equals wff_atom wff_logbinop logbinopimplies eq-trans
168 | andI ax-mp ) FBCGHZABGHZIZACGHNPEOJPNIDONLMMABCKM $.
169 | $}
170 |
171 | 2p2e4 $p |- = + S S 0 S S 0 S S S S 0 $=
172 | ( tzero tsucc binop_plus tbinop pa_ax4_term binpred_equals pa_ax3_term
173 | eq-suc wff_atom ax-mp eqtri ) ABZBZMCDMLCDZBZMBZBZMLENPFIOQFINMACDZBZPMAERMFI
174 | SPFIMGRMHJKNPHJK $.
175 |
--------------------------------------------------------------------------------
/metamath/simple.mm:
--------------------------------------------------------------------------------
1 | $c ( ) -> wff $.
2 | $v p q r s $.
3 | wp $f wff p $.
4 | wq $f wff q $.
5 | wr $f wff r $.
6 | ws $f wff s $.
7 | w2 $a wff ( p -> q ) $.
8 | wnew $p wff ( s -> ( r -> p ) ) $= ws wr wp w2 w2 $.
9 |
--------------------------------------------------------------------------------
/metamath/simple2.mm:
--------------------------------------------------------------------------------
1 | $v P Q R $.
2 | $c -> ( ) |- wff $.
3 |
4 | wp $f wff P $.
5 | wq $f wff Q $.
6 |
7 | maj $e |- ( P -> Q ) $.
8 | min $e |- P $.
9 | mp $a |- Q $.
10 |
11 |
--------------------------------------------------------------------------------
/metamath/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | git clone https://github.com/david-a-wheeler/metamath-test.git
3 | cd metamath-test/ && ./run-testsuite ../verify.py
4 |
5 |
--------------------------------------------------------------------------------
/metamath/twoplustwo.mm:
--------------------------------------------------------------------------------
1 | $[ lib/peano.mm $]
2 |
3 | $(
4 | Doing this sort of thing from the bottom on stream is an impressive undertaking.
5 | Unfortunately, there are a bunch of prerequisites needed to really get anywhere
6 | starting from just the axioms, and propositional logic is a big one. In order to
7 | have a good time using propositional logic, you need a library of ~200 basic
8 | theorems in propositional logic. I will not do this, but instead just prove a few
9 | requirements for the theorems of interest today.
10 |
11 | These proofs are primarily borrowed from peano.mm1, which were themselves borrowed
12 | from set.mm proofs. -Mario
13 | $)
14 |
15 | ${
16 | mpd.1 $e |- implies phi psi $.
17 | mpd.2 $e |- implies phi implies psi chi $.
18 | $( A -> B, A -> B -> C |- A -> C $)
19 | mpd $p |- implies phi chi $=
20 | ( logbinopimplies wff_logbinop ax-2 ax-mp ) FBAGZFCAGZDFFCBGAGFKJGEABCHII
21 | $.
22 | $}
23 |
24 | ${
25 | syl.1 $e |- implies phi psi $.
26 | syl.2 $e |- implies psi chi $.
27 | $( A -> B, B -> C |- A -> C $)
28 | syl $p |- implies phi chi $=
29 | ( logbinopimplies wff_logbinop ax-1 ax-mp mpd ) ABCDFCBGZFKAGEKAHIJ $.
30 | $}
31 |
32 | $( A -> A $)
33 | id $p |- implies phi phi $=
34 | ( logbinopimplies wff_logbinop ax-1 mpd ) ABAACZAAADAFDE $.
35 |
36 | $( !A -> A -> B $)
37 | absurd $p |- implies not phi implies phi psi $=
38 | ( wff_not logbinopimplies wff_logbinop ax-1 ax-3 syl ) ACZDIBCZEDBAEIJFBAGH
39 | $.
40 |
41 | ${
42 | com12.1 $e |- implies phi implies psi chi $.
43 | $( A -> B -> C |- B -> A -> C $)
44 | com12 $p |- implies psi implies phi chi $=
45 | ( logbinopimplies wff_logbinop ax-1 ax-2 ax-mp syl ) BEBAFZECAFZBAGEECBFAFE
46 | LKFDABCHIJ $.
47 | $}
48 |
49 | ${
50 | imidm.1 $e |- implies phi implies phi psi $.
51 | $( A -> A -> B |- A -> B $)
52 | imidm $p |- implies phi psi $=
53 | ( logbinopimplies wff_logbinop id com12 mpd ) ADBAEZBCIABIFGH $.
54 | $}
55 |
56 | $( (!A -> A) -> A $)
57 | contra $p |- implies implies not phi phi phi $=
58 | ( logbinopimplies wff_not wff_logbinop absurd ax-2 ax-mp ax-3 syl imidm ) BA
59 | ACZDZALBLCZKDZBALDBBMADKDBNLDAMEKAMFGALHIJ $.
60 |
61 | $( !!A -> A $)
62 | notnot2 $p |- implies not not phi phi $=
63 | ( wff_not logbinopimplies wff_logbinop absurd contra syl ) ABZBCAHDAHAEAFG
64 | $.
65 |
66 | $( (B -> C) -> (A -> B) -> (A -> C) $)
67 | imim2 $p |- implies implies psi chi
68 | implies implies phi psi
69 | implies phi chi $=
70 | ( logbinopimplies wff_logbinop ax-1 ax-2 syl ) DCBEZDIAEDDCAEDBAEEIAFABCGH
71 | $.
72 |
73 | $( (A -> !B) -> (B -> !A) $)
74 | con2 $p |- implies implies phi not psi
75 | implies psi not phi $=
76 | ( logbinopimplies wff_not wff_logbinop notnot2 imim2 com12 ax-mp ax-3 syl )
77 | CBDZAEZCLADZDZEZCNBECAOEZCPMEAFMQPOALGHINBJK $.
78 |
79 | $( A -> !!A $)
80 | notnot1 $p |- implies phi not not phi $=
81 | ( logbinopimplies wff_not wff_logbinop id con2 ax-mp ) BACZHDBHCADHEHAFG $.
82 |
83 | ${
84 | con1i.1 $e |- implies not phi psi $.
85 | $( !A -> B |- !B -> A $)
86 | con1i $p |- implies not psi phi $=
87 | ( logbinopimplies wff_not wff_logbinop notnot1 syl ax-3 ax-mp ) DBEZEZAEZFD
88 | AKFMBLCBGHAKIJ $.
89 | $}
90 |
91 | $( (A -> B) -> (!B -> !A) $)
92 | con3 $p |- implies implies phi psi
93 | implies not psi not phi $=
94 | ( logbinopimplies wff_logbinop wff_not notnot1 imim2 ax-mp con2 syl ) CBADZC
95 | BEZEZADZCAELDCMBDCNKDBFABMGHALIJ $.
96 |
97 | $( A /\ B -> A $)
98 | andL $p |- implies and phi psi phi $=
99 | ( logbinopand wff_logbinop logbinopimplies logbinopiff df-an bi1 ax-mp
100 | absurd wff_not con1i syl ) CBADZEBKZADZKZAFQNDEQNDABGNQHIAPAOJLM $.
101 |
102 | $( A /\ B -> B $)
103 | andR $p |- implies and phi psi psi $=
104 | ( logbinopand wff_logbinop logbinopimplies wff_not logbinopiff df-an bi1
105 | ax-1 ax-mp con1i syl ) CBADZEBFZADZFZBGQNDEQNDABHNQIKBPOAJLM $.
106 |
107 | $( A -> B -> A /\ B $)
108 | andI $p |- implies phi implies psi and phi psi $=
109 | ( logbinopimplies wff_not wff_logbinop logbinopand com12 con2 syl
110 | logbinopiff id df-an bi2 ax-mp imim2 ) ACCBDZAEZDZBEZCFBAEZBEZACPQESQAPQKGQBH
111 | ICTREZCUASEJRTEUBABLTRMNBRTONI $.
112 |
113 | ${
114 | andId.1 $e |- implies phi psi $.
115 | andId.2 $e |- implies phi chi $.
116 | $( A -> B -> A /\ B $)
117 | andId $p |- implies phi and psi chi $=
118 | ( logbinopand wff_logbinop logbinopimplies andI syl mpd ) ACFCBGZEABHLCGDBC
119 | IJK $.
120 | $}
121 |
122 | ${
123 | imp.1 $e |- implies phi implies psi chi $.
124 | $( A -> B -> C |- A /\ B -> C $)
125 | imp $p |- implies and phi psi chi $=
126 | ( logbinopand wff_logbinop andR logbinopimplies andL syl mpd ) EBAFZBCABGLA
127 | HCBFABIDJK $.
128 | $}
129 |
130 | ${
131 | exp.1 $e |- implies and phi psi chi $.
132 | $( A /\ B -> C |- A -> B -> C $)
133 | exp $p |- implies phi implies psi chi $=
134 | ( logbinopimplies logbinopand wff_logbinop andI imim2 ax-mp syl ) AEFBAGZBG
135 | ZECBGZABHECLGENMGDBLCIJK $.
136 | $}
137 |
138 | wff_pa_ax1 $p wff not = 0 S x $=
139 | tzero varx tvar tsucc binpred_equals wff_atom wff_not
140 | $.
141 |
142 | wff_pa_ax1_term $p wff not = 0 S t $=
143 | tzero tt tsucc binpred_equals wff_atom wff_not
144 | $.
145 |
146 | $(
147 | phi $b varx wff_pa_ax1
148 | psi $b logbinopimplies varx wff_pa_ax1 wff-chi wff_logbinop
149 | ax-mp
150 | $)
151 |
152 | int1 $p |- implies chi not = 0 S x $=
153 | varx wff_pa_ax1
154 | logbinopimplies varx wff_pa_ax1 wff-chi wff_logbinop
155 | varx pa_ax1
156 | varx wff_pa_ax1 wff-chi ax-1
157 | ax-mp
158 | $.
159 |
160 | ${
161 | $d psi x $.
162 | $d x y $.
163 |
164 | int2 $p |- implies psi forall x not = 0 S x $=
165 | varx wff_psi varx wff_pa_ax1 varx wff_psi int1 alpha_2
166 | $.
167 |
168 | $(
169 | phi: vary wff_pa_ax1
170 | psi: varx quant_all varx wff_pa_ax1 wff_quant
171 | min: vary pa_ax1
172 | maj: varx vary wff_pa_ax1 int2
173 | ax-mp
174 | $)
175 |
176 | nocheat $p |- forall x not = 0 S x $=
177 | vary wff_pa_ax1
178 | varx quant_all varx wff_pa_ax1 wff_quant
179 | vary pa_ax1
180 | varx vary wff_pa_ax1 int2
181 | ax-mp
182 | $.
183 | $}
184 |
185 | $(
186 | phi: varx quant_all varx wff_pa_ax1 wff_quant
187 | = wff forall x not = 0 S x
188 | psi: varx quant_all logbinopimplies varx wff_pa_ax1 varx tvar tzero binpred_equals wff_atom wff_logbinop wff_quant
189 | = wff forall x implies = x 0 not = 0 S x
190 | min: varx cheat
191 | = |- forall x not = 0 S x
192 | maj: tzero varx varx wff_pa_ax1 all_elim
193 | = |- implies forall x not = 0 S x forall x implies = x 0 not = 0 S x
194 | ax-mp
195 | $)
196 |
197 | $( forall x, x=0 -> 0 != S x $)
198 | nocheat2 $p |- forall x implies = x 0 not = 0 S x $=
199 | varx quant_all varx wff_pa_ax1 wff_quant
200 | varx quant_all logbinopimplies varx wff_pa_ax1 varx tvar tzero binpred_equals wff_atom wff_logbinop wff_quant
201 | varx nocheat
202 | tzero varx varx wff_pa_ax1 all_elim
203 | ax-mp
204 | $.
205 |
206 | nocheat2_wff $p wff forall x implies = x 0 not = 0 S x $=
207 | varx quant_all logbinopimplies varx tvar wff_pa_ax1_term varx tvar tzero binpred_equals wff_atom wff_logbinop wff_quant
208 | $.
209 |
210 | $( (forall x, forall y, x=y -> phi<->psi) -> forall x, phi <-> forall y, psi $)
211 |
212 | tmp3 $p |- implies and = t t = x 0 iff = t x = t 0 $=
213 | tt tt varx tvar tzero binpred_equals eq-congr
214 | $.
215 |
216 | tmp3a $p |- implies = x 0 = S x S 0 $=
217 | varx tvar tzero eq-suc
218 | $.
219 |
220 | $( x = 0 -> (0 != S x <-> 0 != S 0) $)
221 | $(
222 | s0 = S x
223 | s1 = S 0
224 | t0 = 0
225 | t1 = 0
226 | binpred_equals
227 | eq-congr -> iff = 0 S x = 0 S 0
228 | $)
229 |
230 | tmp3b $p |- implies and = 0 0 = S x S 0 iff = 0 S x = 0 S 0 $=
231 | tzero
232 | tzero
233 | varx tvar tsucc
234 | tzero tsucc
235 | binpred_equals
236 | eq-congr
237 | $.
238 |
239 | tmp3c $p |- implies = S x S 0 and = 0 0 = S x S 0 $=
240 | ( tzero binpred_equals wff_atom logbinopimplies logbinopand tvar
241 | wff_logbinop tsucc eq-refl andI ax-mp ) BBCDZEFAGIBICDZMHNHBJMNKL $.
242 |
243 | eqeq2 $p |- implies = s t iff = u s = u t $=
244 | ( binpred_equals wff_atom logbinopimplies logbinopiff logbinopand andR
245 | eq-sym wff_logbinop andL syl andId eq-trans exp bi3 mpd ) ABDEZFCADEZCBDEZKZG
246 | UATKZSUATHUASKZHBADEZUAKTUDUAUESUAIUDSUESUALABJMNCBAOMPSFUATKFUCUBKSTUAHTSKZH
247 | STKUAUFTSSTISTLNCABOMPTUAQMR $.
248 |
249 | $(
250 | phi: = S x S 0
251 | psi: and = 0 0 = S x S 0
252 | chi: iff = 0 S x = 0 S 0
253 | $)
254 |
255 | tmp3d $p |- implies = S x S 0 iff = 0 S x = 0 S 0 $=
256 | ( tvar tsucc tzero eqeq2 ) ABCDCDE $.
257 |
258 | $(
259 | phi: = x 0
260 | psi: = S x S 0
261 | chi: iff = 0 S x = 0 S 0
262 | $)
263 |
264 | tmp3e $p |- implies = x 0 iff = 0 S x = 0 S 0 $=
265 | ( tvar tzero binpred_equals wff_atom tsucc logbinopiff wff_logbinop tmp3d
266 | syl eq-suc ) ABZCDELFZCFZDEGCNDECMDEHLCKAIJ $.
267 |
268 | $( using ax-3 $)
269 |
270 | $( (A <-> B) -> (!A <-> !B) $)
271 | notbi $p |- implies iff phi psi iff not phi not psi $=
272 | ( logbinopiff wff_logbinop logbinopimplies wff_not bi1 con3 syl bi2 bi3 mpd
273 | ) CBADZEAFZBFZDZCONDZMEBADPABGABHIMEONDZEQPDMEABDRABJBAHINOKIL $.
274 |
275 | tmp3f $p |- implies iff = 0 S x = 0 S 0 iff not = 0 S x not = 0 S 0 $=
276 | ( tzero tvar tsucc binpred_equals wff_atom notbi ) BACDEFBBDEFG $.
277 |
278 | $(
279 | phi: = x 0
280 | psi: iff = 0 S x = 0 S 0
281 | chi: iff not = 0 S x not = 0 S 0
282 | phi -> psi = tmp3e
283 | psi -> chi = tmp3f
284 | $)
285 |
286 | cheat3 $p |- implies = x 0 iff not = 0 S x not = 0 S 0 $=
287 | ( tvar tzero binpred_equals wff_atom logbinopiff tsucc wff_logbinop tmp3e
288 | syl wff_not tmp3f ) ABZCDEFCCGDEZCMGDEZHFNKOKHAIALJ $.
289 |
290 | $( t,x,phi,chi,all_elim3_hyp1 $)
291 | nocheat4 $p |- implies
292 | forall x implies = x 0 not = 0 S x
293 | not = 0 S 0 $=
294 | tzero
295 | varx
296 | varx tvar wff_pa_ax1_term
297 | tzero wff_pa_ax1_term
298 | varx cheat3
299 | all_elim3
300 | $.
301 |
302 | one_ne_zero $p |- not = 0 S 0 $=
303 | varx nocheat2_wff
304 | tzero wff_pa_ax1_term
305 | varx nocheat2
306 | varx nocheat4
307 | ax-mp
308 | $.
309 |
310 |
--------------------------------------------------------------------------------
/metamath/verify.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | from __future__ import print_function
3 | import os
4 | import sys
5 | import code
6 | import lark
7 | import logging
8 | import argparse
9 | import traceback
10 | import itertools
11 | from termcolor import colored
12 | from tqdm import tqdm
13 |
14 | parser = argparse.ArgumentParser(description='Verify metamath')
15 | parser.add_argument('-t', '--test', action='store_true')
16 | parser.add_argument('-r', '--repl', action='store_true')
17 | parser.add_argument('-v', '--verbose', action='store_true')
18 | parser.add_argument('-d', '--debug', action='store_true')
19 | parser.add_argument('file', type=str)
20 | args = parser.parse_args()
21 |
22 | logging.basicConfig(level=logging.WARNING, format='%(message)s')
23 |
24 | log = logging.getLogger(__name__)
25 | loglevel = logging.WARNING
26 | if args.debug:
27 | loglevel = logging.DEBUG
28 | elif args.verbose:
29 | loglevel = logging.INFO
30 | log.setLevel(loglevel)
31 |
32 | grammar = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "mm.g")).read()
33 | l = lark.Lark(grammar, parser="lalr")
34 | p = l.parse(open(args.file).read())
35 | log.info("*********** LOADED ***********")
36 |
37 | class Scope(object):
38 | def __init__(self):
39 | self.constants = set()
40 | self.asserts = dict()
41 | self.hypos = dict()
42 | self.variables = list()
43 | self.horder = list()
44 | self.vtypes = dict()
45 | self.disjoints = set()
46 | self.essen = list()
47 |
48 | def child(self):
49 | ret = Scope()
50 | # asserts are noscope
51 | ret.asserts = self.asserts
52 |
53 | ret.constants = self.constants.copy()
54 | ret.variables = self.variables[:]
55 | ret.horder = self.horder[:]
56 | ret.vtypes = self.vtypes.copy()
57 | ret.disjoints = self.disjoints.copy()
58 |
59 | ret.hypos = self.hypos.copy()
60 | ret.essen = self.essen[:]
61 |
62 | return ret
63 |
64 | def lp(ms):
65 | if ms is None:
66 | return "NONE"
67 | return ' '.join(map(str, ms))
68 |
69 | class Stack(object):
70 | def __init__(self):
71 | self.ss = []
72 |
73 | def __len__(self):
74 | return len(self.ss)
75 |
76 | def push(self, tyc, ms):
77 | self.ss.append((tyc, ms))
78 | log.debug("*** pushed {} {}".format(tyc, lp(ms)))
79 |
80 | def pop(self):
81 | ret = self.ss.pop()
82 | log.debug("*** popped {} {}".format(ret[0], lp(ret[1])))
83 | return ret
84 |
85 | def peek(self):
86 | return self.ss[-1]
87 |
88 | def variables_in_scope(scope, ms):
89 | tvars = []
90 | for e in scope.essen:
91 | for v in e['ms']:
92 | if v in scope.variables and v not in tvars:
93 | tvars.append(v)
94 | for v in ms:
95 | if v in scope.variables and v not in tvars:
96 | tvars.append(v)
97 | return sorted(tvars, key=lambda x: scope.horder.index(x))
98 |
99 | def decompress_proof(scope, inms, children):
100 | crib = []
101 | for v in variables_in_scope(scope, inms):
102 | for lbl,kk in scope.hypos.items():
103 | if kk['ms'] == [v] and kk['floating']:
104 | if lbl not in crib:
105 | crib.append(lbl)
106 |
107 | # get essential hypothesis
108 | crib += [x['lbl'] for x in scope.essen]
109 | log.debug(lp(crib))
110 |
111 | # add to crib and parse weird numbers
112 | cc = []
113 | for x in children:
114 | if x.type == "LABEL":
115 | crib.append(x)
116 | else:
117 | assert x.type == "COMPRESSED_PROOF_BLOCK"
118 | cc.append(str(x))
119 |
120 | # parse weird numbers
121 | nn = []
122 | zz = []
123 | acc = 0
124 | for c in ''.join(cc):
125 | if c in 'UVWXY':
126 | acc *= 5
127 | acc += ord(c) - (ord('U')-1)
128 | elif c in 'ABCDEFGHIJKLMNOPQRST':
129 | acc *= 20
130 | acc += ord(c) - (ord('A')-1)
131 | nn.append(acc)
132 | acc = 0
133 | elif c == "Z":
134 | assert acc == 0
135 | zz.append(len(nn))
136 | #print(len(crib), len(zz))
137 | ret = []
138 | for n in nn:
139 | i = n-1
140 | if i < len(crib):
141 | ret.append(crib[i])
142 | elif i < len(crib)+len(zz):
143 | z = zz[i-len(crib)]
144 | ret.append(z)
145 | else:
146 | log.error("out of range {}".format(i))
147 | assert False
148 | #print(len(ret), n, ret[-1])
149 | return ret
150 |
151 | def bind(scope, ms, bindings, partial=False):
152 | nms = []
153 | for v in ms:
154 | if v in scope.variables:
155 | # late binding no longer supported
156 | if not partial:
157 | assert v in bindings
158 | nms.append(bindings[v])
159 | else:
160 | if v in bindings:
161 | nms.append(bindings[v])
162 | else:
163 | nms.append([v])
164 | else:
165 | # pass through constants
166 | if v not in scope.constants:
167 | log.warning("WTF", v, "ISN'T A CONSTANT", lp(ms))
168 | assert v in scope.constants
169 | nms.append([v])
170 | ret = []
171 | for x in nms:
172 | ret += x
173 | return ret
174 |
175 | def exec_metamath(scope, lbls):
176 | refs = []
177 | stack = Stack()
178 | for ii, s in enumerate(lbls):
179 | log.debug(" proof(%d) %s -> " % (ii+1, s))
180 | bindings = {}
181 | def do_bind(scope, v):
182 | if v not in bindings:
183 | vt, vnms = stack.pop()
184 | assert v in scope.vtypes
185 | if scope.vtypes[v] != vt:
186 | log.warning(" expected type %s, got type %s while binding %s to %s" % (scope.vtypes[v], vt, v, lp(vnms)))
187 | assert scope.vtypes[v] == vt
188 | log.debug(" bind %s to %s" % (v, lp(vnms)))
189 | bindings[v] = vnms
190 |
191 | if s in scope.asserts:
192 | a = scope.asserts[s]
193 | ms = a['ms']
194 | # first bind in essential scope
195 | pop = []
196 |
197 | for e in a['scope'].essen[::-1]:
198 | et, enms = stack.pop()
199 | log.debug("%s: must verify %s %s is %s %s" % (e['lbl'], e['type'], lp(e['ms']), et, lp(enms)))
200 | assert e['type'] == et
201 | pop.append((et, enms, e['ms'], e['lbl']))
202 |
203 | # early binding
204 | tvars = variables_in_scope(a['scope'], ms)
205 | log.debug("binding [%s]" % lp(tvars))
206 | for v in tvars[::-1]:
207 | do_bind(a['scope'], v)
208 |
209 | # verify disjoints
210 | for v1, v2 in a['scope'].disjoints:
211 | if v1 in bindings and v2 in bindings:
212 | for bvv1 in [x for x in bindings[v1] if x in a['scope'].variables]:
213 | for bvv2 in [x for x in bindings[v2] if x in a['scope'].variables]:
214 | # confirm bvv1 and bvv2 are disjoint in current scope
215 | log.debug("verify %s %s disjoint" % (bvv1, bvv2))
216 | assert bvv1 != bvv2
217 | assert (bvv1, bvv2) in scope.disjoints or \
218 | (bvv2, bvv1) in scope.disjoints
219 |
220 | # parse essential
221 | for et, enms, ems, lbl in pop:
222 | log.debug("working on %s" % lbl)
223 | nms = bind(a['scope'], ems, bindings)
224 | log.debug("compare %s to %s" % (lp(nms), lp(enms)))
225 | assert nms == enms
226 |
227 | stack.push(a['type'], bind(a['scope'], ms, bindings))
228 | elif s in scope.hypos:
229 | a = scope.hypos[s]
230 | # don't bind variables
231 | stack.push(a['type'], a['ms'])
232 | elif type(s) == int:
233 | oot, ooms = refs[s-1]
234 | log.debug("load ref", s, oot, lp(ooms))
235 | stack.push(oot, ooms)
236 | else:
237 | raise Exception("%s label not found" % s)
238 | refs.append(stack.peek())
239 |
240 | # confirm stack is this
241 | return stack
242 |
243 | def parse_stmt(scope, xx):
244 | if xx.data == "variable_stmt":
245 | for y in xx.children:
246 | vname = y.children[0]
247 | assert vname not in scope.variables
248 | scope.variables.append(vname)
249 | elif xx.data == "hypothesis_stmt":
250 | xx = xx.children[0]
251 | lbl = xx.children[0]
252 | tyc = xx.children[1].children[0].children[0]
253 | assert tyc in scope.constants
254 | if xx.data == "floating_stmt":
255 | var = xx.children[2].children[0]
256 | assert var in scope.variables
257 | # TODO: we are throwing away this name, do we need it?
258 | assert var not in scope.vtypes
259 | scope.vtypes[var] = tyc
260 | scope.hypos[lbl] = {"type": tyc, "ms": [var], "floating": True}
261 | scope.horder.append(var)
262 | elif xx.data == "essential_stmt":
263 | ms = xx.children[2:]
264 | scope.essen.append({"type": tyc, "ms": ms, "lbl": lbl})
265 | scope.hypos[lbl] = {"type": tyc, "ms": ms, "floating": False}
266 | elif xx.data == "assert_stmt":
267 | xx = xx.children[0]
268 | lbl = xx.children[0]
269 | tyc = xx.children[1].children[0].children[0]
270 | assert tyc in scope.constants
271 | if xx.data == "axiom_stmt":
272 | ms = xx.children[2:]
273 | proof = None
274 | elif xx.data == "provable_stmt":
275 | ms = xx.children[2:-1]
276 | proof = xx.children[-1]
277 | scope.asserts[lbl] = {'type': tyc, 'ms': ms, 'scope': scope.child(), 'proof': proof}
278 | elif xx.data == "disjoint_stmt":
279 | # if we don't check this, it should still verify, just sometimes wrongly
280 | av = [x.children[0] for x in xx.children]
281 | for v1 in av:
282 | assert v1 in scope.variables
283 | for v2 in av:
284 | if v1 != v2 and (v1,v2) not in scope.disjoints and (v2,v1) not in scope.disjoints:
285 | scope.disjoints.add((v1, v2))
286 | elif xx.data == "block":
287 | tscope = scope.child()
288 | for y in xx.children:
289 | parse_stmt(tscope, y.children[0])
290 | else:
291 | log.error("IMPLEMENT", xx.data)
292 | pass
293 |
294 | scope = Scope()
295 |
296 | def parse(p):
297 | for x in p.children:
298 | xx = x.children[0]
299 | if xx.data == "constant_stmt":
300 | for y in xx.children:
301 | cname = y.children[0]
302 | assert cname not in scope.constants
303 | scope.constants.add(cname)
304 | elif xx.data == "include_stmt":
305 | fn = str(xx.children[0])
306 | log.info("including %s" % fn)
307 | parse(l.parse(open(fn).read()))
308 | else:
309 | parse_stmt(scope, xx.children[0])
310 | parse(p)
311 |
312 | log.info("*********** PARSED ***********")
313 | pbar = tqdm(scope.asserts.items())
314 | for k,v in pbar:
315 | if v['proof'] is not None:
316 | pbar.set_description(k)
317 | log.info("******** verify %s" % k)
318 |
319 | # get proof labels
320 | xx = v['proof'].children[0]
321 | if xx.data == "compressed_proof":
322 | lbls = decompress_proof(v['scope'], v['ms'], xx.children)
323 | else:
324 | lbls = xx.children
325 | log.info(lp(lbls))
326 | stack = exec_metamath(v['scope'], lbls)
327 | o = stack.pop()
328 | assert len(stack) == 0
329 | log.info(" produced %s %s expected %s %s" % (o[0], lp(o[1]), v['type'], lp(v['ms'])))
330 | assert o == (v['type'], v['ms'])
331 | log.info("*********** VERIFIED ***********")
332 |
333 | def search_forward(scope, ty, ms):
334 | print("asserts: %d hypos: %d" % (len(scope.asserts), len(scope.hypos)))
335 | all_lbls = [lark.lexer.Token(value=x, type_="LABEL") for x in list(scope.asserts.keys())+list(scope.hypos.keys())]
336 | ok = [[],]
337 | d = 0
338 | while 1:
339 | d += 1
340 | print("searching at depth %d with %d" % (d, len(ok)))
341 | for prefix in ok[:]:
342 | for l in all_lbls:
343 | try:
344 | log.setLevel(logging.ERROR)
345 | x = prefix+[l]
346 | stack = exec_metamath(scope, x)
347 | log.setLevel(loglevel)
348 | o = stack.pop()
349 | if o[0] == ty and o[1] == ms:
350 | if len(stack) == 0:
351 | return x
352 | ok.append(x)
353 | except Exception:
354 | #traceback.print_exc()
355 | pass
356 |
357 | def can_produce(scope, tms, ms, d, binds):
358 | var = variables_in_scope(scope, tms)
359 | #print("CAN", lp(tms), "PRODUCE", lp(ms), "REPLACING", lp(var))
360 | p0, p1 = 0, 0
361 | while p0 < len(tms) and p1 < len(ms):
362 | if tms[p0] not in var:
363 | if tms[p0] == ms[p1]:
364 | p0 += 1
365 | p1 += 1
366 | else:
367 | return None
368 | elif tms[p0] in binds:
369 | b = binds[tms[p0]]
370 | if b[1] == ms[p1:p1+len(b[1])]:
371 | p0 += 1
372 | p1 += len(b[1])
373 | else:
374 | return None
375 | else:
376 | # tms[p0] is a var
377 | # 1 symbol replaced for now
378 | # this is an issue
379 | for l in range(1, len(ms)-p1+1):
380 | if tms[p0] not in binds:
381 | qret = search(scope, scope.vtypes[tms[p0]], ms[p1:p1+l], d+1)
382 | if qret is not None:
383 | binds[tms[p0]] = (scope.vtypes[tms[p0]], ms[p1:p1+l], qret)
384 | p0 += 1
385 | p1 += l
386 | break
387 | else:
388 | return None
389 | if p0 != len(tms) or p1 != len(ms):
390 | return None
391 | return binds
392 |
393 | def search(scope, ty, ms, d=0):
394 | if d == 10:
395 | return None
396 | log.debug(" "*d+"searching for %s %s" % (ty, lp(ms)))
397 | for k,x in scope.hypos.items():
398 | if x['floating']:
399 | # hypothesis must be exact
400 | if x['type'] == ty and x['ms'] == ms:
401 | # exact match ends the search
402 | return [k]
403 |
404 | for k,x in scope.asserts.items():
405 | if x['type'] == ty:
406 | binds = can_produce(x['scope'], x['ms'], ms, d, {})
407 | if binds is not None:
408 | var = variables_in_scope(x['scope'], x['ms'])
409 | good = True
410 | # check for essential hypothesis in scope
411 | for kk in x['scope'].essen:
412 | bb = bind(x['scope'], kk['ms'], {k : v[1] for k, v in binds.items()}, partial=True)
413 | print(" "*d+"check essential", kk['lbl'], kk['type'], lp(bb))
414 | #ss = search(x['scope'], kk['type'], bb, d+1)
415 | good = False
416 | # get the order right
417 | rret = []
418 | for kk in var:
419 | if kk not in binds:
420 | good = False
421 | break
422 | rret += binds[kk][2]
423 | if good:
424 | return rret+[k]
425 |
426 | return None
427 |
428 | def tokenize(ind, type_):
429 | return [lark.lexer.Token(value=x, type_=type_) for x in ind.split(" ")]
430 |
431 | if args.test:
432 | tests = [
433 | "wff not = 0 S x",
434 | "wff not = 0 S t",
435 | "wff = 0 0",
436 | "|- = 0 0",
437 | "term x",
438 | "var x",
439 | "|- = x x",
440 | "|- not = 0 S x",
441 | "|- implies chi not = 0 S x", # fails due to essential hypothesis
442 | "wff forall x implies = x 0 not = 0 S x",
443 | "wff iff = 0 S x = 0 S 0",
444 | "|- = S 0 S 0",
445 | "|- implies = x y = S x S y",
446 | "|- implies = S x S y = S S x S S y",
447 | "|- implies = x y = S S x S S y", # fails, combine?
448 | "|- not = 0 S 0", # fails, superhard
449 | "wff not = 0 S 0",
450 | "|- = + S S 0 S S 0 S S S S 0", # 2+2=4 :)
451 | "wff = + S S 0 S S 0 S S S S 0",
452 | "wff = + S S 0 S S 0 S S S 0",
453 | "|- implies = x y = y x",
454 | "|- implies and = x y = y z = x z",
455 | "|- implies and = x y = z y = x z", # this fails
456 | ]
457 | for tst in tests:
458 | ms = tokenize(tst, "MATH_SYMBOL")
459 | prog = search(scope, ms[0], ms[1:])
460 | if prog is None:
461 | passed = False
462 | else:
463 | stk = exec_metamath(scope, prog)
464 | t = stk.pop()
465 | passed = len(stk) == 0 and ms[0] == t[0] and ms[1:] == t[1]
466 | print(colored("passed", "green") if passed else colored("failed", "red"), tst, colored("<-", "yellow"), lp(prog))
467 | if not passed:
468 | print("stopping early")
469 | break
470 |
471 | if args.repl:
472 | print("entering repl")
473 | # labels
474 | print("asserts:", lp(scope.asserts))
475 | print("hypos:", lp(scope.hypos))
476 | # math symbols
477 | print("constants:", lp(scope.constants))
478 | print("variables:", lp(scope.variables))
479 | try:
480 | import readline
481 | except ImportError:
482 | pass
483 | else:
484 | import rlcompleter
485 | readline.parse_and_bind("tab: complete")
486 |
487 | while True:
488 | ind = input('cmd> ').strip()
489 | if len(ind) == 0 or " " not in ind:
490 | continue
491 | cmd, ind = ind.split(" ", 1)
492 | if cmd == "c" or cmd == "command":
493 | lbls = tokenize(ind, "LABEL")
494 | try:
495 | stack = exec_metamath(scope, lbls)
496 | while len(stack) != 0:
497 | o = stack.pop()
498 | print(o[0], lp(o[1]))
499 | except Exception:
500 | traceback.print_exc()
501 | elif cmd == "f" or cmd == "forward":
502 | ms = tokenize(ind, "MATH_SYMBOL")
503 | try:
504 | ret = search_forward(scope, ms[0], ms[1:])
505 | print(lp(ret))
506 | except KeyboardInterrupt:
507 | print("interrupted")
508 | elif cmd == "s" or cmd == "search":
509 | # search for a set of labels that produces this string of math symbols
510 | ms = tokenize(ind, "MATH_SYMBOL")
511 | try:
512 | ret = search(scope, ms[0], ms[1:])
513 | if ret is not None:
514 | print(lp(ret))
515 | else:
516 | print("search failed")
517 | except KeyboardInterrupt:
518 | print("interrupted")
519 |
520 |
521 |
--------------------------------------------------------------------------------
/prove/.gitignore:
--------------------------------------------------------------------------------
1 | a.out
2 | *.compcert.c
3 |
--------------------------------------------------------------------------------
/prove/fact.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int fact(int n) {
4 | int r = 1;
5 | int i;
6 | for (i = 2; i <= n; i++) r *= i;
7 | return r;
8 | }
9 |
10 | int main(void) {
11 | printf("fact(10) = %d\n", fact(10));
12 | return 0;
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/prove/test.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[]) {
4 | int i = atoi(argv[1]);
5 | if (i < 3) {
6 | printf("hello\n");
7 | } else {
8 | printf("world\n");
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | lark-parser==0.7.8
2 | tqdm
3 | termcolor
4 |
--------------------------------------------------------------------------------
|