├── .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 | --------------------------------------------------------------------------------