├── js ├── README.md ├── parameters.js ├── lambdaTerms.js ├── icequine.js ├── nodes.js ├── pagelook-lab.js ├── pagelook.js ├── pagelook-vs.js ├── ioprep.js ├── pagelook-skilambda.js ├── myD3Graph.js └── 0parser.js ├── img ├── readme.md ├── AA.jpg ├── AK.jpg ├── AKx.jpg ├── AS.jpg ├── IA.jpg ├── IS.jpg ├── ISx.jpg ├── KA.jpg ├── KS.jpg ├── KSx.jpg ├── SA.jpg ├── SK.jpg ├── SK2.jpg ├── SS.jpg ├── COMB.jpg ├── SSAA.jpg ├── nodeS.jpg ├── node3val.jpg ├── synthSA.jpg ├── synthSK.jpg ├── tokens.jpg ├── colorcodes.jpg ├── node3val2.jpg └── combinators.jpg ├── pdf ├── readme.md └── chemSKI.pdf ├── css ├── README.md ├── icequine.css └── icequine-on-white.css ├── README.md ├── chemski.html └── chemski-with-tokens.html /js/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /img/readme.md: -------------------------------------------------------------------------------- 1 | Images folder 2 | -------------------------------------------------------------------------------- /pdf/readme.md: -------------------------------------------------------------------------------- 1 | Pdf versions 2 | -------------------------------------------------------------------------------- /img/AA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/AA.jpg -------------------------------------------------------------------------------- /img/AK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/AK.jpg -------------------------------------------------------------------------------- /img/AKx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/AKx.jpg -------------------------------------------------------------------------------- /img/AS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/AS.jpg -------------------------------------------------------------------------------- /img/IA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/IA.jpg -------------------------------------------------------------------------------- /img/IS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/IS.jpg -------------------------------------------------------------------------------- /img/ISx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/ISx.jpg -------------------------------------------------------------------------------- /img/KA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/KA.jpg -------------------------------------------------------------------------------- /img/KS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/KS.jpg -------------------------------------------------------------------------------- /img/KSx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/KSx.jpg -------------------------------------------------------------------------------- /img/SA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/SA.jpg -------------------------------------------------------------------------------- /img/SK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/SK.jpg -------------------------------------------------------------------------------- /img/SK2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/SK2.jpg -------------------------------------------------------------------------------- /img/SS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/SS.jpg -------------------------------------------------------------------------------- /img/COMB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/COMB.jpg -------------------------------------------------------------------------------- /img/SSAA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/SSAA.jpg -------------------------------------------------------------------------------- /img/nodeS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/nodeS.jpg -------------------------------------------------------------------------------- /img/node3val.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/node3val.jpg -------------------------------------------------------------------------------- /img/synthSA.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/synthSA.jpg -------------------------------------------------------------------------------- /img/synthSK.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/synthSK.jpg -------------------------------------------------------------------------------- /img/tokens.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/tokens.jpg -------------------------------------------------------------------------------- /pdf/chemSKI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/pdf/chemSKI.pdf -------------------------------------------------------------------------------- /img/colorcodes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/colorcodes.jpg -------------------------------------------------------------------------------- /img/node3val2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/node3val2.jpg -------------------------------------------------------------------------------- /img/combinators.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbuliga/chemski/HEAD/img/combinators.jpg -------------------------------------------------------------------------------- /css/README.md: -------------------------------------------------------------------------------- 1 | css, forked and modified from https://github.com/mbuliga/quinegraphs/tree/master/css 2 | -------------------------------------------------------------------------------- /js/parameters.js: -------------------------------------------------------------------------------- 1 | // general parameters 2 | // 3 | // forked from https://github.com/mbuliga/quinegraphs/blob/master/js/parameters.js 4 | // 5 | // this version 29.05.2023 6 | 7 | 8 | // set up the d3 visualisation 9 | var w = 560, 10 | h = 480; 11 | 12 | // node radii 13 | 14 | var smallNode = 6, 15 | bigNode = 10; 16 | 17 | // d3 force graph parameters 18 | 19 | var chargeForceStrength = -16; 20 | var gravForceStrength = 0.12; 21 | 22 | var forceStrength = 0.5; 23 | var forceAlpha = 0.1; 24 | var forceAlphaDecay = 0; 25 | var forceVelocityDecay = 0.1; 26 | 27 | // colors 28 | 29 | var redCol = "#FF0000"; //"red"; // "#b80000"; 30 | var orangeCol = "#F08080"; //"lightcoral"; // "#FF6C03"; 31 | var orange2Col = "#FF8C00"; //"darkorange"; // "#FFA500"; 32 | var yellowCol = "#FFD700"; //"gold"; // "#FFCE54"; 33 | var greenCol = "#008000"; //"green"; // "#9fc952"; 34 | var middleCol = "#4682B4"; //"steelblue"; // "#4A89DC"; 35 | var blueCol = "#0000FF"; //"blue"; // "#00F"; 36 | var violetCol = "#D503FF"; 37 | var whiteCol = "#fff"; 38 | 39 | // 40 | 41 | var speed = 0; 42 | var startVar = 0; 43 | var arenaVar = 0; 44 | var fightersVar = 0; 45 | var combOnly = 0; 46 | var olderFirst = 0; 47 | 48 | // transform chemlambda into directed IC and back parameter 49 | 50 | var isChemlambda = 1; 51 | 52 | // parser for lambda term (isSkiTerm = 0) or for SKI term (isSkiTerm = 1) 53 | 54 | var isSkiTerm = 1; 55 | 56 | 57 | // age 58 | 59 | var age = 0; 60 | 61 | 62 | // global counter 63 | 64 | var globCount = 0; 65 | 66 | // balance of tokens 67 | 68 | var balanceOfTokens = []; 69 | 70 | // tag and number and token 71 | 72 | 73 | var tokenIni = ""; 74 | var tagIni = ""; 75 | var numberIni = 0; 76 | var decorationOfEdges = []; 77 | 78 | // node colors for metabolism 79 | 80 | var metabo = 0; 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chemSKI 2 | [Marius Buliga](https://mbuliga.github.io/) 3 | 4 | A purely local graph rewrite system for the SKI combinator calculus, in [chemlambda](https://chemlambda.github.io/index.html) style. 5 | 6 | The main article is [chemSKI with tokens: world building and economy in the SKI universe](https://mbuliga.github.io/chemski/chemski-with-tokens.html), [arXiv:2306.00938](https://arxiv.org/abs/2306.00938). 7 | 8 | chemSKI was first proposed in [chemSKI & chemlambda](https://mbuliga.github.io/chemski/chemski.html#SIISII). 9 | 10 | **Motivation.** German Kruszewski posed the problem of a chemlambda style graph-rewriting version of his and Tomas Mikolov Combinatory Chemistry 11 | https://www.mitpressjournals.org/doi/pdf/10.1162/isal_a_00258 12 | https://arxiv.org/pdf/2003.07916.pdf 13 | 14 | **chemSKI** is a graph rewrite system for the SKI combinator calculus, with only local graph rewrites. The algorithm of application of rewrites is random. 15 | 16 | **Differences.** Kruszewski and Mikolov Combinatory Chemistry is conservative. Therefore the reaction 17 | 18 | S a b c + c --> (a c) (b c) + S 19 | 20 | is based on the delegated duplication of c, i.e. the reaction happens only if somewhere else in the system the term c is produced. 21 | 22 | chemSKI graph rewrites are not conservative, but they can be made conservative, as explained in the main article, inspired by the [project Hapax](https://github.com/mbuliga/hapax). In chemSKI the *SKI combinators graphs* (i.e. chemSKI graphs) can be supplemented with *small token molecules*, ie two nodes molecules like I-A, S-A, S-K, ..., which added to the rewrites make them conservative in the nodes and edges. This allows to build various costs of computation. 23 | 24 | 25 | Another feature of Combinatory Chemistry is that it allows chemical reactions which build larger graphs from smaller ones. In terms of combinators, the reaction is 26 | 27 | A + B --> A B 28 | 29 | like in Fontana and Buss ALCHEMY. 30 | 31 | 32 | This can be replaced in chemSKI by synthesis rewrites which adds (inserts, glues) a token molecule to an edge of the graph of another token, or to one of any other graph. This was first suggested for chemlambda in Chemlambda strings 33 | https://doi.org/10.6084/m9.figshare.5751318.v1 34 | and a first attempt was done in the repository hapax 35 | https://github.com/mbuliga/hapax 36 | mentioned before. 37 | -------------------------------------------------------------------------------- /js/lambdaTerms.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | forked from https://github.com/mbuliga/quinegraphs/blob/master/js/lambdaTerms.js 4 | 5 | */ 6 | 7 | 8 | function termLibrary(lambdaName) { 9 | 10 | switch (lambdaName) { 11 | 12 | case "alexo_SKI": 13 | var lambdaTerm = "(S I I) (S (K (S I I)) (S (K (S I)) (S (K K) I)))"; 14 | break; 15 | 16 | case "SKKI": 17 | var lambdaTerm = "S K K I"; 18 | break; 19 | 20 | case "SKILAMBDAEX": 21 | var lambdaTerm = "(\\x.\\y.y x x) K S I"; 22 | break; 23 | 24 | case "SIISII": 25 | var lambdaTerm = "(S I I) (S I I)"; 26 | break; 27 | 28 | case "lambdanote": 29 | var lambdaTerm = "(\\n.(\\f.(\\x.(((n (\\g.(\\h.(h (g f))))) (\\u.x)) (\\u.u))))) (((\\b.(\\e.(e b))) (\\f.(\\x.(f (f (f x)))))) (\\f.(\\x.(f(f (f (f x)))))))"; 30 | break; 31 | 32 | case "(SUBSTRACT ((MULTLONG 3) 4)) 4": 33 | var lambdaTerm = "(((\\m.\\n.((n (\\n.(\\f.(\\x.(((n (\\g.(\\h.(h (g f))))) (\\u.x)) (\\u.u)))))) m)) (((\\m.(\\n.((m ((\\m.(\\n.((m (\\n.(\\f.(\\x.(f ((n f) x)))))) n))) n)) (\\f.(\\x.x))))) (\\f.(\\x.(f (f (f x)))))) (\\f.(\\x.(f(f (f (f x)))))))) (\\f.(\\x.(f(f (f (f x)))))))"; 34 | break; 35 | 36 | case "4omega": 37 | var lambdaTerm = "((\\f.(\\x.(f(f (f (f x)))))) ((\\ x.x x) (\\x.x x)))"; 38 | break; 39 | 40 | case "times_only_short": 41 | var lambdaTerm = "(((\\m.(\\n.(\\f.(m (n f))))) (\\f.(\\x.(f(f (f (f (f x)))))))) (\\f.(\\x.(f(f (f (f (f x))))))))"; 42 | break; 43 | 44 | case "times_only_long": 45 | var lambdaTerm = "(((\\m.(\\n.((m ((\\m.(\\n.((m (\\n.(\\f.(\\x.(f ((n f) x)))))) n))) n)) (\\f.(\\x.x))))) (\\f.(\\x.(f(f (f (f (f x)))))))) (\\f.(\\x.(f(f (f (f (f x))))))))"; 46 | break; 47 | 48 | case "ackermann_2_2": 49 | var lambdaTerm = "(((\\x.(\\y.(((x (\\a.(\\b.((((\\c.(\\d.(\\e.(d ((c d) e))))) b) a) (\\f.(\\g.(f g))))))) (\\z.(\\u.(\\v.(u ((z u) v)))))) y))) (\\h.(\\i.(h (h i))))) (\\j.(\\k.(j (j k)))))"; 50 | break; 51 | 52 | case "ackermann_3_2": 53 | var lambdaTerm = "(((\\x.(\\y.(((x (\\a.(\\b.((((\\c.(\\d.(\\e.(d ((c d) e))))) b) a) (\\f.(\\g.(f g))))))) (\\z.(\\u.(\\v.(u ((z u) v)))))) y))) (\\h.(\\i.(h (h (h i)))))) (\\j.(\\k.(j (j k)))))"; 54 | break; 55 | 56 | case "bigpredLambda": 57 | var lambdaTerm = "(\\n.(\\f.(\\x.(((n (\\g.(\\h.(h (g f))))) (\\u.x)) (\\u.u))))) (\\f.(\\x.(f(f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f x))))))))))))))))))))))))))))))"; 58 | break; 59 | 60 | case "omegaSI": 61 | var lambdaTerm = "(\\S.\\I.S I I (S I I)) (\\x.\\y.\\z.(x z) (y z)) \\x.x"; 62 | break; 63 | 64 | case "SKK": 65 | var lambdaTerm = "(((\\S.(\\K.((S K) K))) (\\x.(\\y.(\\z.((x z) (y z)))))) (\\x.(\\y.x)))"; 66 | break; 67 | 68 | case "y_comb_id": 69 | var lambdaTerm = "((\\g.((\\x.(g (x x))) (\\x.(g (x x))))) (\\x.x))"; 70 | break; 71 | 72 | case "omega": 73 | var lambdaTerm = "((\\x.x x) (\\x.x x))"; 74 | break; 75 | 76 | case "alexo_example": 77 | var lambdaTerm = "(\\a.a a)(\\x.((\\b.b b)(\\y.y x)))"; 78 | break; 79 | 80 | case "false (Y A)": 81 | var lambdaTerm = "((\\x.(\\y.y)) ((\\g.((\\x.(g (x x))) (\\x.(g (x x))))) A))"; 82 | break; 83 | 84 | 85 | default: 86 | var lambdaTerm = ""; 87 | break; 88 | } 89 | return lambdaTerm; 90 | } 91 | -------------------------------------------------------------------------------- /js/icequine.js: -------------------------------------------------------------------------------- 1 | //chemlambda + IC only version of the kali system, or anharmonic lambda, grown from: 2 | // https://github.com/chorasimilarity/chemlambda-gui/blob/gh-pages/dynamic/README.md 3 | // https://arxiv.org/abs/1807.02058 4 | // 5 | // this program is forked and modified from https://mbuliga.github.io/kali-try.js on 24.10.2019, which is 6 | // a modification of the js version https://github.com/ishanpm/chemlambda-editor of my chemlambda v2, see the issue https://github.com/chorasimilarity/chemlambda-gui/issues/9 7 | // author: Marius Buliga http://imar.ro/~mbuliga/index.html 8 | // 9 | // 10 | // forked from https://github.com/mbuliga/quinegraphs/blob/master/js/icequine.js 11 | // 12 | // last modified: 29.05.2023 13 | // 14 | 15 | 16 | 17 | var graph; 18 | var mode = "transform"; 19 | var addType = 0; 20 | var selection = null; 21 | var newNodeIndex = 0; 22 | var transformCache = []; // rewrites cache 23 | 24 | 25 | 26 | 27 | // which chemistries (i.e. graph rewrite systems) we use? UPDATE: moved to pagelook.js, selectionStarter(), selectionLambda() 28 | var graphRewriteSystems = []; 29 | 30 | 31 | 32 | //priority of rewrites, for the moment only COMB 33 | var combPriority = 1; 34 | 35 | // build the list of graph rewrites UPDATE: moved to pagelook.js, selectionStarter(), selectionLambda() 36 | 37 | 38 | 39 | // build the d3 graph 40 | graph = myGraph("#svgdiv") 41 | 42 | // main loop 43 | function loop(dt) { 44 | var anyMoves = false; 45 | 46 | 47 | 48 | // added age increase 49 | age +=1; 50 | 51 | // added gloCount increase 52 | globCount +=1; 53 | 54 | var maxNumberOfNodesStr = document.getElementById("maxnodenumber").innerHTML; 55 | var maxNumberOfNodes = maxNumberOfNodesStr - 2; 56 | // var numberOfCenterNodes = Math.floor(nodes.length / 4); 57 | // document.getElementById("nodenumber").innerHTML = numberOfCenterNodes; 58 | 59 | 60 | var rewriteWeight = (document.getElementById("rewritesRange").value) / 100; 61 | 62 | if (nodes.length > 4*maxNumberOfNodes) { setSpeed(0);} 63 | 64 | if (speed == 1 && transformCache.length > 0) { 65 | 66 | // shuffle transformCache 67 | 68 | var transformCacheLength = transformCache.length; 69 | var iswap, tswap; 70 | 71 | // compute minimal age of transforms 72 | 73 | var minAgeTransform = transformCache[0].age; 74 | for (var i=1; i minAgeTransform) { 85 | // transformCacheDeterministic.push(transformCache[i]); 86 | removeFromCache.push(i); 87 | } 88 | } 89 | for (var i=removeFromCache.length - 1; i >=0; i--) { 90 | transformCache.splice(removeFromCache[i],1); 91 | } 92 | 93 | transformCacheLength = transformCache.length; 94 | } 95 | } 96 | 97 | if (speed == 1 && transformCache.length > 0) { 98 | 99 | while (transformCacheLength) { 100 | 101 | // Pick a remaining element 102 | iswap = Math.floor(Math.random() * transformCacheLength--); 103 | 104 | // And swap it with the current element. 105 | tswap = transformCache[transformCacheLength]; 106 | transformCache[transformCacheLength] = transformCache[iswap]; 107 | transformCache[iswap] = tswap; 108 | } 109 | 110 | var putTransformCacheAlt = ""; 111 | for (var i=0; i"; 193 | document.getElementById("chosentransform").innerHTML = chosenTransform; 194 | // 195 | } 196 | } 197 | } 198 | 199 | if (anyMoves) { 200 | update(); 201 | 202 | var putTransformCacheAlt = ""; 203 | for (var i=0; i 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | chemSKI & chemλ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | Cite as:
chemSKI & chemlambda. © Marius Buliga (2020), https://mbuliga.github.io/chemski/chemski.html

