chemart / high-order-chem
View on GitHubHigh-order chemistry (rules as molecules) — A chemistry whose rules are themselves molecules. The vessel holds two multisets, one of data and one of rules; each step draws a rule, counts its binding sites, draws that many data molecules, applies it, and returns ev…
hub:
repo_type: generator
builtin: high-order-chem
tags:
- banzhaf-yamamoto
chemistries:
- id: high-order-chem
name: High-order chemistry (rules as molecules)
intuition: 'A chemistry whose rules are themselves molecules. The vessel holds two multisets, one of
data and one of rules; each step draws a rule, counts its binding sites, draws that many data molecules,
applies it, and returns everything - rule included - to the vessel. Because a rule is a molecule,
its concentration matters: rules compete for substrate and can be added or removed at run time. The
natural next step, rules that rewrite rules, is what the design points at without yet doing.
'
aliases:
- HighOrderChem
- NumberChemHO
origin: Yamamoto, 2014 (PyCellChemistry); Banzhaf & Yamamoto, 2015
book: 'appendix: Writing Your Own Artificial Chemistry in Python, ''A High-Order Chemistry'' (figure
3, divrule); module list (HighOrderChem.py)'
refs:
- https://github.com/laryamamoto/PyCellChemistry
family: core
kind: framework
constructive: true
S:
repr: 'two multisets: data molecules (JSON integers or lists; species n<k> or compact JSON text such
as [0,3,1,2]) and rule molecules (species rule:<name>, structure the rule text, e.g. divrule(m1,
m2))'
definition: implicit
notes: 'the rule multiset is constant: rules are never consumed and never rewritten'
R:
definition: implicit
arity: variable - the number of binding sites of the drawn rule, plus the rule molecule itself
scheme: rule + m1 + ... + mk -> rule + products(m1, ..., mk), k = binding sites of the rule; e.g.
rule:divrule + n12 + n3 -> rule:divrule + n4 + n3
notes: rules are catalysts of every reaction they execute because they are reinjected; rules are built-in
named functions or expressions in a small interpreted language, never executed Python strings
A:
reactor: well-stirred-multiset
dilution: none - products replace educts; the data population changes only if a rule returns more
or fewer molecules than it binds
notes: 'per iteration: draw a random rule (stop if none), count its binding sites nsites, if at least
nsites data molecules are present draw nsites of them without replacement, execute the rule, inject
its products, reinject the rule (book figure 3)'
params:
- name: method
type: enum
default: soup
choices:
- soup
- closure
role: structural
meaning: 'soup: the book''s HighOrderChem.iterate loop, observed effective reactions with counts;
closure: every reaction reachable from the distinct data molecules under deterministic rules (Chemart
addition)'
- name: rules
type: dict
default:
divrule: 4
range: 'NumberChemHO.py: {divrule: 4}; MolecularTSP.py: {exchangeMachine: 100, cutMachine: 100, invertMachine:
100, recombinationMachine: 1}'
role: structural
meaning: 'the rule multiset {rule: multiplicity}; this IS the chemistry. A rule is a built-in name
(divrule, exchangeMachine, cutMachine, invertMachine, recombinationMachine), optionally written
as its rule molecule ''divrule(m1, m2)'', or an expression rule ''[name:] x, y -> expr, ... [if
condition]'' (integers, + - * / % comparisons and or not, min max abs; see the module docstring).
Rules are selected with probability proportional to multiplicity'
- name: data
type: list
default: []
role: structural
meaning: explicit initial data multiset as a list of JSON integers or lists; overrides the random
initialisation selected by init
- name: init
type: enum
default: numbers
choices:
- numbers
- tours
role: structural
meaning: 'random data multiset when data is empty: numbers draws M integers uniformly from [minn,
maxn] (NumberChemHO.py); tours draws M random tours on the ring of `cities` cities (MolecularTSP.py)'
- name: M
type: int
default: 100
min: 1
max: 100000
range: NumberChemHO.py popsize 100; MolecularTSP.py popsize 9
role: population
meaning: number of data molecules drawn when data is empty
- name: minn
type: int
default: 2
min: 1
role: structural
meaning: 'init numbers: lower bound of the uniform draw (inclusive)'
- name: maxn
type: int
default: 1000
min: 1
role: structural
meaning: 'init numbers: upper bound of the uniform draw (inclusive)'
- name: cities
type: int
default: 10
min: 3
max: 1000
range: MolecularTSP.py default 10
role: structural
meaning: number of cities on the ring instance that the tour machines (and init tours) use; tours
are permutations of 0..cities-1
- name: iterations
type: int
default: 10000
min: 0
max: 10000000
range: 'NumberChemHO.run: 10000; MolecularTSP.py: up to 1000 generations of ceil(M * 100 / |rules|)
iterations'
role: population
meaning: 'soup only: number of iterations of the algorithm (one rule drawn per iteration, elastic
and idle ones included)'
- name: max_species
type: int
default: 1000
min: 1
role: structural
meaning: 'closure only: budget of data species; status truncated when exceeded'
provides:
- topology
- stoichiometry
- catalysts
- initial-state
- sequence-structure-function
fidelity: book+decisions
sources:
- Banzhaf, W. & Yamamoto, L. (2015). Artificial Chemistries. MIT Press. Appendix, 'A High-Order Chemistry'
(figure 3 and the divrule listing).
- PyCellChemistry src/HighOrderChem.py, src/NumberChemHO.py, src/MolecularTSP.py and src/artchem/Multiset.py
(Yamamoto, 2014). https://github.com/laryamamoto/PyCellChemistry
decisions:
- 'Security: the reference executes rule strings with exec. Chemart never executes a string: a rule
is looked up by name in a registry of built-in functions ported from the reference examples (divrule
from NumberChemHO.py and the book; exchangeMachine, cutMachine, invertMachine, recombinationMachine
from MolecularTSP.py), or parsed and interpreted as an expression rule in a small documented language.
Unknown names are rejected with ValueError. Subclass methods (the book''s self.fold(m)) are replaced
by the registry; a leading self. is accepted and ignored.'
- 'Binding sites: for named rules nsites is computed from the rule molecule exactly as figure 3 does
(len(bsite.split('',''))), and a user-written rule molecule must have as many sites as the function
takes (the reference would crash on a mismatch). For expression rules nsites is the number of binding-site
variables.'
- Multisets are lists; a random draw removes a uniformly chosen molecule, the same distribution as Multiset.expelrnd
(each molecule with probability 1/total). The rule is drawn and reinjected every iteration, so the
rule multiset never changes and rules are catalysts in the network (the rule species appears on both
sides).
- When fewer data molecules than binding sites are present, the rule is reinjected and nothing else
happens (figure 3 lines 17 and 26); such iterations count towards `iterations` and are reported as
extras.analysis.idle_draws.
- divrule is written with Python 2 integer division in the book (m1 / m2 on ints); it is floor division
(//), exact here because the quotient is only taken when it divides. Built-in rules collide elastically
(return their educts) on molecules outside their domain (non-integers or 0 for divrule, non-tours
for the machines), where the reference would raise.
- 'Default rules {divrule: 4}, M = 100 from [2, 1000] and 10000 iterations are NumberChemHO.py''s; the
book only says ''at least one molecule of divrule(m1, m2)''. With a single rule type the multiplicity
does not change the dynamics.'
- 'The observed network keeps the effective reactions (HighOrderChem.is_effective: product multiset
differs from educt multiset) with firing counts; initial_state and extras.final_state include the
rule molecules; extras.analysis records rule_draws per rule, and prime_fraction per generation of
M iterations when the only rule is divrule on integers (NumberChemHO.nprimes).'
- 'Tour machines use MolecularTSP.py''s ring topology (TSPgraph ring=True: gridsize 2N, radius N, fully
meshed roads) and its fitness with penalties; a tour molecule is the list of cities rather than the
string ''fitness [tour]'', since the fitness is a function of the tour. The reference''s %g rounding
of the stored fitness is kept (the drawn molecules'' fitness is compared after ''%g'' formatting,
the new tour''s exactly). The random topology is not offered: the dedicated molecular-tsp chemistry
covers the full model. List molecules must be permutations of 0..cities-1 when a machine is in the
rule set.'
- method closure is a Chemart addition (chemart.expand.expand, ordered reactants, each rule producing
its own reaction); it is only defined for deterministic rules, so the stochastic tour machines are
rejected.
- 'The book''s caveat is kept: this is not yet truly high-order, since rules never take rules as educts
and cannot rewrite rules (no typed binding sites).'
- v1 parameters rules (callable) and seed (matrix) are replaced by the JSON rule multiset `rules` and
the data multiset `data`/`init`; the v1 name `seed` is the generate_network seed.
reference_impl: PyCellChemistry HighOrderChem.py (NumberChemHO.py, MolecularTSP.py build on it)
phenomena:
- 'the divrule rule set reproduces the prime-number chemistry: primes are never consumed, composites
are divided, and the prime fraction grows towards 1 (book appendix: ''the results should be the same
as the original NumberChem implementation'')'
- 'rule molecules are catalysts: every reaction has its rule on both sides and the rule multiset stays
constant'
- 'rules compete for substrate: each iteration one rule is chosen with probability proportional to its
multiplicity'
- changing the rule multiset changes the chemistry without changing the algorithm (e.g. the molecular
TSP machines on tour molecules)
notes: 'Not a chemistry but a substrate for constructive chemistries, and the closest PyCellChemistry
analogue of Chemart''s own react/expand/soup split. The book notes that making it truly high-order
would need typed binding sites so that rules can take other rules as educts, and rule sets that keep
rewritten rules functional.
'