29 | Version 24.08.2020

30 | See also:
All chemlambda projects 31 |


32 | German Kruszewski posed the problem of a graph-rewriting version of his and Tomas Mikolov Combinatory Chemistry: Towards a Simple Model of Emergent Evolution, arXiv:2003.07916 in chemlambda style.

33 | chemSKI is a purely local graph rewrite system for the SKI combinators calculus which answers this problem.

34 | In chemSKI there are two 1-valent nodes, for the combinators I and K, and two 3-valent nodes, for the combinator S and for the application (A like in chemlambda). There are also two 1-valent nodes, FRIN (free in) and FROUT (free out) and a 2-valent node Arrow, which serve the same roles as in chemlambda, namely to cap the free half-edges of the graph or to allow simultaneous application of rewrites, followed by the deletion of the introduced Arrow nodes by the rewrite COMB (which "combs" the graph).

35 | The rewrites concerning the node S are different, according to the existence of an edge between S node ports 1 and 2 (in this case S represents the combinator S) or not (in this case S is a fanout node).

36 | There is a variant of chemSKI which is fully compatible with chemlambda rewrites, called "chemSKI+λ" where the occurences of the node S when there is no edge between ports 1 and 2 are replaced with a chemlambda node FOE. You can toggle between chemSKI and chemSKI+λ by using the "change" button.

37 | You can explore the differences between chemSKI and chemSKI+λ by using the parser window and button "λSKI -> mol".

38 | The parser transforms any mix of SKI with lambda calculus (where the letters "S", "K", and "I" are always interpreted as combinators, not lambda calculus variables) into a mol file (i.e. into a graph). This graph can be reduced with chemSKI plus chemlambda or chemSKI+λ plus chemlambda.

39 | In the case of chemSKI the chemlambda nodes do not interpret the node S as a fanout, nor the pure chemSKI nodes (I,S,K) do not see FO and FOE as fanouts. Differently, if you change to the chemistry chemSKI+λ then the reductions work better, with the price of mixing the FO and FOE nodes into the pure chemSKI formalism.

40 |
41 |
42 | 43 |
44 | 57 | 89 | 93 |
94 | 95 |
96 | 99 | 102 | 104 |
105 | 106 |
107 | 114 | 122 | 125 |
126 | 127 |
128 |
129 | before:

130 | 131 |
132 |
133 | chosen:

134 | 135 |
136 |
137 | after:

138 | 139 |
140 |
141 | mol before:

142 | 143 |
144 |
145 | mol after:

146 | 147 |
148 |
149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /js/nodes.js: -------------------------------------------------------------------------------- 1 | // nodes info 2 | // forked from https://github.com/mbuliga/quinegraphs/blob/master/js/nodes.js 3 | // this version: 31.05.2023, added vTokensCost 4 | 5 | /* 6 | In order to define mols (molecules) and mol patterns, we introduce mol node types and 7 | their nodeValence vectors. 8 | */ 9 | 10 | 11 | 12 | // mol nodes 13 | 14 | /* 15 | The mol nodes types are listed in the vector autofilter. For the theory, let NT be the 16 | finite set of mol node types. 17 | */ 18 | 19 | // added S,K,I for chemSKI , "S1" is the 1-valent version of "S" 20 | 21 | var autoFilter = ["L","A","FI","D","FOE","FOX","FO","T","Arrow","GAMMA","DELTA","S","K","I"]; 22 | var Tokens = ["A-A","I-A","S-A","S-K","S-S","Arrow"]; 23 | var TokensCost = [3,2,3,2,3,0]; // cost by number of edges 24 | /* 25 | */ 26 | var balanceOfTokens = []; 27 | for (var ibal=0; ibal < Tokens.length; ibal++) { 28 | balanceOfTokens.push(0);} 29 | /* 30 | In the following definition of nodeValence we see some mol node types with comments. These mol 31 | node types can be decorated with permutations of 3 elements, or with elements of the anharmonic 32 | group. These decorations are a bridge from the present work to emergent algebras (see for 33 | example https://arxiv.org/abs/1807.02058) which are "commutative" in the sense that they satisfy 34 | "the shuffle trick". 35 | 36 | Here we are going to use this correspondence only heuristically, for example to choose the form 37 | of the rewrites "DIST", which increase the number of nodes. 38 | (See more at: 39 | - anharmonic lambda calculus https://mbuliga.github.io/kali24.html 40 | - the tool to choose DIST rewrites https://mbuliga.github.io/rhs.html 41 | - the commented js script https://mbuliga.github.io/rhs.js 42 | but mind that this is work in progress.) 43 | 44 | */ 45 | 46 | /* 47 | Only the node type arity will matter. Arity is nodeValence[node].length. 48 | */ 49 | var nodeValence = { 50 | "L": [0,1,1], // (12) , 1-z 51 | "A": [0,0,1], // (231), (z-1)/z 52 | "FI": [0,0,1], // (312), 1/(1-z) 53 | "D": [0,0,1], // () , z 54 | "FOE":[0,1,1], // (23) , 1/z 55 | "FOX": [0,1,1], // (13) , z/(z-1) 56 | "FO": [0,1,1], // 57 | "T": [0], 58 | "FRIN":[1], 59 | "FROUT":[0], 60 | "Arrow":[0,1], 61 | // added interaction combinators 62 | "GAMMA":[0,0,0], 63 | "DELTA":[0,0,0], 64 | // added S,K,I for chemSKI 65 | "S": [0,1,1], 66 | "K": [0], 67 | "I": [1], 68 | "S1": [1], 69 | } 70 | 71 | /* 72 | Now we can define mols. 73 | 74 | Given a nonempty, finite set of edge tags E, a mol node whose ports are E-decorated is a vector 75 | (t, η) 76 | where: 77 | - t is a mol node type, called the type of the mol node 78 | - η is a word over the alphabet E, such that: 79 | -- any letter from E appears at most twice, 80 | -- the length of η equals the valence of t. 81 | 82 | For a mol node we shall use a notation like 83 | 84 | L a b c 85 | 86 | where "L" is a mol node type and "abc" is the word η with letters from an alphabet E 87 | which contains a, b, c. You can see that the mol node type L has nodeValence vector [0,1,1], whose length is 3, equal to the length of the word abc. 88 | 89 | A mol pattern (which is E-decorated) is a vector of mol nodes, such that any letter from E 90 | appears at most twice over all mol nodes. 91 | 92 | Any letter which appears exactly once in a mol pattern P, is called a free edge. The set of free edges of the mol pattern P is denoted by Free(P). 93 | 94 | A mol, or molecule (which is E-decorated), is a mol pattern without free edges. 95 | 96 | For mol patterns, in particular for mols, we use a notation like 97 | 98 | L a b c 99 | A c d e 100 | 101 | which is amenable to a record with a line separator (here we use newline) which separates the record into lines. Each line is a mol node, itself a record with a field separator (here we use 102 | space, therefore we can't admit space or newline in the alphabet E). 103 | 104 | Such records are available in iceMol.js, in the form of the function molLibrary(). In those records the line separator is "^". 105 | 106 | Note that any mol pattern can be turned into a mol by adding some new mol nodes "FRIN" (i.e. "free in") and "FROUT" (i.e. "free out"). 107 | 108 | 109 | 110 | */ 111 | 112 | 113 | // used in myGraph function 114 | 115 | 116 | /* 117 | A mol pattern, or a mol in particular, can be turned into a graph (here a d3 graph). In order to understand 118 | the conversion (done by functions in ioprep.js), we have to understand the relation between mol patterns and 119 | graphs. 120 | 121 | A graph is pair (G,E) where G is a finite nonempty set of nodes and E is a set of edges. Each edge is a set of two nodes (therefore the nodes have to be different). We say that an edge links the two nodes. There are no edges which connect a node with itself. 122 | 123 | An oriented graph is a different mathematical object. It is a pair of functions (source, target) defined on a set E of edges, with values in a set G of nodes. An oriented graph admits edges with the source and target being the same node. If an oriented graph does not have such edges, then it can be turned into a graph (as defined previously) by associating to each edge e the set formed by the nodes source(e) and target(e). 124 | 125 | d3 graphs are oriented graphs. See more about d3 graphs in myD3Graph.js. 126 | 127 | However, we use d3 graphs as usual graphs. This is done in the follwoing way. 128 | 129 | First we introduce a set GT of graph node types. Further we exploit the fact that here we use mol node types with valence at most 3 (but the extension to any valence should be obvious). 130 | 131 | If NT is the set of mol node types, then GT is obtained from NT by adding 3 new types: 132 | - "in", "middle", "out". 133 | 134 | We also have a predicate isCenter, which is true for any graph node type which is not "in", "middle" or "out". We shall say that a graph node is a center if it has a graph node type for which isCenter is true. 135 | 136 | A node which is not a center is called a port node. 137 | 138 | GT is kept in the vector graphNodes. 139 | */ 140 | 141 | // added S,K,I for chemSKI 142 | 143 | var graphNodes = ["in","out","middle","L","A","FI","D","FOE","FOX","FO","T","FRIN","FROUT","Arrow","GAMMA","DELTA","S","K","I"]; 144 | 145 | /* 146 | Because we want to represent graphically the nodes, we associate colors to each graph node type. Remark that we don't use a bijection from the graph node types to the colors. 147 | 148 | Each node of the graph (which are goind to define from a mol pattern) is graphically represented by a colored circle. The radius of the circle is a function of the predicate isCenter, that is center nodes have a radius and the port nodes have a different radius. 149 | */ 150 | 151 | // added S,K,I for chemSKI 152 | 153 | var graphNodesColors = [yellowCol,blueCol,middleCol,redCol,greenCol,violetCol,blueCol,yellowCol,orangeCol,orange2Col,"#345",yellowCol,blueCol,whiteCol,"#ff9933","#0099ff",orange2Col,"#345",whiteCol] 154 | 155 | 156 | // used in addNodeAndEdges function 157 | 158 | /* 159 | To each mol node we associate a graph. The association is the following. 160 | 161 | There is a center graph according to the mol node type. There are port nodes, one for each letter of the mol node word. Here we exploit the fact that we use mol nodes of valence at most 3. 162 | 163 | The function which associates a vector of graph node types (among "in", "out" or "middle") to the valence of a mol node is nodePortTypes. 164 | */ 165 | 166 | var nodePortTypes = [["in"],["in","out"],["in","middle","out"]]; 167 | 168 | /* 169 | So the first port node is always "in", the last one (for valence at least 2) is always "out", the remaining port is "middle". 170 | 171 | The graph associated to a mol node is formed by the center node and the port nodes, with edges from the center nodes to the port nodes. 172 | Specifically, we draw a center graph node as an "o" and a port node as a dash "|" with a number (starting from 1). 173 | 174 | Then a mol node of valence 1, of mol node type "t" and edge "a" 175 | 176 | t a 177 | 178 | becomes a graph 179 | 180 | 1 181 | t o--|-- a 182 | "in" 183 | 184 | A mol node of valence 2, of mol node type "t" and edges "ab" 185 | 186 | t a b 187 | 188 | becomes a graph 189 | 190 | 191 | 1 2 192 | a --|--o--|-- b 193 | "in" t "out" 194 | 195 | A mol node of valence 3, of mol type "t" and edges "abc" 196 | 197 | t a b c 198 | 199 | becomes a graph 200 | 201 | 202 | 203 | b 204 | 2_/ "middle" 205 | / 206 | 1 / 207 | a --|----o t 208 | "in" \ 209 | \_3 "out" 210 | \ 211 | c 212 | 213 | 214 | 215 | 216 | To the mol pattern we associate the graph formed by (the graphs of) all mol nodes, with edges connecting port nodes which have the same edge tag. The definition of a mol pattern assures us that this is possible, because each edge tag cannot occur more than twice. 217 | 218 | Let us come back to the d3 graphs, which are oriented. The orientation (i.e. which node is the source and which one is the target) wil be neglected. This is possible because the graphs which we obtain do not have edges which connect a node with itself. Indeed, even if an edge tag appears twice in the same mol node, the corresponding edge connects different node ports. 219 | 220 | See the functions: 221 | - getLinked, which gives the nodes connected, as sources or targets, to the given node 222 | - findLinkedHalfEdge, which returns the unique other port node which is linked to a port node (actually the 223 | first found other port node) 224 | - findLinkedCenter, which returns the only center node linked (or identical with) the given node 225 | - findLinkedOfType, which returns the only node of given type, linked to the given node. 226 | 227 | 228 | */ 229 | 230 | -------------------------------------------------------------------------------- /js/pagelook-lab.js: -------------------------------------------------------------------------------- 1 | /* 2 | page look (buttons, etc), import-export mol 3 | 4 | forked from https://github.com/mbuliga/quinegraphs/blob/master/js/pagelook-lab.js 5 | 6 | */ 7 | // last updated: 17.03.2020 8 | 9 | var versusVar = "

VS.

"; 10 | var transformList = []; 11 | 12 | function chemistryChoice() { 13 | 14 | // added chemistryChoice 15 | if (isChemlambda == 1) { 16 | // which chemistries (i.e. graph rewrite systems) we use? 17 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND"]; 18 | } else { 19 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","DICMOD"]; 20 | } 21 | transformList = []; 22 | for (var ichem=0; ichemmol"}, 99 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 100 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 101 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 102 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol>λ"}, 103 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 104 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 105 | ]; 106 | 107 | 108 | var ButtonRandomGraph = [ 109 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"new"}, 110 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 111 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 112 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 113 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 114 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 115 | {"Id":"buttonImportMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {importMolTextarea("inputmol");}, "Text":"input mol"}, 116 | {"Id":"buttonUpdateMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {updateMolTextarea("inputmol");}, "Text":"update"}, 117 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 118 | ]; 119 | 120 | 121 | var ButtonArena = [ 122 | {"Id":"button1", "Class":"image2", "Visibility":"hidden", "Onclick": function () {document.getElementById("listofmols").value = "arena"; setArena(1); selectionStarter();}, "Text":"add"}, 123 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"fight"}, 124 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 125 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 126 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"purge"}, 127 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 128 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 129 | ]; 130 | 131 | var ButtonGreedyAlgorithm = [ 132 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"greedy"}, 133 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 134 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 135 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 136 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 137 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 138 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 139 | ]; 140 | 141 | function showAllButtons(butto) { 142 | for (var i = 0; i < butto.length; i++) { 143 | showButton(butto[i]); 144 | } 145 | } 146 | 147 | function showButton(buttt) { 148 | document.getElementById(buttt.Id).onclick = buttt.Onclick; 149 | document.getElementById(buttt.Id).style.visibility = buttt.Visibility; 150 | document.getElementById(buttt.Id).innerHTML = buttt.Text; 151 | } 152 | 153 | 154 | 155 | function whichButtons(choiceButtons) { 156 | // var choiceButtons = document.getElementById("listofmols").value; 157 | switch (choiceButtons) { 158 | 159 | case "lambdanote": 160 | var selectedButtons = ButtonLambda; 161 | break; 162 | 163 | 164 | case "arena": 165 | var selectedButtons = ButtonArena; 166 | break; 167 | 168 | case "greedy": 169 | var selectedButtons = ButtonGreedyAlgorithm; 170 | break; 171 | 172 | case "random_16_quine_A_L_FI_FO_duplicate": 173 | var selectedButtons = ButtonRandomGraph; 174 | break; 175 | 176 | case "random_egg_A_L_FI_FO": 177 | var selectedButtons = ButtonRandomGraph; 178 | break; 179 | 180 | case "random_egg_A_L_FI_FOE": 181 | var selectedButtons = ButtonRandomGraph; 182 | break; 183 | 184 | case "random_10_quine_bubbles": 185 | var selectedButtons = ButtonRandomGraph; 186 | break; 187 | 188 | case "random_egg_G_G_D_D": 189 | var selectedButtons = ButtonRandomGraph; 190 | break; 191 | 192 | default: 193 | var selectedButtons = ButtonOriginal; 194 | break; 195 | } 196 | showAllButtons(selectedButtons); 197 | } 198 | 199 | function voidMolToScreenAfter() { 200 | document.getElementById("puttransformcachealt").innerHTML = ""; 201 | document.getElementById("chosentransform").innerHTML = ""; 202 | document.getElementById("puttransformcachealtafter").innerHTML = ""; 203 | if (arenaVar == 0) { 204 | document.getElementById("molexport").innerHTML = ""; 205 | document.getElementById("molexportafter").innerHTML = ""; 206 | } else { 207 | document.getElementById("molexport").innerHTML += "
"; 208 | document.getElementById("molexportafter").innerHTML += "
"; 209 | } 210 | } 211 | 212 | function setSpeed(newSpeed) { 213 | speed = newSpeed; 214 | } 215 | 216 | function setStart(varStart) { 217 | startVar = varStart; 218 | } 219 | 220 | function setArena(varArena) { 221 | arenaVar = varArena; 222 | } 223 | 224 | function setComb(newComb) { 225 | combOnly = newComb; 226 | } 227 | 228 | function setAge(newAge) { 229 | age = newAge; 230 | } 231 | 232 | function setOlder() { 233 | if (olderFirst == 1) { 234 | olderFirst = 0; 235 | document.getElementById("agetext").innerHTML = "random choices "; 236 | } else { 237 | olderFirst = 1; 238 | document.getElementById("agetext").innerHTML = "older is first "; 239 | } 240 | } 241 | 242 | -------------------------------------------------------------------------------- /js/pagelook.js: -------------------------------------------------------------------------------- 1 | /* 2 | page look (buttons, etc), import-export mol 3 | 4 | forked from https://github.com/mbuliga/quinegraphs/blob/master/js/pagelook.js 5 | 6 | */ 7 | // last updated: 15.08.2020 8 | 9 | var versusVar = "

VS.

"; 10 | var transformList = []; 11 | 12 | function chemistryChoice() { 13 | 14 | // added chemistryChoice 15 | if (isChemlambda == 1) { 16 | // which chemistries (i.e. graph rewrite systems) we use? 17 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND","CHEMSKI"]; 18 | } else { 19 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","DICMOD"]; 20 | } 21 | transformList = []; 22 | for (var ichem=0; ichemmol"}, 148 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 149 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 150 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 151 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol>λ"}, 152 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 153 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChem();}, "Text":"change"}, 154 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 155 | ]; 156 | 157 | var ButtonICLambda = [ 158 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); ic2chem(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"IC>chemλ"}, 159 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 160 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 161 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); }, "Text":"step"}, 162 | // {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol>λ"}, 163 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 164 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChem();}, "Text":"change"}, 165 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 166 | ]; 167 | 168 | var ButtonRandomGraph = [ 169 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"new"}, 170 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 171 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 172 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 173 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 174 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 175 | // {"Id":"buttonImportMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {importMolTextarea("inputmol");}, "Text":"input mol"}, 176 | // {"Id":"buttonUpdateMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {updateMolTextarea("inputmol");}, "Text":"update"}, 177 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 178 | ]; 179 | 180 | 181 | var ButtonArena = [ 182 | {"Id":"button1", "Class":"image2", "Visibility":"hidden", "Onclick": function () {document.getElementById("listofmols").value = "arena"; setArena(1); selectionStarter();}, "Text":"add"}, 183 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"fight"}, 184 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 185 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 186 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"purge"}, 187 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 188 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 189 | ]; 190 | 191 | var ButtonGreedyAlgorithm = [ 192 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"greedy"}, 193 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 194 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 195 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 196 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 197 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 198 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 199 | ]; 200 | 201 | function showAllButtons(butto) { 202 | for (var i = 0; i < butto.length; i++) { 203 | showButton(butto[i]); 204 | } 205 | } 206 | 207 | function showButton(buttt) { 208 | document.getElementById(buttt.Id).onclick = buttt.Onclick; 209 | document.getElementById(buttt.Id).style.visibility = buttt.Visibility; 210 | document.getElementById(buttt.Id).innerHTML = buttt.Text; 211 | } 212 | 213 | 214 | 215 | function whichButtons(choiceButtons) { 216 | // var choiceButtons = document.getElementById("listofmols").value; 217 | switch (choiceButtons) { 218 | 219 | case "dirvschem": 220 | var selectedButtons = ButtonICLambda; 221 | break; 222 | 223 | case "lambdanote": 224 | var selectedButtons = ButtonLambda; 225 | break; 226 | 227 | 228 | case "arena": 229 | var selectedButtons = ButtonArena; 230 | break; 231 | 232 | case "greedy": 233 | var selectedButtons = ButtonGreedyAlgorithm; 234 | break; 235 | 236 | case "random_16_quine_A_L_FI_FO_duplicate": 237 | var selectedButtons = ButtonRandomGraph; 238 | break; 239 | 240 | case "random_egg_A_L_FI_FO": 241 | var selectedButtons = ButtonRandomGraph; 242 | break; 243 | 244 | case "random_egg_A_L_FI_FOE": 245 | var selectedButtons = ButtonRandomGraph; 246 | break; 247 | 248 | case "random_10_quine_bubbles": 249 | var selectedButtons = ButtonRandomGraph; 250 | break; 251 | 252 | case "random_egg_G_G_D_D": 253 | var selectedButtons = ButtonRandomGraph; 254 | break; 255 | 256 | default: 257 | var selectedButtons = ButtonOriginal; 258 | break; 259 | } 260 | showAllButtons(selectedButtons); 261 | } 262 | 263 | function voidMolToScreenAfter() { 264 | document.getElementById("puttransformcachealt").innerHTML = ""; 265 | document.getElementById("chosentransform").innerHTML = ""; 266 | document.getElementById("puttransformcachealtafter").innerHTML = ""; 267 | if (arenaVar == 0) { 268 | document.getElementById("molexport").innerHTML = ""; 269 | document.getElementById("molexportafter").innerHTML = ""; 270 | } else { 271 | document.getElementById("molexport").innerHTML += "
"; 272 | document.getElementById("molexportafter").innerHTML += "
"; 273 | } 274 | } 275 | 276 | function setSpeed(newSpeed) { 277 | speed = newSpeed; 278 | } 279 | 280 | function setStart(varStart) { 281 | startVar = varStart; 282 | } 283 | 284 | function setArena(varArena) { 285 | arenaVar = varArena; 286 | } 287 | 288 | function setComb(newComb) { 289 | combOnly = newComb; 290 | } 291 | 292 | function setAge(newAge) { 293 | age = newAge; 294 | } 295 | 296 | function setOlder() { 297 | if (olderFirst == 1) { 298 | olderFirst = 0; 299 | document.getElementById("agetext").innerHTML = "random choices "; 300 | } else { 301 | olderFirst = 1; 302 | document.getElementById("agetext").innerHTML = "older is first "; 303 | } 304 | } 305 | 306 | function setChem() { 307 | if (isChemlambda == 1) { 308 | isChemlambda = 0; 309 | chemistryChoice(); 310 | document.getElementById("chemtext").innerHTML = "dirIC"; 311 | } else { 312 | isChemlambda = 1; 313 | chemistryChoice(); 314 | document.getElementById("chemtext").innerHTML = "chemλ"; 315 | } 316 | 317 | } 318 | 319 | -------------------------------------------------------------------------------- /js/pagelook-vs.js: -------------------------------------------------------------------------------- 1 | /* 2 | page look (buttons, etc), import-export mol 3 | 4 | forked from https://github.com/mbuliga/quinegraphs/blob/master/js/pagelook-vs.js 5 | 6 | */ 7 | 8 | // last updated: 05.05.2020 9 | 10 | var versusVar = "

VS.

"; 11 | var transformList = []; 12 | 13 | function chemistryChoice() { 14 | 15 | // added chemistryChoice 16 | if (isChemlambda == 1) { 17 | // which chemistries (i.e. graph rewrite systems) we use? 18 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND","CHEMSKI"]; 19 | } else { 20 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","DICMOD"]; 21 | } 22 | transformList = []; 23 | for (var ichem=0; ichemmol"}, 126 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 127 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 128 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 129 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol>λ"}, 130 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 131 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChem();}, "Text":"change"}, 132 | // {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 133 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 134 | ]; 135 | 136 | 137 | var ButtonSKILambda = [ 138 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); lambdaToMol(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"λSKI> mol"}, 139 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 140 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 141 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 142 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol> λSKI"}, 143 | // {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 144 | // {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChem();}, "Text":"change"}, 145 | // {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 146 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 147 | ]; 148 | 149 | var ButtonICLambda = [ 150 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); ic2chem(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"IC>chemλ"}, 151 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 152 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 153 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); }, "Text":"step"}, 154 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); molSelect(); exportMolToScreen()}, "Text":"reload"}, 155 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 156 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChem();}, "Text":"change"}, 157 | {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 158 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 159 | ]; 160 | 161 | var ButtonRandomGraph = [ 162 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); ic2chem(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"IC>chemλ"}, 163 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"new"}, 164 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 165 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 166 | // {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 167 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 168 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 169 | // {"Id":"buttonImportMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {importMolTextarea("inputmol");}, "Text":"input mol"}, 170 | // {"Id":"buttonUpdateMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {updateMolTextarea("inputmol");}, "Text":"update"}, 171 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 172 | ]; 173 | 174 | 175 | var ButtonArena = [ 176 | {"Id":"button1", "Class":"image2", "Visibility":"hidden", "Onclick": function () {document.getElementById("listofmols").value = "arena"; setArena(1); selectionStarter();}, "Text":"add"}, 177 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"fight"}, 178 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 179 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 180 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"purge"}, 181 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 182 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 183 | ]; 184 | 185 | var ButtonGreedyAlgorithm = [ 186 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"greedy"}, 187 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 188 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 189 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 190 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 191 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 192 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 193 | ]; 194 | 195 | function showAllButtons(butto) { 196 | for (var i = 0; i < butto.length; i++) { 197 | showButton(butto[i]); 198 | } 199 | } 200 | 201 | function showButton(buttt) { 202 | document.getElementById(buttt.Id).onclick = buttt.Onclick; 203 | document.getElementById(buttt.Id).style.visibility = buttt.Visibility; 204 | document.getElementById(buttt.Id).innerHTML = buttt.Text; 205 | } 206 | 207 | 208 | 209 | function whichButtons(choiceButtons) { 210 | // var choiceButtons = document.getElementById("listofmols").value; 211 | switch (choiceButtons) { 212 | 213 | case "icvschem": 214 | var selectedButtons = ButtonICLambda; 215 | break; 216 | 217 | case "lambdanote": 218 | var selectedButtons = ButtonLambda; 219 | break; 220 | 221 | case "SKInote": 222 | var selectedButtons = ButtonSKILambda; 223 | break; 224 | 225 | case "arena": 226 | var selectedButtons = ButtonArena; 227 | break; 228 | 229 | case "greedy": 230 | var selectedButtons = ButtonGreedyAlgorithm; 231 | break; 232 | 233 | case "random_16_quine_A_L_FI_FO_duplicate": 234 | var selectedButtons = ButtonRandomGraph; 235 | break; 236 | 237 | case "random_egg_A_L_FI_FO": 238 | var selectedButtons = ButtonRandomGraph; 239 | break; 240 | 241 | case "random_egg_A_L_FI_FOE": 242 | var selectedButtons = ButtonRandomGraph; 243 | break; 244 | 245 | case "random_10_quine_bubbles": 246 | var selectedButtons = ButtonRandomGraph; 247 | break; 248 | 249 | case "random_egg_G_G_D_D": 250 | var selectedButtons = ButtonRandomGraph; 251 | break; 252 | 253 | default: 254 | var selectedButtons = ButtonICLambda; 255 | break; 256 | } 257 | showAllButtons(selectedButtons); 258 | } 259 | 260 | function voidMolToScreenAfter() { 261 | document.getElementById("puttransformcachealt").innerHTML = ""; 262 | document.getElementById("chosentransform").innerHTML = ""; 263 | document.getElementById("puttransformcachealtafter").innerHTML = ""; 264 | if (arenaVar == 0) { 265 | document.getElementById("molexport").innerHTML = ""; 266 | document.getElementById("molexportafter").innerHTML = ""; 267 | } else { 268 | document.getElementById("molexport").innerHTML += "
"; 269 | document.getElementById("molexportafter").innerHTML += "
"; 270 | } 271 | } 272 | 273 | function setSpeed(newSpeed) { 274 | speed = newSpeed; 275 | } 276 | 277 | function setStart(varStart) { 278 | startVar = varStart; 279 | } 280 | 281 | function setArena(varArena) { 282 | arenaVar = varArena; 283 | } 284 | 285 | function setComb(newComb) { 286 | combOnly = newComb; 287 | } 288 | 289 | function setAge(newAge) { 290 | age = newAge; 291 | } 292 | 293 | function setOlder() { 294 | if (olderFirst == 1) { 295 | olderFirst = 0; 296 | document.getElementById("agetext").innerHTML = "random choices "; 297 | } else { 298 | olderFirst = 1; 299 | document.getElementById("agetext").innerHTML = "older is first "; 300 | } 301 | } 302 | 303 | function setChem() { 304 | if (isChemlambda == 1) { 305 | isChemlambda = 0; 306 | chemistryChoice(); 307 | document.getElementById("chemtext").innerHTML = "dirIC"; 308 | } else { 309 | isChemlambda = 1; 310 | chemistryChoice(); 311 | document.getElementById("chemtext").innerHTML = "chemλ"; 312 | } 313 | 314 | } 315 | 316 | 317 | function setMetabo() { 318 | if (metabo == 1) { 319 | metabo = 0; 320 | document.getElementById("metabotext").innerHTML = "colored nodes"; 321 | } else { 322 | metabo = 1; 323 | document.getElementById("metabotext").innerHTML = "uncolored nodes"; 324 | } 325 | 326 | } 327 | 328 | -------------------------------------------------------------------------------- /js/ioprep.js: -------------------------------------------------------------------------------- 1 | // IO and preparation functions 2 | // 3 | // modification for decorations with lambda terms of the edges, for the GLOBALFO of COMBINALAMBDA 4 | // 5 | // forked from https://github.com/mbuliga/quinegraphs/blob/master/js/ioprep.js 6 | // 7 | // last updated: 31.05.2023, modified showBalanceOfNodes 8 | 9 | 10 | 11 | 12 | // IO functions 13 | 14 | 15 | /* 16 | Functions which convert mols and mol patterns from records into vectors of mol modes. 17 | 18 | */ 19 | 20 | 21 | /* Splits a record str into a vector of lines by using the separator chara. 22 | Each lines element is split into a vector, by using the space character 23 | (after supplimentary spaces are trimmed). 24 | 25 | */ 26 | 27 | function importMolVector(str,chara) { 28 | var lines = str.split(chara); 29 | var output = [], line; 30 | 31 | for (var i=0; i"). 86 | 87 | This creates a graph which does not have free edges. 88 | 89 | */ 90 | 91 | 92 | 93 | function importMol(str) { 94 | 95 | importMolGen(str,"\n"); 96 | var molIntermed = exportMol(); 97 | removeAllNodes(); 98 | importMolGen(molIntermed,"
"); 99 | } 100 | 101 | /* The same as importMol, but adapted to imports from molLibrary, 102 | i.e. with separator "^". Same effect as importMol. 103 | 104 | */ 105 | 106 | function importMolFromLib(str) { 107 | 108 | importMolGen(str,"^"); 109 | var molIntermed = exportMol(); 110 | removeAllNodes(); 111 | importMolGen(molIntermed,"
"); 112 | } 113 | 114 | function importMolTextarea(textarea) { 115 | setSpeed(0); 116 | // added age reset 117 | setAge(0); 118 | removeAllNodes(); 119 | var molIn = document.getElementById(textarea).value; 120 | molIn = molIn.replace(/\^/g,"\n"); 121 | molIn = molIn.replace(/
/g,"\n"); 122 | molIn = molIn.replace(/[^a-z.A-Z\\0-9\s\n]/g, ""); 123 | var molCode = molIn.replace(/\n/g,"\^"); 124 | importMol(molIn); 125 | exportMolToScreen(); 126 | exportMolToScreenAfter(); 127 | document.getElementById("molyoulookat").innerHTML = molCode; 128 | } 129 | 130 | function updateMolTextarea(textarea) { 131 | setSpeed(0); 132 | // added age reset 133 | // setAge(0); 134 | removeAllNodes(); 135 | var molIn = document.getElementById("molexportafter").innerHTML; 136 | if (molIn == "") molIn = document.getElementById("molexport").innerHTML; 137 | molIn = molIn.replace(/\^/g,"\n"); 138 | molIn = molIn.replace(/
/g,"\n"); 139 | molIn = molIn.replace(/[^a-z.A-Z\\0-9\s\n]/g, ""); 140 | var molCode = molIn.replace(/\n/g,"\^"); 141 | importMol(molIn); 142 | exportMolToScreen(); 143 | exportMolToScreenAfter(); 144 | // document.getElementById("molyoulookat").innerHTML = molCode; 145 | var molCodeAr = molCode.split("^"); 146 | var molCodeWfree = ""; 147 | for (var i=0; i" as newline. 175 | 176 | This function also writes the number of center nodes (thus uses the predicate isCenter). 177 | 178 | */ 179 | 180 | 181 | 182 | function exportMol() { 183 | var edgeCount = 0; 184 | var numberOfCenterNodes = 0; 185 | 186 | var result = ""; 187 | var edges = {}; 188 | var addedFR = ""; 189 | var currNode = {}; 190 | 191 | for (var i=0; i"; 222 | } else { 223 | addedFR += "FROUT" + " free" + edgeCount + "
"; 224 | } 225 | // 226 | } 227 | } 228 | } 229 | 230 | line += "
"; 231 | line += addedFR; 232 | result += line; 233 | nodes[i].number = numberOfCenterNodes; 234 | numberOfCenterNodes +=1; 235 | } 236 | } 237 | // updates the d3 db 238 | update(); 239 | // var addToResult = ""; 240 | // addToResult += numberOfCenterNodes + "
"; 241 | // for (var i=0; i"; 243 | // } 244 | // document.getElementById("nodenumber").innerHTML = addToResult; 245 | document.getElementById("nodenumber").innerHTML = numberOfCenterNodes; 246 | 247 | return result; 248 | } 249 | 250 | /* Clears the d3 graph and imports from the molLibrary. 251 | Exception: if it is used in the arena.html, it adds the d3 graph 252 | from the imported mol to the actual graph. 253 | 254 | */ 255 | function doClearImportFromLib(molname) { 256 | var molL = molLibrary(molname); 257 | var molCom = molComments(molname); 258 | if (arenaVar == 0) { 259 | removeAllNodes(); 260 | document.getElementById("molyoulookat").innerHTML = molL; 261 | document.getElementById("comments").innerHTML = molCom; 262 | } else { 263 | document.getElementById("molyoulookat").innerHTML = ""; 264 | if (molname != "arena") { 265 | fightersVar += 1; 266 | if (fightersVar <= 1) { 267 | var versusAdd = "
"; 268 | } else { 269 | var versusAdd = versusVar; 270 | } 271 | document.getElementById("comments").innerHTML += versusAdd + molname; 272 | } 273 | } 274 | importMolFromLib(molL); 275 | } 276 | 277 | /* 278 | Clears the d3 graph. 279 | Stops the simulation. 280 | Resets age. 281 | Imports the mol record from the html element with id = "molyoulookat". 282 | Exports the mol to screen. 283 | */ 284 | 285 | function reloadCode() { 286 | removeAllNodes(); 287 | setSpeed(0); 288 | // added age reset 289 | setAge(0); 290 | if (arenaVar == 0) { 291 | voidMolToScreenAfter(); 292 | } else { 293 | document.getElementById("puttransformcachealt").innerHTML = ""; 294 | document.getElementById("chosentransform").innerHTML = ""; 295 | document.getElementById("puttransformcachealtafter").innerHTML = ""; 296 | document.getElementById("molexport").innerHTML = ""; 297 | document.getElementById("molexportafter").innerHTML = ""; 298 | document.getElementById("comments").innerHTML = ""; 299 | fightersVar = 0; 300 | } 301 | var molL = document.getElementById("molyoulookat").innerHTML; 302 | importMolFromLib(molL); 303 | exportMolToScreen(); 304 | } 305 | 306 | /* 307 | Stops the simulation. 308 | Imports from molLibrary the mol from the menu with doClearImportFromLib. 309 | */ 310 | 311 | function molSelect() { 312 | setSpeed(0); 313 | var molN = document.getElementById("listofmols").value; 314 | doClearImportFromLib(molN); 315 | var initNrOfCenterNodes = Math.floor(nodes.length / 4); 316 | document.getElementById("nodenumber").innerHTML = initNrOfCenterNodes; 317 | } 318 | 319 | // take the mol from "molexportafter", if it is not void, else take it from "molexport" 320 | 321 | function takeMolFromScreen() { 322 | 323 | var result = document.getElementById("molexportafter").innerHTML; 324 | if (result == "") { result = document.getElementById("molexport").innerHTML;} 325 | return result; 326 | 327 | } 328 | 329 | /* 330 | Imports/exports mol from/to textarea. 331 | 332 | 333 | function doImport(textarea) { 334 | importMol(textarea.value); 335 | } 336 | 337 | function doExport(textarea) { 338 | textarea.value = exportMol(); 339 | } 340 | 341 | */ 342 | 343 | function exportMolToScreen() { 344 | document.getElementById("molexport").innerHTML = exportMol(); 345 | } 346 | 347 | function exportMolToScreenAfter() { 348 | document.getElementById("molexportafter").innerHTML = exportMol(); 349 | } 350 | 351 | function showImportError(e) { 352 | alert(e); 353 | } 354 | 355 | /* 356 | takes screenshots as sgv. Needs modifications. 357 | */ 358 | 359 | function screenShot() { 360 | 361 | var photo = document.getElementById("svgdiv").innerHTML; 362 | 363 | var wrap = "
\n "; 364 | 365 | wrap = wrap + photo; 366 | 367 | output = wrap + "\n \n
"; 368 | 369 | var dimensions = "\"width=" + w + ",height=" + h + "\""; 370 | 371 | document.getElementById("photoTaken").innerHTML = output; 372 | 373 | /* 374 | var myWindow = window.open("photobooth.html", "Photo Booth", function () { return dimensions;}); 375 | 376 | myWindow.document.write(output); 377 | */ 378 | } 379 | 380 | 381 | 382 | // parser from IC to chemlambda 383 | // author: Marius Buliga 384 | // last updated: 05.05.2020 385 | 386 | function ic2chem() { 387 | 388 | 389 | // take the mol from "molexport", if it is not void, else take it from "molexportafter" 390 | 391 | var molString = document.getElementById("molexport").innerHTML; 392 | if (molString == "") { molString = document.getElementById("molexport").innerHTML;} 393 | var molStringVect = molString.split("
"); 394 | 395 | // transform it into an array 396 | var molArray = [], molLine = []; 397 | 398 | for (var i=0; i"; 434 | translation += "FI " + portSignb[0] + portb + " " + portSignc[0] + portc + " " + portSigna[1] + porta + "
"; 435 | countIC = 1; 436 | break; 437 | 438 | case "DELTA": 439 | porta = molArray[i][1]; portSigna = edgePar(porta); 440 | portb = molArray[i][2]; portSignb = edgePar(portb); 441 | portc = molArray[i][3]; portSignc = edgePar(portc); 442 | translation += "A " + portSigna[0] + porta + " " + portSignb[0] + portb + " " + portSignc[1] + portc + "
"; 443 | translation += "L " + portSignc[0] + portc + " " + portSignb[1] + portb + " " + portSigna[1] + porta + "
"; 444 | countIC = 1; 445 | break; 446 | 447 | case "Arrow": 448 | porta = molArray[i][1]; portSigna = edgePar(porta); 449 | portb = molArray[i][2]; portSignb = edgePar(portb); 450 | translation += "Arrow " + portSigna[0] + porta + " " + portSignb[1] + portb + "
"; 451 | translation += "Arrow " + portSigna[1] + porta + " " + portSignb[0] + portb + "
"; 452 | break; 453 | 454 | case "T": 455 | porta = molArray[i][1]; portSigna = edgePar(porta); 456 | translation += "T " + portSigna[0] + porta + "
"; 457 | translation += "T " + portSigna[1] + porta + "
"; 458 | break; 459 | } 460 | 461 | } 462 | 463 | 464 | if (countIC == 1) { 465 | translation = translation.replace(/
/g, "^"); 466 | } else { 467 | translation = molString.replace(/
/g, "^"); 468 | 469 | } 470 | document.getElementById("molyoulookat").innerHTML = translation; 471 | 472 | 473 | } 474 | 475 | 476 | function showBalanceOfNodes() { 477 | var textB = ""; var costcount = 0; var negative = 0; 478 | 479 | 480 | 481 | for (var ibil=0; ibil < Tokens.length; ibil++) { 482 | negative = 0 - balanceOfTokens[ibil]; 483 | // costcount = costcount + (negative * TokensCost[ibil]); 484 | costcount = costcount + (balanceOfTokens[ibil] * TokensCost[ibil]); 485 | textB = textB + Tokens[ibil] + ": " + balanceOfTokens[ibil] + "
"; 486 | } 487 | textB = "Edges won: " + costcount + "

" + textB; 488 | document.getElementById("errors").innerHTML = textB; 489 | } 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | -------------------------------------------------------------------------------- /js/pagelook-skilambda.js: -------------------------------------------------------------------------------- 1 | /* 2 | page look (buttons, etc), import-export mol 3 | 4 | forked from https://github.com/mbuliga/quinegraphs/blob/master/js/pagelook-vs.js 5 | 6 | uses toggle between chemSKI and chemSKI+lambda 7 | 8 | */ 9 | 10 | // last updated: 29.05.2023 11 | 12 | var versusVar = "

VS.

"; 13 | var transformList = []; 14 | 15 | function chemistryChoice() { 16 | 17 | // added chemistryChoice 18 | if (isChemlambda == 1) { 19 | // which chemistries (i.e. graph rewrite systems) we use? 20 | // graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND","CHEMSKI"]; 21 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND","CHEMSKI"]; 22 | } else { 23 | graphRewriteSystems = ["T","COMB","IC","CHEMLAMBDABARE","CHEMLAMBDAEND","CHEMSKI+LAMBDA"]; 24 | } 25 | transformList = []; 26 | for (var ichem=0; ichemmol"}, 129 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 130 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 131 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 132 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol>λ"}, 133 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 134 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChemPlus();}, "Text":"change"}, 135 | // {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 136 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 137 | ]; 138 | 139 | 140 | var ButtonSKILambda = [ 141 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); lambdaToMol(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); setBalanceOfNodes();showBalanceOfNodes(); loop();}, "Text":"λSKI> mol"}, 142 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); setBalanceOfNodes();showBalanceOfNodes(); loop();}, "Text":"start"}, 143 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 144 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); decoratorLambda();}, "Text":"step"}, 145 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); decoratorLambda();}, "Text":"mol> λSKI"}, 146 | // {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 147 | {"Id":"whichChem2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChemPlus();}, "Text":"change"}, 148 | // {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 149 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 150 | ]; 151 | 152 | var ButtonICLambda = [ 153 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); ic2chem(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"IC>chemλ"}, 154 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"start"}, 155 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 156 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2(); }, "Text":"step"}, 157 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); molSelect(); exportMolToScreen()}, "Text":"reload"}, 158 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 159 | {"Id":"whichChem", "Class":"image2", "Visibility":"visible", "Onclick": function () {setChemPlus();}, "Text":"change"}, 160 | {"Id":"whichMetabo", "Class":"image2", "Visibility":"visible", "Onclick": function () {setMetabo();}, "Text":"change"}, 161 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 162 | ]; 163 | 164 | var ButtonRandomGraph = [ 165 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); ic2chem(); reloadCode(); setComb(1);setSpeed(1); setStart(1); chemistryChoice(); loop();}, "Text":"IC>chemλ"}, 166 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"new"}, 167 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 168 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 169 | // {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 170 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 171 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 172 | // {"Id":"buttonImportMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {importMolTextarea("inputmol");}, "Text":"input mol"}, 173 | // {"Id":"buttonUpdateMol", "Class":"image2", "Visibility":"visible", "Onclick": function () {updateMolTextarea("inputmol");}, "Text":"update"}, 174 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 175 | ]; 176 | 177 | 178 | var ButtonArena = [ 179 | {"Id":"button1", "Class":"image2", "Visibility":"hidden", "Onclick": function () {document.getElementById("listofmols").value = "arena"; setArena(1); selectionStarter();}, "Text":"add"}, 180 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"fight"}, 181 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 182 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 183 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"purge"}, 184 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 185 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 186 | ]; 187 | 188 | var ButtonGreedyAlgorithm = [ 189 | {"Id":"button3", "Class":"image2", "Visibility":"visible", "Onclick": function () {selectionStarter();}, "Text":"greedy"}, 190 | {"Id":"button0", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(1); setStart(1); loop();}, "Text":"start"}, 191 | {"Id":"button1", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0);}, "Text":"stop"}, 192 | {"Id":"button2", "Class":"image2", "Visibility":"visible", "Onclick": function () {setStart(0); loop2();}, "Text":"step"}, 193 | {"Id":"button4", "Class":"image2", "Visibility":"visible", "Onclick": function () {setSpeed(0); setStart(0); reloadCode();}, "Text":"reload"}, 194 | {"Id":"buttonAge", "Class":"image2", "Visibility":"visible", "Onclick": function () {setOlder();}, "Text":"change"}, 195 | // {"Id":"buttonShot", "Class":"image2", "Visibility":"visible", "Onclick": function () {screenShot();}, "Text":"photo"} 196 | ]; 197 | 198 | function showAllButtons(butto) { 199 | for (var i = 0; i < butto.length; i++) { 200 | showButton(butto[i]); 201 | } 202 | } 203 | 204 | function showButton(buttt) { 205 | document.getElementById(buttt.Id).onclick = buttt.Onclick; 206 | document.getElementById(buttt.Id).style.visibility = buttt.Visibility; 207 | document.getElementById(buttt.Id).innerHTML = buttt.Text; 208 | } 209 | 210 | 211 | 212 | function whichButtons(choiceButtons) { 213 | // var choiceButtons = document.getElementById("listofmols").value; 214 | switch (choiceButtons) { 215 | 216 | case "icvschem": 217 | var selectedButtons = ButtonICLambda; 218 | break; 219 | 220 | case "lambdanote": 221 | var selectedButtons = ButtonLambda; 222 | break; 223 | 224 | case "SKInote": 225 | var selectedButtons = ButtonSKILambda; 226 | break; 227 | 228 | case "arena": 229 | var selectedButtons = ButtonArena; 230 | break; 231 | 232 | case "greedy": 233 | var selectedButtons = ButtonGreedyAlgorithm; 234 | break; 235 | 236 | case "random_16_quine_A_L_FI_FO_duplicate": 237 | var selectedButtons = ButtonRandomGraph; 238 | break; 239 | 240 | case "random_egg_A_L_FI_FO": 241 | var selectedButtons = ButtonRandomGraph; 242 | break; 243 | 244 | case "random_egg_A_L_FI_FOE": 245 | var selectedButtons = ButtonRandomGraph; 246 | break; 247 | 248 | case "random_10_quine_bubbles": 249 | var selectedButtons = ButtonRandomGraph; 250 | break; 251 | 252 | case "random_egg_G_G_D_D": 253 | var selectedButtons = ButtonRandomGraph; 254 | break; 255 | 256 | default: 257 | var selectedButtons = ButtonICLambda; 258 | break; 259 | } 260 | showAllButtons(selectedButtons); 261 | } 262 | 263 | function voidMolToScreenAfter() { 264 | document.getElementById("puttransformcachealt").innerHTML = ""; 265 | document.getElementById("chosentransform").innerHTML = ""; 266 | document.getElementById("puttransformcachealtafter").innerHTML = ""; 267 | if (arenaVar == 0) { 268 | document.getElementById("molexport").innerHTML = ""; 269 | document.getElementById("molexportafter").innerHTML = ""; 270 | } else { 271 | document.getElementById("molexport").innerHTML += "
"; 272 | document.getElementById("molexportafter").innerHTML += "
"; 273 | } 274 | } 275 | 276 | function setSpeed(newSpeed) { 277 | speed = newSpeed; 278 | } 279 | 280 | function setStart(varStart) { 281 | startVar = varStart; 282 | } 283 | 284 | function setArena(varArena) { 285 | arenaVar = varArena; 286 | } 287 | 288 | function setComb(newComb) { 289 | combOnly = newComb; 290 | } 291 | 292 | function setAge(newAge) { 293 | age = newAge; 294 | } 295 | 296 | function setOlder() { 297 | if (olderFirst == 1) { 298 | olderFirst = 0; 299 | document.getElementById("agetext").innerHTML = "random choices "; 300 | } else { 301 | olderFirst = 1; 302 | document.getElementById("agetext").innerHTML = "older is first "; 303 | } 304 | } 305 | 306 | function setChemPlus() { 307 | setSpeed(0); 308 | setStart(0); 309 | 310 | var whatsInThere = document.getElementById('inputlambda').value; 311 | if (isChemlambda == 1) { 312 | isChemlambda = 0; 313 | chemistryChoice(); 314 | document.getElementById("chemtext").innerHTML = "chemSKI+λ"; 315 | 316 | } else { 317 | isChemlambda = 1; 318 | chemistryChoice(); 319 | document.getElementById("chemtext").innerHTML = "chemSKI"; 320 | 321 | } 322 | if (whatsInThere == "") { 323 | voidMolToScreenAfter(); 324 | molSelect(); 325 | exportMolToScreen(); 326 | } else { 327 | lambdaToMol(); 328 | reloadCode(); 329 | } 330 | setComb(1);setSpeed(1); setStart(1); setBalanceOfNodes(); showBalanceOfNodes(); loop(); 331 | 332 | } 333 | 334 | 335 | function setMetabo() { 336 | if (metabo == 1) { 337 | metabo = 0; 338 | document.getElementById("metabotext").innerHTML = "colored nodes"; 339 | } else { 340 | metabo = 1; 341 | document.getElementById("metabotext").innerHTML = "uncolored nodes"; 342 | } 343 | } 344 | 345 | function setBalanceOfNodes() { 346 | for (var ibal=0; ibal < balanceOfTokens.length; ibal++) { 347 | balanceOfTokens[ibal] = 0; 348 | } 349 | 350 | } 351 | 352 | -------------------------------------------------------------------------------- /js/myD3Graph.js: -------------------------------------------------------------------------------- 1 | // d3 force graphs related, i.e. visualization + physics 2 | // 3 | // https://github.com/mbuliga/quinegraphs/blob/master/js/myD3Graph.js 4 | // 5 | // last updated: 14.08.2020 6 | // added tag and number fields to nodes and edges, to be used for global fanout GLOBALFO 7 | // added token field to nodes, to be used with tokens 8 | 9 | 10 | /* 11 | Acknowledgement: in my initial treatment 12 | https://github.com/chorasimilarity/chemlambda-gui/tree/gh-pages/dynamic 13 | the rewrites were done using awk programs (because awk has associative arrays which eliminate 14 | the need to use global counters or namings). Then the list of rewrites was embedded into a d3.js 15 | script. This could be then visualized in a browser. 16 | 17 | The advantage was speed, independence on the graphical part and a more flexible program (for example 18 | concerning algorithms of rewrites). It was not good though that the output of the awk scripts was 19 | sometimes punishing for the browser. I used as intermediary the collection of animations 20 | https://chemlambda.github.io/collection.html 21 | and the outputs of experiments with the awk programs are collected in 22 | https://figshare.com/articles/The_Chemlambda_collection_of_simulations/4747390 23 | 24 | However, I needed a more easy to use tool. This was provided by the contribution of ishanpm with his chemlambda-editor 25 | https://github.com/ishanpm/chemlambda-editor 26 | who took the effort to rewrite the reduction and graphical representation in a js-only way. 27 | 28 | Starting from his editor, I further rewritten his js scripts according to my needs, and added more of 29 | them. His contribution which allowed to work in js only is thanked! 30 | 31 | I also thank ishanpm because his initial scripts made me realize I can embedd with very little effort 32 | interaction combinators rewrites. 33 | */ 34 | 35 | 36 | 37 | /* 38 | A d3 graph is an oriented, decorated graph. 39 | */ 40 | 41 | function myGraph(selector) { 42 | 43 | /* 44 | The vector of nodes is nodes. Each node is an object 45 | which has an id, type, screen coordinates x, y, and velocities vx, vy, a links vector and an age. 46 | */ 47 | 48 | // Adds a node. age is from a global variable 49 | // added tag and number fields, see for the global parameters tagIni and numberIni parameters.js 50 | // added token field for the introduction of tokens 51 | this.addNode = function (id, type, x, y) { 52 | nodes.push({"id": id, "type": type, x: x, y: y, vx:0, vy:0, links:[], "age":age, tag:tagIni, number:numberIni, token:tokenIni}); 53 | return nodes[nodes.length-1]; 54 | }; 55 | this.addNodeWithDeco = function (id, type, x, y, deco) { 56 | nodes.push({"id": id, "type": type, x: x, y: y, vx:0, vy:0, links:[], "age":age, tag:deco, number:numberIni, token:tokenIni}); 57 | return nodes[nodes.length-1]; 58 | }; 59 | 60 | // removes nodes based on id 61 | this.removeNode = function (id) { 62 | var n = findNode(id); 63 | while (n.links.length > 0) { 64 | removeLinkIndex(links.indexOf(n.links[0])); 65 | } 66 | nodes.splice(findNodeIndex(id), 1); 67 | }; 68 | 69 | 70 | // removes links based in index 71 | var removeLinkIndex = function(i) { 72 | var slinks = links[i].source.links; 73 | slinks.splice(slinks.indexOf(links[i]), 1); 74 | var tlinks = links[i].target.links; 75 | tlinks.splice(tlinks.indexOf(links[i]), 1); 76 | links.splice(i, 1); 77 | } 78 | 79 | // removes link based on source and target 80 | this.removeLink = function (source, target) { 81 | for (var i = 0; i < links.length; i++) { 82 | if (links[i].source.id == source && links[i].target.id == target) { 83 | removeLinkIndex(i); 84 | break; 85 | } 86 | } 87 | }; 88 | 89 | 90 | // removes all links 91 | this.removeAllLinks = function () { 92 | links.splice(0, links.length); 93 | update(); 94 | }; 95 | 96 | // removes all nodes and all affected links 97 | this.removeAllNodes = function () { 98 | nodes.splice(0, nodes.length); 99 | links.splice(0, links.length); 100 | newNodeIndex = 0; 101 | update(); 102 | }; 103 | 104 | /* 105 | Each link has a source and a target. It also has a value (to be used for graphical purposes) and an age 106 | (from a global variable). 107 | added tag and number 108 | */ 109 | this.addLink = function (source, target, value) { 110 | var nsource = findNode(source); 111 | var ntarget = findNode(target); 112 | var newLink = {"source": nsource, "target": ntarget, "value": value, "age":age, tag:tagIni, number:numberIni}; 113 | nsource.links.push(newLink); 114 | ntarget.links.push(newLink); 115 | links.push(newLink); 116 | }; 117 | 118 | 119 | // finds node based on id 120 | this.findNode = function (id) { 121 | for (var i in nodes) { 122 | if (nodes[i]["id"] === id) return nodes[i]; 123 | } 124 | ; 125 | }; 126 | 127 | // finds the age of a link between nodes with id id1 and id2 128 | this.findLinkAge = function (id1,id2) { 129 | for (var i in links) { 130 | if ((links[i].source == id1 && links[i].target == id2) || (links[i].source == id2 && links[i].target == id1) ) return links[i].age; 131 | } 132 | }; 133 | 134 | // finds the node index of a node with id 135 | var findNodeIndex = function (id) { 136 | for (var i = 0; i < nodes.length; i++) { 137 | if (nodes[i].id == id) { 138 | return i; 139 | } 140 | } 141 | 142 | }; 143 | 144 | 145 | // finds linked nodes 146 | this.getLinked = function (node) { 147 | return node.links.map(function(e) { 148 | return (e.source === node ? e.target : e.source); 149 | }); 150 | } 151 | 152 | 153 | // graphical use 154 | this.screenToWorldPoint = function(x,y) { 155 | var svgEl = svg.node(); 156 | var pt = svgEl.createSVGPoint(); 157 | pt.x = x; 158 | pt.y = y; 159 | pt = pt.matrixTransform(vis.node().getCTM().inverse()); 160 | return pt; 161 | } 162 | 163 | // set up the D3 visualisation in the specified element 164 | 165 | var color = d3.scaleOrdinal() 166 | .domain(graphNodes) 167 | .range(graphNodesColors); 168 | 169 | 170 | var svg = d3.select(selector) 171 | .append("svg:svg") 172 | .attr("width", w) 173 | .attr("height", h) 174 | .attr("id", "svg") 175 | .attr("pointer-events", "all") 176 | .attr("viewBox", "0 0 " + w + " " + h) 177 | .attr("preserveAspectRatio", "xMinYMin meet") 178 | .on("click",backClick) 179 | 180 | 181 | 182 | var vis = svg.append('svg:g'); 183 | 184 | // defines a force simulation 185 | var force = d3.forceSimulation(); 186 | 187 | this.nodes = force.nodes() 188 | this.links = []; 189 | 190 | d3.select("input[id='gravRange']") 191 | .on("input", inputted); 192 | 193 | // triggers the search for rewrite patterns 194 | this.update = function () { 195 | // Update transform list 196 | findAllTransforms(); 197 | 198 | // Update graph 199 | var link = vis.selectAll("line") 200 | .data(links, function (d) { 201 | return d.source.id + "-" + d.target.id; 202 | }); 203 | 204 | // adds a link representation as a line, the value is used for stroke width 205 | var linkEnter = link.enter() 206 | .append("line") 207 | .style("stroke-opacity",0).style("fill-opacity",0) 208 | .attr("id", function (d) { 209 | return d.source.id + "-" + d.target.id; 210 | }) 211 | .attr("stroke-width", function (d) { 212 | return d.value / 10; 213 | }) 214 | .transition() 215 | // .delay(0.2) 216 | .duration(2) 217 | .style("stroke-opacity",1).style("fill-opacity",1) 218 | .attr("class", "link") 219 | //link.append("title") 220 | // .text(function (d) { 221 | // return d.value; 222 | // }); 223 | link.exit().remove(); 224 | 225 | link = link.merge(linkEnter) 226 | 227 | var node = vis.selectAll("g.node") 228 | .data(nodes, function (d) { 229 | return d.id; 230 | }); 231 | 232 | var nodeEnter = node.enter().append("g") 233 | .attr("class", "node") 234 | 235 | // adds a node representation as a circle 236 | nodeEnter.append("svg:circle") 237 | .style("stroke-opacity",0).style("fill-opacity",0) 238 | .transition() 239 | // .delay(0.2) 240 | .duration(1) 241 | .style("stroke-opacity",1).style("fill-opacity",1) 242 | .attr("r", function(d) { 243 | if (d.type == "in" || d.type == "out" || d.type == "middle") { 244 | return 4; 245 | } else { 246 | return 8; 247 | } 248 | }) 249 | .attr("id", function (d) { 250 | return "Node;" + d.id; 251 | }) 252 | .attr("class", "nodeStrokeClass") 253 | .attr("fill", function(d) { 254 | // added metabolism colors 255 | if (metabo == 0) { 256 | return color(d.type); 257 | } else { 258 | return whiteCol; 259 | } 260 | }) 261 | 262 | node.exit().remove(); 263 | 264 | node = node.merge(nodeEnter) 265 | .on("click",nodeClick) 266 | .on("mouseenter",nodeHover) 267 | .call(d3.drag() 268 | .on("start", dragstarted) 269 | .on("drag", dragged) 270 | .on("end", dragended) 271 | ); 272 | 273 | // mouse drag behaviour 274 | function dragstarted(d) { 275 | if (!d3.event.active) force.alphaTarget(0.1).restart(); 276 | d.fx = d.x; 277 | d.fy = d.y; 278 | } 279 | 280 | function dragged(d) { 281 | d.fx = d3.event.x; 282 | d.fy = d3.event.y; 283 | } 284 | 285 | function dragended(d) { 286 | if (!d3.event.active) force.alphaTarget(0); 287 | d.fx = null; 288 | d.fy = null; 289 | } 290 | 291 | 292 | // takes the value of gravity from the gravity slider 293 | function gravForce() { 294 | var gravi = (document.getElementById("gravRange").value) / 1000; 295 | return gravi; 296 | } 297 | 298 | // keeps node objects on top of edges 299 | $(".nodeStrokeClass").each(function( index ) { 300 | var gnode = this.parentNode; 301 | gnode.parentNode.appendChild(gnode); 302 | }); 303 | 304 | 305 | // zoom behaviour 306 | d3.zoom().on("zoom", function zoom_actions(){ 307 | vis.attr("transform", d3.event.transform) 308 | })(svg) 309 | 310 | // Restart the force layout. 311 | force 312 | .alpha(forceAlpha) 313 | .alphaDecay(forceAlphaDecay) 314 | .velocityDecay(forceVelocityDecay) 315 | .force("charge_force", d3.forceManyBody().strength(chargeForceStrength)) 316 | .force("center_x", d3.forceX(w / 2).strength(gravForce)) 317 | .force("center_y", d3.forceY(h / 2).strength(gravForce)) 318 | .force("links", d3.forceLink(links).id(function (d) { return d.id; }).distance(function(d) { 319 | if (d.value == 1) { 320 | return 2; 321 | } else { 322 | return 1; 323 | } 324 | }).strength(forceStrength)) 325 | .on("tick", function () { 326 | 327 | node.attr("transform", function (d) { 328 | return "translate(" + d.x + "," + d.y + ")"; 329 | }); 330 | 331 | link.attr("x1", function (d) { 332 | return d.source.x; 333 | }) 334 | .attr("y1", function (d) { 335 | return d.source.y; 336 | }) 337 | .attr("x2", function (d) { 338 | return d.target.x; 339 | }) 340 | .attr("y2", function (d) { 341 | return d.target.y; 342 | }); 343 | }) 344 | .restart(); 345 | 346 | // end function update() 347 | }; 348 | 349 | function inputted() { 350 | force.alphaTarget(1); 351 | force.restart(); 352 | update(); 353 | } 354 | 355 | // Make it all go 356 | update(); 357 | 358 | // end function myGraph 359 | } 360 | 361 | 362 | 363 | function setMode(newMode, newType) { 364 | mode = newMode; 365 | addType = newType; 366 | selection = null; 367 | } 368 | 369 | 370 | 371 | function findLinkedOfType(node, type) { 372 | var linked = getLinked(node); 373 | for (var i=0; i 0) { 74 | errorsline = "Missing parentheses"; 75 | document.getElementById("errors").innerHTML += errorsline; 76 | throw "Missing parentheses"; 77 | } else { 78 | for (var i=0; i= lex2A.length) { 101 | errorsline = "Malformed expression"; 102 | document.getElementById("errors").innerHTML += errorsline; 103 | throw "Malformed expression"; 104 | } else { 105 | if (!(isVar(lex2A[i+1]) || lex2A[i+1] == op.lparen || lex2A[i+1] == op.lambda)) { 106 | errorsline = "Malformed expression"; 107 | document.getElementById("errors").innerHTML += errorsline; 108 | throw "Malformed expression"; 109 | } 110 | } 111 | } 112 | if (lex2A[i] == op.lambda) { 113 | ji = i + 4; 114 | if (ji >= lex2A.length) { 115 | errorsline = "Malformed expression"; 116 | document.getElementById("errors").innerHTML += errorsline; 117 | throw "Malformed expression"; 118 | } else { 119 | if ( isOp(lex2A[i+1]) || lex2A[i+2] !== op.dot) { 120 | errorsline = "Malformed expression"; 121 | document.getElementById("errors").innerHTML += errorsline; 122 | throw "Malformed expression"; 123 | } 124 | } 125 | } 126 | } 127 | 128 | 129 | // print lexer result 130 | /* 131 | document.getElementById("lexer").innerHTML = "lexer:

"; 132 | for (var i=0; i 137 | 138 | return lex2A; 139 | } 140 | 141 | // parser to mol with variables 142 | function parserCaller(molvi, stick) { 143 | 144 | var molV = molvi; 145 | var rootAdd = true; 146 | 147 | function parser(term) { 148 | var stack = term.content, current, termout = {}, iLeftAbs = 0, iRightAbs = 0, iMiddleAbs = 0; 149 | var rootAddCurrent; 150 | rootAddCurrent = rootAdd; 151 | current = stack[term.left]; 152 | 153 | while (current !== op.eof) { 154 | if (isVar(current)) { 155 | iRightAbs = term.right + term.absolute; 156 | // mod for SKI, without isSkiTerm 157 | if (isSKIComb(current)) { 158 | if (current == "S" ) { 159 | molV += "S1" + " " + current + " " + iRightAbs + "^"; 160 | } else { 161 | molV += current + " " + current + " " + iRightAbs + "^"; 162 | } 163 | } else { 164 | molV += "FRIN " + current + " " + iRightAbs + "^"; 165 | } 166 | term.right += 1; 167 | term.middle = term.right; 168 | current = stack[term.right]; 169 | } else if (current == op.bof || current == op.eof) { 170 | term.right += 1; 171 | term.left= term.right; 172 | term.middle = term.right; 173 | current = stack[term.right]; 174 | } else if (current == op.lparen) { 175 | term.middle = term.right; 176 | termout.left = 0; 177 | termout.middle = 0; 178 | termout.right = 0; 179 | termout.absolute = term.right + term.absolute; 180 | termout.content = [op.bof]; 181 | term.right +=1; 182 | var parens = 1; 183 | while (parens > 0) { 184 | if (stack[term.right] == op.lparen) { 185 | parens +=1; 186 | } else if (stack[term.right] == op.rparen) { 187 | parens = parens - 1; 188 | } 189 | if (parens > 0) { 190 | termout.content.push(stack[term.right]); 191 | } 192 | term.right +=1; 193 | } 194 | termout.content.push(op.eof); 195 | parser(termout); 196 | term.middle = term.right; 197 | current = stack[term.right]; 198 | } else if (current == op.lambda) { 199 | term.middle = term.right + 1; 200 | var next = stack[term.middle]; 201 | iMiddleAbs = term.middle + term.absolute; 202 | if (isVar(next)) { 203 | molV += "FROUT " + next + " " + iMiddleAbs + "^"; 204 | term.left = term.middle + 1; 205 | if (stack[term.left] == op.dot) { 206 | iLeftAbs = term.left + term.absolute; 207 | iRightAbs = term.right + term.absolute; 208 | molV += "L " + iLeftAbs + " " + iMiddleAbs + " " + iRightAbs + "^"; 209 | term.left = term.left - 2; 210 | term.right = term.right + 2; 211 | termout.left = 0; 212 | termout.middle = 0; 213 | termout.right = 0; 214 | termout.absolute = term.right + term.absolute; 215 | termout.content = [op.bof]; 216 | term.right +=1; 217 | while (stack[term.right] !== op.eof) { 218 | termout.content.push(stack[term.right]); 219 | term.right +=1; 220 | } 221 | termout.content.push(op.eof); 222 | parser(termout); 223 | term.middle = term.right; 224 | current = stack[term.right]; 225 | } else { 226 | errorsline = "Not a variable in lambda: \"\\" + next + " " + stack[term.middle] + stack[term.left] + "\""; 227 | document.getElementById("errors").innerHTML += errorsline; 228 | throw "Not a variable in lambda: \"\\" + next + " " + stack[term.middle] + stack[term.left] + "\""; 229 | } 230 | } else { 231 | errorsline = "Not a variable in lambda: \"\\" + stack[term.middle] + "\""; 232 | document.getElementById("errors").innerHTML += errorsline; 233 | throw "Not a variable in lambda: \"\\" + stack[term.middle] + "\""; 234 | } 235 | } else if (current == op.app) { 236 | term.middle = term.right; 237 | iLeftAbs = term.left+ term.absolute; 238 | term.middle +=1; 239 | if (stack[term.middle] == op.lambda) { 240 | var itempo = term.right + term.absolute; 241 | if (rootAdd) { 242 | molV += "Arrow" + " " + itempo + " " + term.absolute + "^";} 243 | rootAddCurrent = false; 244 | } 245 | iMiddleAbs = term.middle + term.absolute; 246 | iRightAbs = term.right + term.absolute; 247 | molV += "A " + iLeftAbs + " " + iMiddleAbs + " " + iRightAbs + "^"; 248 | term.left = term.right; 249 | term.right = term.middle; 250 | term.middle = term.right; 251 | current = stack[term.right]; 252 | } else if (current == op.eof) { 253 | iRightAbs = term.right + term.absolute; 254 | molV += "Arrow" + iRightAbs + " " + term.absolute + "^"; 255 | current = stack[term.right]; 256 | } 257 | } 258 | iLeftAbs = term.left + term.absolute; 259 | if (rootAddCurrent) { 260 | molV += "Arrow" + " " + iLeftAbs + " " + term.absolute + "^";} 261 | } 262 | 263 | parser(stick); 264 | return molV; 265 | } 266 | 267 | // walk the edges function: molvi is a mol file as an array of lines, molve is the edges vector 268 | function molvOtherEnd(molvi,molve,lin,pos) { 269 | var imolve = molvi[lin][pos]; 270 | for (var i=0; i 307 | 308 | var edgesprettyline = "", errorsline = ""; 309 | for (var i=0; i 0) { 312 | for (var j=0; j"; // 314 | } 315 | switch (molve[i].length){ 316 | case 2: case 0: 317 | continue; 318 | break; 319 | 320 | case 1: 321 | errorsline = "Probably the graph is disconnected, because of missing parantheses."; 322 | document.getElementById("errors").innerHTML += errorsline; 323 | // throw "edge " + i + " has only one end. Probably the graph is disconnected, because of missing parantheses?"; 324 | break; 325 | 326 | default: 327 | errorsline = "Malformed graph. Try to add parantheses in textarea."; 328 | document.getElementById("errors").innerHTML += errorsline; 329 | throw "edge " + i + " has " + molve[i].length + " ends: " + edgesprettyline + " Malformed graph. Try to add parantheses in textarea."; 330 | break; 331 | } 332 | } 333 | var walkCount = 0, maxwalkCount = 2 * molvi.length, stopb, jwalk; 334 | for (var i=0; i maxwalkCount) { 346 | errorsline = "From " + molvL + " ,running circles in the graph. Stopped."; 347 | document.getElementById("errors").innerHTML += errorsline; 348 | throw "From " + molvL + " ,running circles in the graph. Stopped."; 349 | stopb = false; 350 | } 351 | jwalk = varOut.line; 352 | molvC = molvi[jwalk]; 353 | switch (molvC[0]) { 354 | case "A": 355 | varOut = molvOtherEnd(molvi,molve,jwalk,3); 356 | break; 357 | case "Arrow": 358 | varOut = molvOtherEnd(molvi,molve,jwalk,2); 359 | break; 360 | case "L": 361 | var imov = molvOtherEnd(molvi,molve,jwalk,2); 362 | if (varNm == molvi[imov.line][1]) { 363 | boundEdg[imov.line].push(i); 364 | stopb = false; 365 | } else { 366 | varOut = molvOtherEnd(molvi,molve,jwalk,3); 367 | } 368 | break; 369 | case "ROOT": 370 | freeEdg[i] = true; 371 | stopb = false; 372 | break; 373 | default: 374 | errorsline = "Entered through a FRIN node (" + molvL + ") and exited in a weird place (" + molvC + "). Stopped. Put parantheses in the textarea?"; 375 | document.getElementById("errors").innerHTML += errorsline; 376 | throw "From " + molvL + " ,exit through " + molvC + " which is weird. Stopped."; 377 | break; 378 | } 379 | } 380 | } 381 | } 382 | 383 | output = {"free":freeEdg,"bound":boundEdg,"edges":molve}; 384 | return output; 385 | } 386 | 387 | 388 | 389 | 390 | // main function 391 | function lambdaToMol() { 392 | var input = document.getElementById("inputlambda").value; 393 | document.getElementById("errors").innerHTML = ""; 394 | 395 | var inputArray = sanitize(input); 396 | var lexArray = lexer(inputArray); 397 | 398 | var molvIn = "ROOT 0^"; 399 | var maxCount = lexArray.length; 400 | var stack0 = { 401 | "left":0, 402 | "right":0, 403 | "middle":0, 404 | "absolute":0, 405 | "content":lexArray, 406 | }; 407 | 408 | var molvOut = parserCaller(molvIn,stack0); 409 | 410 | // put molvOut in array format 411 | // var molvC, jline, varNm, varIn, varOut, varBound; 412 | // document.getElementById("molv").innerHTML = "molvDet:

"; // 413 | var molvL; 414 | 415 | var molvDet = importMolVector(molvOut,"^"); 416 | 417 | 418 | 419 | // 420 | 421 | 422 | //find edges of the graph, until now, free and bound variables 423 | var mkEdgeV = makeEdgesVector(molvDet,maxCount); 424 | 425 | var molVedges = mkEdgeV.edges, 426 | boundEdges = mkEdgeV.bound, 427 | freeEdges = mkEdgeV.free; 428 | 429 | var nodeCnt = maxCount + 1; 430 | // add FO and T nodes for the bounded vars 431 | for (var i=0; i"); 561 | 562 | // transform it into an array 563 | var molFinalArray = [], molLine = [], linkedi = [], frinSuccess; 564 | 565 | for (var i=0; i 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | chemSKI with tokens: world building and economy in the SKI universe 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | Cite as:
chemSKI with tokens: world building and economy in the SKI universe. © Marius Buliga (2023), https://mbuliga.github.io/chemski/chemski-with-tokens.html

30 | Version 23.06.2023, updated from version 01.06.2023 which is associated with arXiv:2306.00938

31 | See also:
All chemlambda projects 32 |


33 | 34 |

chemSKI with tokens: world building and economy in the SKI universe



35 | 36 |

Contents

37 |

Introduction

38 |

Graphs and nodes

39 |

Conservative rewrites with tokens

40 |

Cost of rewrites

41 |

chemSKI rewrites

42 |

Tokens, synthesis and waste rewrites

43 |

chemSKI + chemlambda v2

44 |

How are chemSKI rewrites used

45 |

From SKI to chemSKI

46 |

Play with chemSKI

47 | 48 | 49 | 50 |

51 | 52 | 53 |

Introduction

54 |

(back to contents)



55 | 56 | In the article chemSKI and chemlambda I introduced the purely local graph rewrite system chemSKI for the SKI combinators calculus. I was motivated to build chemSKI because in the article Combinatory Chemistry: Towards a Simple Model of Emergent Evolution arXiv:2003.07916 Kruszewski and Mikolov asked for a graph-rewriting version of their term rewrite system in chemlambda style. chemSKI is not a graph rewrite version of Combinatory Chemistry, though. Instead is a confluent graph rewrite system where all rewrites are local, which moreover can be used to do SKI calculus reductions. This is true in the same sense that Lafont Interaction Combinators can be used to do lambda calculus reductions. That is because there is a parser from a SKI term to a chemSKI graph and a partial inverse function which can associate a SKI term to a free edge of a chemSKI graph, such that term reductions in SKI calculus correspond to sequences of graph rewrites in chemSKI.

57 | Here I explain chemSKI [chemSKI repository] with tokens, where the graph rewrites of chemSKI are made conservative by the use of tokens. We thus achieve two goals: conservative rewrites in a chemical style, and a new estimation of the cost of a computation.

58 | 59 |

Graphs and nodes of chemSKI

60 |

(back to contents)


61 | 62 | The graphs are called "molecules" and they are formed by nodes connected by edges. Each node has a type and 1, 2 or 3 numbered node ports. The types of nodes of chemSKI are S, K, I, A, Arrow, FRIN, FROUT, see [nodes.js line 21] (contains the all types of nodes used in the chemlambda project). 63 |

64 | 65 | nodes of chemSKI

66 | 67 | 68 | There are two 1-valent nodes, for the combinators I and K, and two 3-valent nodes, one for the combinator S and simultaneously for fanout, the other for the application (A like in chemlambda v2). There are also two 1-valent nodes, FRIN (free in) and FROUT (free out) and a 2-valent node Arrow which serve the same roles as in chemlambda.

69 | 70 | As explained in arXiv.2003.14332, we use the mol notation, for example a 3-valent node S is described by the string "S a b c" which means that the node type is "S", the port 1 of the node is linked to the edge named "a", the port 2 of the node is linked to the edge named "b" and finally the port 3 of the node is linked to the edge named "c".

71 | 72 | node S

73 | 74 | The edge names are arbitrary strings (with letters a-z, A-Z, 0-9, without space character) and different edges of the graph have different names. To each node port there is only one edge connected. They follow the same conventions as chemlambda v2.

75 | 76 | The color codes for node types and ports [nodes.js line 153] are described in the next figure.

77 | 78 | color codes for chemSKI

79 | 80 | 81 | 82 | 83 | 84 | FRIN and FROUT are used to cap the free half-edges of the graph, if any. This is done according to the type of the ports of nodes: the first port is always "in", the last port is always "out" and, for the middle ports of the two trivalent nodes the rules are: for the node S the middle port is of type "out", for the node "A" the middle port is of type "in". in the following figure we see how or and

85 | 86 | FRIN and FROUT added to nodes

87 | 88 | The Arrow node was introduced to allow simultaneous application of rewrites, followed by the deletion of the introduced Arrow nodes by the rewrite COMB (which "combs" the graph). Together with FRIN and FROUT, they are used in all chemlambda rewrite systems.

89 | 90 | 91 | It is possible to have edges connected to the same node, but at different ports. For example "S b b a" describes a node of type "S", with an edge named "b" connecting port 1 and port 2 of that node.

92 | 93 | combinators, application, fanout

94 | 95 | 96 | The rewrites concerning the node S are different, according to the existence of an edge between S node ports 1 and 2 (in this case S represents the combinator S) or not (in this case S is a fanout node).

97 | 98 | Any molecule (ie chemSKI graph) is described by a mol file. A mol file is a list of nodes, where each node is a list which starts with the node type and continues with the edge names connected to ports, in the order of the ports. Therefore, as a string, a mol file needs a line separator (between node lines) and a field separator (within each line). As an example, the molecule which is the translation of the combinator ((S K) K) I is described by the mol file

99 | FROUT 1
100 | S 2 2 3
101 | A 3 4 5
102 | K 4
103 | A 5 6 7
104 | K 6
105 | A 7 8 1
106 | I 8

107 | with space " " as field separator and new line as a line separator. In the simulation section Play with chemSKI we use "^" as the line separator, for example the same molecule appears as the string

108 | FROUT 6^S 10 10 1^A 1 3 2^K 3^A 2 5 4^K 5^A 4 7 6^I 7

109 | Mind that the edge names are different, which is not important, because they are arbitrary.

110 | The line separator is not important, because we can deduce the number of ports (ie the number of edge names on a node line) from the node type, therefore we shall also use a notation like

111 | FROUT 6 S 10 10 1 A 1 3 2 K 3 A 2 5 4 K 5 A 4 7 6 I 7

112 | for the same molecule, where the line and field separator are the same. Thus a mol file appears as a string of node types and edge names. This convention is useful in the section about rewrites.

113 | 114 |

Conservative rewrites with tokens

115 |

(back to contents)


116 | 117 | Each chemSKI rewrite is described by a left hand side (LHS) and a right hand side (RHS) pattern, which are mol files. There is also a chemical interpretation, where we see each rewrite as a chemical reaction, which transforms the LHS into RHS. In order to be conservative in nodes and edges, we need to add tokens, ie a finite number (up to isomorphism) of small graphs.

118 | 119 | We shall use the following tokens [nodes.js line 22]:

120 | 121 | chemSKI tokens

122 | 123 | For each chemSKI rewrite are specified the LHS and RHS appear as mol files (with "," as line separator). Moreover, with the addition of tokens there will be two bigger mol files, called "LHS with tokens" and "RHS with tokens". Written as strings (ie with line and field separator equal), "RHS with tokens" will be a permutation of "LHS with tokens".

124 | 125 | Borrowing from the Project Hapax, we see that the addition of tokens solves the problem of unique name edges, even in a decentralized graphical reduction. It is enough to have "minted" tokens (ie tokens with unique edge names) and then to use them in the rewrites. The minting is of course an independent part from the reduction rewrites.

126 | 127 | The tokens have 1 (for Arrow token), 2 (for S-K and I-A tokens) or 3 (for A-A, S-A, S-S tokens) edge names. Minting such a token is a process where the new, unique name edges of the token are produced. In a sense, each such token carries 1, 2 or 3 unique names.

128 | 129 |

Cost of rewrites

130 |

(back to contents)


131 | 132 | 133 | Each chemSKI rewrite has the form

134 | 135 | LHS + In Tokens = RHS + Out Tokens

136 | 137 | Suppose that each token has a scalar cost, per token type, in our case there are numbers cost[A-A], cost[I-A], cost[S-A], cost [S-K], cost[S-S], cost[Arrow]. In the programs the cost per token is in the TokensCost vector [nodes.js line 23]. Then the cost of a collection of tokens is the sum of costs of tokens.

138 | 139 | A reasonable choice is to take the cost of the token as the number of unique names it carries, but this choice is not unique. In an economy application the cost per token would be decided by trading. In a world building application the cost per token would be tuned bo reflect its scarcity.

140 | 141 | As the Arrow token enters in many "COMB" rewrites, which just eliminate the Arrow nodes, it is also reasonable to assign a cost equal to 0 for this token, because Arrow nodes in graphs have a fleeting existence.

142 | 143 | The cost of a rewrite depends on the application. There is an in cost of a rewrite:

144 | InCost[rewrite] = cost[In Tokens]

145 | and an out cost of a rewrite:

146 | OutCost[rewrite] = cost[Out Tokens]

147 | From here, we may have a cost of a rewrite, as

148 | cost[rewrite] = OutCost[rewrite] - InCost[rewrite]

149 | The cost of a graph reduction would be then the sum of the costs of rewrites performed.

150 | For example, in the case when the cost measures the number of new names, this is reasonable. Also, this cost[rewrite] would be interesting in relation to world building applications, where we see graphs as artificial life, arXiv:2005.06060 section 3, or the experiment page How to test a quine. For such an application cost[rewrite] is related to the metabolism.

151 | For economy applications we may use InCost[rewrite] to bill a rewrite. We would use perhaps only "In Tokens" from the customer. Then OutCost[rewrite] would measure the value of the tokens we obtain because we performed the rewrite. cost[rewrite] would be then the profit.

152 | Also for economy or general computation applications, such cost would supplement other costs considered, like the number of computational steps performed by a virtual machine to do the rewrite. Indeed, for some quine graphs, like in Play with chemSKI menu the graph associated to (S I I) (S I I), the cost of the graph reduction oscilates in time around 0. The computational cost of running the reductions for such a quine should be something which increases approximately linear in time. For other graphs, like in Play with chemSKI menu the graph associated to (S I I) (S (K (S I I)) (S (K (S I)) (S (K K) I))), they may evolve into a "dirty" quine graph, which is an ever increasing graph which has a component which is a quine, but also more and more "dirt" or "waste" composed of small graphs which are inert. In such a case the cost proposed here is linear in time.

153 | 154 | The existence of "waste" implies that, whatever cost we consider, it should also extend to the cost[Initial graph] and cost[Final Graph], such that it satisfies:

155 | cost[Initial Graph] + InCost[all rewrites performed] = cost[Final Graph] + OutCost[all rewrites performed]

156 | OutCost[all rewrites performed] = Profit[all rewrites performed] + cost[waste]

157 | 158 | We leave open this subject.

159 | 160 | 161 |

chemSKI rewrites

162 |

(back to contents)


163 | 164 | The list of rewrites of chemSKI is the following, in mol notation and graphically.

165 | 166 | 178 | 179 | 180 | The rewrites are defined in [chemistry.js from line 99]

181 | 182 | "function chemistry(id) {
183 | switch (id) {
184 | case "CHEMSKI":
185 | ... }}"

186 | 187 | by a string like for example for the rewrite I-S: [chemistry.js line 102]

188 | 189 | {left:"I",right:"S",action:"terminIS", named:"I-S", kind:"TERMINATION"}

190 | 191 | called in the programs comments "a transform". The meaning of this string is the following. A rewrite is mathematically described by a pair (LHS,RHS), where LHS and RHS are graphs, in mol notation. In order to use a rewrite we need first to identify the LHS pattern in the graph. For this we visit each node of the graph, ie we visit each line in the mol description of the graph. Once we are at a node n1, we verify if the node type is the one from the "right" field. Then, according to the name of the "action" field, there is an algorithm which tries to visit the graph, going from the node n1 by the edges of the graph. The algorithm tries to identify the node n2, which should have the type of the "left" field. The algorithm describes a path in the LHS, starting from n1, passing by n2, in a way which allows to decide if there is a subgraph which is isomorphic with the LHS pattern.

192 | 193 | The "named" field is the name of the rewrite which we use in explanations, following the convention to use the node types "left"-"right". The field "kind" describes what kind of rewrite we have, for example "TERMINATION" describe rewrites which involve pruning nodes connected to a "termination" node.

194 | 195 | Therefore, the important fields used for the rewrites are "left", "right" and "action".

196 | 197 | As a comment on the same line as the transform string, there is a pair, like for that rewrite I-S

198 | 199 | "tokenIn: I-A     tokenOut: S-A"

200 | 201 | which indicates to the reader a way to make the rewrite conservative by the use of tokens.

202 | 203 | 204 | 205 | 206 |

The rewrite K-A

207 |

(back to chemSKI rewrites)

corresponds to the SKI combinators rewrite K a b -> a. It is a rewrite of kind "BETA", similar to the beta rewrite (in graphical form) from lambda calculus.

208 | {left:"K",right:"A",action:"KA", named:"K-A", kind:"BETA"}

209 | 210 | It is described in [chemistry.js line 99]. In mol notation, is described as:

211 | LHS = K 1, A 1 a 2, A 2 b c
212 | 213 | RHS = K e, Arrow a c, Arrow b e

214 | 215 | and as a chemical reaction by

216 | 217 | K-A rewrite

218 | 219 | with the tokens: 2 Arrow and A-A.

220 | 221 | The LHS and RHS patterns with the tokens, are:

222 | LHS with tokens = K 1, A 1 a 2, A 2 b c, Arrow d d, Arrow e e
223 | RHS with tokens = K e, A 1 d 1, A 2 d 2, Arrow a c, Arrow b e

224 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

225 | (0 1 2 3 4 5 6 7 8 9 a b c d e f)
226 | (0 e 2 1 b 3 6 5 c 7 a 4 9 d 8 f) 227 |

228 | 229 | 230 |

The rewrite I-A

231 |

(back to chemSKI rewrites)

corresponds to the SKI combinators rewrite I a -> a.

232 | {left:"I",right:"A",action:"termIA", named:"I-A", kind:"TERMINATION"}

233 | 234 | 235 | It is described in [chemistry.js line 102]. In mol notation, is described as:

236 | LHS = I 1, A 1 a b
237 | 238 | RHS = Arrow a b

239 | 240 | and as a chemical reaction by

241 | 242 | I-A rewrite

243 | 244 | with the tokens Arrow and I-A.

245 | 246 | The LHS and RHS patterns with the tokens, are:

247 | LHS with tokens = I 1, A 1 a b, Arrow c c
248 | RHS with tokens = I 1, A c 1 c, Arrow a b

249 | 250 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

251 | (0 1 2 3 4 5 6 7 8)
252 | (0 1 2 7 3 8 6 4 5) 253 |

254 | 255 |

The rewrite I-S

256 |

(back to chemSKI rewrites)

used to duplicate a I combinator node by the S node which plays the role of a fanout in this rewrite. It can also be seen as a rewrite which eliminates a S node.

257 | {left:"I",right:"S",action:"terminIS", named:"I-S", kind:"TERMINATION"}

258 | 259 | 260 | It is described in [chemistry.js line 103]. In mol notation, is described as:

261 | LHS = I a, S a b c
262 | 263 | RHS = I b, I c

264 | 265 | and as a chemical reaction by

266 | 267 | I-S rewrite

268 | 269 | with the tokens I-A and S-A.

270 | 271 | The LHS and RHS patterns with the tokens, are:

272 | LHS with tokens = I a, S a b c, I d, A e d e
273 | RHS with tokens = I b, S a d a, I c, A e d e

274 | 275 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

276 | (0 1 2 3 4 5 6 7 8 9 a b)
277 | (0 4 2 1 7 3 6 5 8 9 a b) 278 |

279 | 280 | 281 |

The rewrite K-S

282 |

(back to chemSKI rewrites)

used to duplicate a K combinator node by the S node which plays the role of a fanout in this rewrite.

283 | {left:"K",right:"S",action:"terminKS", named:"K-S", kind:"TERMINATION"}

284 | 285 | It is described in [chemistry.js line 104]. In mol notation, the K-S rewrite is described as:

286 | LHS = K a, S a b c
287 | 288 | RHS = K b, K c

289 | 290 | and as a chemical reaction by

291 | 292 | K-S rewrite

293 | 294 | with the tokens S-K and S-S.

295 | 296 | The LHS and RHS patterns with the tokens, are:

297 | LHS with tokens = K a, S a b c, K d, S e d e
298 | RHS with tokens = K b, S a d a, K c, S e d e

299 | 300 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the same permutation as the one from the rewrite I-S

301 | (0 1 2 3 4 5 6 7 8 9 a b)
302 | (0 4 2 1 7 3 6 5 8 9 a b) 303 |

304 | 305 | 306 |

The rewrite S-K

307 |

(back to chemSKI rewrites)

has two LHS patterns, in both cases the K node, connected at port 2 or port 3 of a S node (when it has the role of a fanout), prunes the respective port.

308 | {left:"S",right:"K",action:"terminSK", named:"S-K", kind:"TERMINATION"}

309 | 310 | 311 | It is described in [chemistry.js line 105]. In mol notation, the first S-K rewrite is described as:

312 | LHS = S a b c, K c
313 | 314 | RHS = Arrow a b

315 | 316 | and as a chemical reaction by

317 | 318 | first S-K rewrite

319 | 320 | with the tokens Arrow and S-L.

321 | 322 | The LHS and RHS patterns with the tokens, are:

323 | LHS with tokens = S a b c, K c, Arrow d d
324 | RHS with tokens = S d c d, K c, Arrow a b

325 | 326 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

327 | (0 1 2 3 4 5 6 7 8)
328 | (0 7 3 8 4 5 6 1 2) 329 |

330 | 331 | 332 | The second S-K rewrite is described as:

333 | LHS = S a c b, K c
334 | 335 | RHS = Arrow a b

336 | 337 | and as a chemical reaction by

338 | 339 | second S-K rewrite

340 | 341 | with the tokens Arrow and S-K.

342 | 343 | The LHS and RHS patterns with the tokens, are:

344 | LHS with tokens = S a c b, K c, Arrow d d
345 | RHS with tokens = S d c d, K c, Arrow a b

346 | 347 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

348 | (0 1 2 3 4 5 6 7 8)
349 | (0 7 2 8 4 5 6 1 3) 350 |

351 | 352 |

The rewrite A-K

353 |

(back to chemSKI rewrites)

is a pruning rewrite where a K combinator node connected to the port 3 of an application A node transforms into a pair of K nodes.

354 | {left:"A",right:"K",action:"termAK", named:"A-K", kind:"TERMINATION"}

355 | 356 | 357 | It is described in [chemistry.js line 106]. In mol notation, the rewrite is described as:

358 | LHS = A a b c, K c
359 | 360 | RHS = K a, K b

361 | 362 | and as a chemical reaction by

363 | 364 | A-K rewrite

365 | 366 | with the tokens S-K and S-A.

367 | 368 | The LHS and RHS patterns with the tokens, are:

369 | LHS with tokens = A a b c, K c, S d e d, K e
370 | RHS with tokens = A c e c, K a, S d e d, K b

371 | 372 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

373 | (0 1 2 3 4 5 6 7 8 9 a b)
374 | (0 3 8 5 4 1 6 7 8 9 a 2) 375 |

376 | 377 |

The rewrite A-S

378 |

(back to chemSKI rewrites)

duplicates a pair of nodes A and S, thus serving to duplicate A nodes and also S nodes in their role of fanouts.

379 | {left:"A",right:"S",action:"DIST1", named:"A-S", t1:"S",t2:"S",t3:"A",t4:"A", kind:"DIST"}

380 | The kind "DIST" takes the name from "distributivity", but I used the name as a generic one for duplication rewrites or even for rewrites which do not increase the number of nodes. The rewrite. However the action field is "DIST1", which is a precise description because there are 8 types of truly inspired from "distributivity" rewrites (DIST0 to DIST7), as explained in [chemistry.js from line 820]. In the case of DIST0 to DIST7 rewrites there are new fields "t1", ..., "t4" which are used for the types of nodes in the RHS of the rewrite.

381 | It is described in [chemistry.js line 110]. In mol notation, the rewrite is described as:

382 | LHS = A a b e, S e c d
383 | 384 | RHS = S a e f, S b g h, A e g c, A f h d

385 | 386 | and as a chemical reaction by

387 | 388 | A-S rewrite

389 | 390 | with the token S-A.

391 | 392 | The LHS and RHS patterns with the tokens, are:

393 | LHS with tokens = S e c d, S f h f, A a b e, A g h g
394 | RHS with tokens = S a e f, S b g h, A e g c, A f h d

395 | 396 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

397 | (0 1 2 3 4 5 6 7 8 9 a b c d e f)
398 | (0 9 1 5 4 a d 6 8 b f 2 c 7 e 3) 399 |

400 | 401 | 402 |

The rewrite S-S

403 |

(back to chemSKI rewrites)

is a neutral rewrite (ie no tokens needed). It uses a S node in the role of an S combinator, connected to another S node in the role of fanout. It duplicates the S combinator, but this is done by rewiring of the two S nodes available.

404 | {left:"S",right:"S",action:"SS", named:"S-S", kind:"DIST"}

405 | Mind that even if the kind is "DIST", the action is not one of DIST0 to DIST7, therefore here is a case where I used the kind "DIST" as a placeholder for duplication. This is also justified by the fact that the rewrite does not decrease the number of nodes, it is therefore put in the category of rewrites which is favored by the "GROW" strategy.

406 | 407 | This is described in [chemistry.js line 113]. In mol notation, the rewrite is described as:

408 | LHS = S a a b, S b c d
409 | 410 | RHS = S a a c, S b b d

411 | 412 | and as a chemical reaction by

413 | 414 | S-S rewrite

415 | 416 | with no tokens.

417 | 418 | The LHS and RHS patterns with the tokens, are the same, because the rewrite is neutral:

419 | LHS with tokens = S a a b, S b c d
420 | RHS with tokens = S a a c, S b b d

421 | 422 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

423 | (0 1 2 3 4 5 6 7)
424 | (0 1 2 6 4 3 5 7) 425 |

426 | 427 | 428 |

The rewrite S-A

429 |

(back to chemSKI rewrites)

is the graphical rewrite version of S a b c -> (a c) (b c). Instead of duplicating "c", it just rewires the LHS where the combinator S appears as an S node with ports 1 and 2 connected, into the RHS where the node S has not the ports 1 and 2 connected, thus it plays the role of a fanout. It is therefore a neutral rewrite (no tokens needed).

430 | {left:"S",right:"A",action:"SA", named:"S-A", kind:"DIST"}

431 | The kind of this rewrite is "DIST", because it does not decrease the number of nodes, therefore it is favored by the rewrite strategy "GROW". It is not a DIST0 to DIST7 rewrite, because the action is "SA".

432 | 433 | It is described in [chemistry.js line 114]. In mol notation, the rewrite is described as:

434 | LHS = S 1 1 2, A 2 a 3, A 3 b 4, A 4 c d
435 | 436 | RHS = S c 1 2, A a 1 3, A b 2 4, A 3 4 d

437 | 438 | and as a chemical reaction by

439 | 440 | S-A rewrite

441 | 442 | with no tokens needed.

443 | 444 | The LHS and RHS patterns with the tokens, are the same:

445 | LHS with tokens = S 1 1 2, A 2 a 3, A 3 b 4, A 4 c d
446 | RHS with tokens = S c 1 2, A a 1 3, A b 2 4, A 3 4 d

447 | 448 | We can encode the passage from (LHS with tokens) to (RHS with tokens) as the permutation

449 | (0 1 2 3 4 5 6 7 8 9 a b c d e f)
450 | (0 e 1 3 4 6 2 7 8 a 5 b c 9 d f) 451 |

452 | 453 | 454 |

The rewrite COMB

455 |

(back to chemSKI rewrites)

is a generic rewrite which appears in all chemlambda formalisms. It has the role to eliminate Arrow nodes. It appears as

456 | {left:"any",right:"Arrow",action:"arrow", named:"COMB", kind:"COMPOSE"}

457 | 458 | 459 | It is described in [chemistry.js line 15]. In not quite a mol notation, is described as:

460 | LHS = [The other node connected to the edge named "a"], Arrow a b
461 | 462 | RHS = [That node where "a" is replaced by "b"]

463 | 464 | It is thus a schema of rewrites. As a a chemical reaction by

465 | 466 | COMB rewrite

467 | 468 | with no token as input and a token Arrow as output.

469 | 470 | 471 | 472 | 473 | 474 | 475 |

Tokens, synthesis and waste rewrites

476 |

(back to contents)


477 | 478 | Tokens rewrites are rewrites involving only tokens. They are needed in case we have tokens which do not appear as in tokens.

479 | 480 | Synthesis rewrites are needed to produce new graphs from old ones, outside of the chemSKI reduction. For example we may want to copy an existing graph, to erase one, or to produce a new graph from existing ones.

481 | Waste rewrites convert waste to tokens or useful graphs.

482 | In this version of the programs these rewrites are not implemented.

483 | 484 | 490 | 491 | 492 |

Tokens rewrites

493 |

(back to Tokens, synthesis and waste rewrites)

In this proposal we have only one such rewrite:

494 | S-S + A-A = 2 S-A

495 | The justification is that the tokens A-A and S-S never appear as In Tokens in the chemSKI rewrites, so there should be a way to convert these tokens into ones which can be used further.

496 | In mol notation, the rewrite is described as:

497 | LHS = S a b a, S c b c, A d e d, A f e f
498 | 499 | RHS = S a b a, S c e c, A d b d, A f e f

500 | 501 | and as a chemical reaction by

502 | 503 | token rewrite SSAA

504 | 505 | 506 | We can encode the passage from LHS to RHS as the permutation

507 | (0 1 2 3 4 5 6 7 8 9 a b c d e f)
508 | (0 1 2 3 4 5 a 7 8 9 6 b c d e f) 509 |

510 | 511 |

Synthesis S-K rewrite

512 |

(back to Tokens, synthesis and waste rewrites)

is a rewrite which rewires two FROUT nodes, with the help of a S-K token. 513 | In mol notation, the rewrite is described as:

514 | LHS with tokens = FROUT a, FROUT b, S c e c, K e
515 | 516 | RHS with tokens = FROUT e, FROUT c, S a e c, K b

517 | 518 | and as a chemical reaction by

519 | 520 | Synthesis S-K rewrite

521 | 522 | 523 | We can encode the passage from LHS with tokens to RHS with tokens as the permutation

524 | (0 1 2 3 4 5 6 7 8 9)
525 | (0 6 2 5 4 1 9 7 8 3) 526 |

527 | 528 | This rewrite is used to duplicate a graph and erase another. Indeed, suppose FROUT a and FROUT b are the free out nodes corresponding to the roots of two combinators, denoted Ta and Tb (converted to chemSKI). After the rewrite is done, the combinator Ta will be duplicated and the combinator Tb will be erased, by using only the chemSKI rewrites.

529 | 530 | These duplication and erasure rewrites will have costs which, in particular, can be used to define the cost of a graph (here cost[Ta]) or to define the cost of erasure of a graph (here the cost of reductions of the Tb graph connected to K). This can be used in section Cost of rewrites.

531 | 532 | In artificial life applications, such a rewrite, applied randomly, will trigger a duplication of a molecule and the erasure of another.

533 | 534 |

Synthesis S-A rewrite

535 |

(back to Tokens, synthesis and waste rewrites)

is a rewrite which rewires two FROUT nodes, with the help of a S-K token. In mol notation, the rewrite is described as:

536 | LHS with tokens = FROUT a, FROUT b, S c e c, A d e d
537 | 538 | RHS with tokens = FROUT e, FROUT c, S a e d, A d b c

539 | 540 | 541 | and as a chemical reaction by

542 | 543 | Synthesis SA rewrite

544 | 545 | 546 | We can encode the passage from LHS to RHS as the permutation

547 | (0 1 2 3 4 5 6 7 8 9 a b)
548 | (0 6 2 5 4 1 a 9 8 b 3 7) 549 |

550 | 551 | This rewrite is used to duplicate a graph and connect one of the copies to another, via an A node. Indeed, as before suppose FROUT a and FROUT b are the free out nodes corresponding to the roots of two combinators, denoted Ta and Tb (converted to chemSKI). After the rewrite is done, the combinator Ta will be duplicated (by the node S) into Ta1 and Ta2 and Ta2 will be applied to the combinator Tb, by using only the chemSKI rewrites.

552 | 553 | This rewrite may play the role of a rewrite from Combinatory Chemistry: Towards a Simple Model of Emergent Evolution arXiv:2003.07916:

554 | Ta + Tb = Ta Tb

555 | which does not have a correspondent in chemSKI rewrites.

556 | 557 | 558 |

Waste rewrites

559 |

(back to Tokens, synthesis and waste rewrites)

are rewrites involving tokens and inert 2 nodes graphs, like a pair of K-K or I-K or I-I or A-K graphs.

560 | 561 | We leave such rewrites unspecified exactly, but it is clear how to propose them. Some could be in a form similar to token rewrites, like

562 | K-K + S-S = 2 S-K

563 | I-I + A-A = 2 I-A

564 | I-K + A-A = A-K + I-A

565 | A-K + S-S = S-A + S-K

566 | With each such rewrite comes a cost, building towards a cost[waste], see section Cost of rewrites.

567 | 568 | UPDATE (23.06.2023): The following waste rewrites were added, compatible with those mentioned:

569 | (termKK):     K-K + S-S = 2 S-K

570 | (termIK):     I-K + A-A + S-S = (A-K + S-S + I-A = )   S-A + S-K + I-A

571 | The rewrite "termIK" is a one step version of two of the mentioned rewrites.



572 | 573 |

chemSKI + chemlambda v2

574 |

(back to contents)


575 | 576 | There is a variant of chemSKI which is fully compatible with chemlambda v2 rewrites, called "chemSKI+λ" where the occurences of the node S when there is no edge between ports 1 and 2 are replaced with a chemlambda node FOE. You can toggle between chemSKI and chemSKI+λ by using the "change" button.

577 | You can explore the differences between chemSKI and chemSKI+λ by using the parser window and button "λSKI -> mol".

578 | The parser transforms any mix of SKI with lambda calculus (where the letters "S", "K", and "I" are always interpreted as combinators, not lambda calculus variables) into a mol file (i.e. into a graph). This graph can be reduced with chemSKI or chemSKI+λ (ie chemSKI plus chemlambda).

579 | In the case of chemSKI the chemlambda nodes do not interpret the node S as a fanout, nor the pure chemSKI nodes (I,S,K) do not see FO and FOE as fanouts. Differently, if you change to the chemistry chemSKI+λ then the reductions work better, with the price of mixing the FO and FOE nodes into the pure chemSKI formalism.

580 | 581 |

chemSKI + directed Interaction Combinators?

582 |

(back to contents)


583 | 584 | There is not yet a variant of chemSKI compatible with dirIC (directed Interaction Combinators), because in dirIC the rewrite A-FOE from chemlambda is replaced by a rewrite FI-A. This breaks the adaptation chemSKI+λ of chemSKI to chemlambda by replacing the node S as a fanout by a node FOE. It is an interesting problem to consider.

585 | 586 | 587 |

How are chemSKI rewrites used

588 |

(back to contents)


589 | 590 | All the programs are abundantly commented, for the convenience of the reader. The way rewrites are done by the programs is described shortly here.

591 | 592 | The recognition of the LHS pattern is defined in [chemistry.js from line 293] in the function 593 | findTransform(n1), where "n1" is the node where the recognition of the LHS pattern algorithm starts (it should have the type ot the "right" field of the transform). The rewrite is identified by the "action" field, for our example, the rewrite I-S, we have action:"terminIS", and the recognition of the LHS pattern for that transform is done at 594 | [chemistry.js lines 448-456], which starts with:

595 | 596 | "case "terminIS": case "terminIFOE": "

597 | 598 | (Thus we may have the same algorithm of recognizing LHS patterns for different action fields, which is not surprising, because the algorithm describes an abstract way to visit a pattern and to perform checks.)

599 | 600 | If the LHS pattern of the transform trans (defined by the transform "action" field and the node n1 seen as a node of the type defined by the "right" field) is found then the function returns the transform trans. Then the graph rewrite is done by the function doTransform(n1, trans), defined in [chemistry.js from line 602]. At the level of mol files, doing the rewrite means: eliminate the lines in the mol file which correspond to the nodes from the identified LHS pattern, add to the mol file the new lines corresponding to the RHS pattern.

601 | 602 | There is no canonical way, no particular order of the lines in the mol file associated to a graph. Any permutation of the lines in the mol file describes the same graph. Any renaming of the edges describes the same graph. That is why we randomly shuffle the mol file before looking for rewrites and we also randomize the choice of rewrites which will be applied. The probability of application of rewrites depends on their "kind", but roughly there is a parameter which is controlled by the "rewrites weight slider" which favors either the rewrites of the kind which increases (or does not decrease)the number of nodes (ie "GROW"), typically of kind "DIST", or the kind which decreases the number of nodes (ie "SLIM"), such as kinds "TERMINATION" or "BETA". Another control we have is to associate to the edges of the graph an age (how many time steps since that edge appeared) and then to favor the rewrites performed on older edges first. As the programs don't do rewrites in parallel (although the first version, in awk, chemlambda-gui, does this for chemlambda v2), this age-based choice of rewrites is a good approximation of the choice to do as much as possible independent rewrites, as soon as possible. This age-based strategy is not used in this version of chemSKI. See Alife properties of directed interaction combinators vs. chemlambda. Marius Buliga (2020), arXiv:2005.06060.

603 | 604 | 605 | 606 | 607 |

From SKI to chemSKI

608 |

(back to contents)


609 | 610 | The chemSKI molecule associated to a SKI combinator term is simply the syntax tree of the term, which has as leaves the S,K,I combinator nodes. Go to Play with chemSKI to use the parser. Use the window "λ or SKI -> mol" to parse a SKI combinator to chemSKI. Actually this is a parser from lambda calculus AND SKI combinators to chemlambda AND chemSKI, where the letters "S", "K" and "I" are treated as in SKI. The source is at [0parser.js].
611 | 612 | Examples:
613 | SII will not work, use a space for application: S I I will be understood as the term (S I) I.
614 | (S I I) (S I I) will work
615 | Also, the parser works for lambda terms, like (\x.x x) (\x.x x) or (\x.\y.x) z.

616 | 617 | 618 | 619 | 620 | 621 |

Play with chemSKI

622 |

(back to contents)


623 | 624 | 625 | 626 |
627 |
628 | 629 |
630 | 643 | 676 | 680 |
681 | 682 |
683 | 686 | 689 | 691 |
692 | 693 |
694 | 701 | 709 | 712 |
713 | 714 |
715 |
716 | before:

717 | 718 |
719 |
720 | chosen:

721 | 722 |
723 |
724 | after:

725 | 726 |
727 |
728 | mol before:

729 | 730 |
731 |
732 | mol after:

733 | 734 |
735 |
736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 762 | 763 | 764 | 765 | 766 | 767 | --------------------------------------------------------------------------------