chemart / farmer-immune
View on GitHubBitstring immune system model (idiotypic network) — An immune system as a reaction network, and one of the few chemistries that fixes its own rate constants. Antibodies are bitstrings with two sites; when one antibody's paratope matches another's epitope, the recogniser i…
How it works
An immune system as a reaction network, and one of the few chemistries that fixes its own rate constants. Antibodies are bitstrings with two sites; when one antibody's paratope matches another's epitope, the recogniser is replicated and the recognised destroyed. The crucial move is that the reaction rate is computed from the *degree* of complementarity between the strings, over all alignments - structure determines kinetics. Species below a concentration threshold are periodically culled and new ones injected, so the species set turns over.
- S
- antibodies X_i as binary strings with two binding sites (epitope e, paratope p); antigens Y_j with an epitope · implicit
- R
- Recognition of an epitope by a paratope replicates the recogniser and destroys the recognised. Matching specificity: m_ij = sum_k G( sum_n [ e_i(n+k) XOR p_j(n) ] - s + 1 ), G(x)=x for x>0 else 0, over all alignments -l_p < k < l_e. · arity 1, 2
- A
- ode, ssa · metadynamics: periodically drop species below a concentration threshold and inject new ones
Parameters
| name | default | meaning |
|---|---|---|
| N int · population |
10 | number of antibody species [1, 100] |
| M int · population |
2 | number of foreign antigens [0, 20] |
| l_e int · structural |
8 | epitope length (bits) [1, 64] |
| l_p int · structural |
8 | paratope length (bits) [1, 64] |
| s int · structural |
6 | matching threshold: an alignment counts when at least s bits are complementary [1, ∞] |
| c float · kinetic |
1.0 | weight of the interactive part vs. spontaneous decay [0, ∞] |
| k1 float · kinetic |
1.0 | suppression vs. stimulation weight, antibody-antibody [0, ∞] |
| k2 float · kinetic |
0.5 | spontaneous antibody decay rate [0, ∞] |
| k3 float · kinetic |
1.0 | suppression weight, antibody-antigen [0, ∞] |
Bitstring immune system model (idiotypic network)
One of the artificial chemistries of Banzhaf & Yamamoto, Artificial Chemistries (MIT Press, 2015), §11.2.2; first proposed by Farmer, Packard & Perelson, 1986.
Its generator ships with the chemart library, so loading it runs no code from the hub and needs no trust_remote_code.
import chemart
net = chemart.generate_network("chemart/farmer-immune", seed=0) # same as "farmer-immune"
print(net.summary())
What to look for
- clonal selection
- idiotypic network memory
- constructive dynamics via metadynamics
Implementation decisions
- Strings are random bits from the seed. Each term of eqs. 11.5-11.6 is one mass-action reaction whose rate the matching strengths prescribe: stimulation X_i + X_j -> 2X_i + X_j (c m_ji), suppression X_i + X_j -> X_j (c k1 m_ij), antigen stimulation X_i + Y_j -> 2X_i + Y_j (c m), antigen removal Y_j + X_i -> X_i (k3 m), decay X_i -> (k2). A self-interaction i = j uses 2X_i on the left.
- The book says strings bind when 's > min(l_e, l_p)', which contradicts its own definition of G. Here an alignment contributes when at least s bits are complementary, which is what eq. 11.4 computes.
- The book gives no parameter values; defaults are N = 10, M = 2, 8-bit sites, s = 6, c = k1 = k3 = 1, k2 = 0.5. Metadynamics (mutation and replacement) acts between network snapshots and is not generated; mutation_ops is dropped.
Banzhaf & Yamamoto, Artificial Chemistries (2015), §11.2.2
Preview at default parameters
12 species · 88 reactions · status complete · seed 1
X1 + X2 -> 2 X1 + X2 [mass-action k=1.0] X1 + X4 -> X4 [mass-action k=1.0] X1 + X5 -> X5 [mass-action k=1.0] X1 + X6 -> 2 X1 + X6 [mass-action k=1.0] X1 + X7 -> 2 X1 + X7 [mass-action k=1.0] X1 + X8 -> X8 [mass-action k=1.0] X1 + X10 -> 2 X1 + X10 [mass-action k=1.0] X2 + X1 -> X1 [mass-action k=1.0] 2 X2 -> 3 X2 [mass-action k=2.0] 2 X2 -> X2 [mass-action k=2.0] X2 + X3 -> X3 [mass-action k=1.0] X2 + X4 -> 2 X2 + X4 [mass-action k=1.0] X2 + X5 -> X5 [mass-action k=3.0] X2 + X7 -> 2 X2 + X7 [mass-action k=2.0] X2 + X7 -> X7 [mass-action k=2.0] X2 + X9 -> 2 X2 + X9 [mass-action k=1.0] X2 + X10 -> 2 X2 + X10 [mass-action k=2.0] X3 + X2 -> 2 X3 + X2 [mass-action k=1.0] X3 + X5 -> 2 X3 + X5 [mass-action k=1.0] X3 + X5 -> X5 [mass-action k=1.0] X3 + X6 -> X6 [mass-action k=1.0] X3 + X8 -> 2 X3 + X8 [mass-action k=2.0] X3 + X10 -> X10 [mass-action k=2.0] X4 + X1 -> 2 X4 + X1 [mass-action k=1.0] X4 + X2 -> X2 [mass-action k=1.0] 2 X4 -> 3 X4 [mass-action k=2.0] 2 X4 -> X4 [mass-action k=2.0] X4 + X5 -> 2 X4 + X5 [mass-action k=1.0] X4 + X5 -> X5 [mass-action k=1.0] X4 + X7 -> 2 X4 + X7 [mass-action k=1.0] X4 + X8 -> X8 [mass-action k=1.0] X4 + X9 -> 2 X4 + X9 [mass-action k=2.0] X4 + X10 -> 2 X4 + X10 [mass-action k=1.0] X5 + X1 -> 2 X5 + X1 [mass-action k=1.0] X5 + X2 -> 2 X5 + X2 [mass-action k=3.0] X5 + X3 -> 2 X5 + X3 [mass-action k=1.0] X5 + X3 -> X3 [mass-action k=1.0] X5 + X4 -> 2 X5 + X4 [mass-action k=1.0] X5 + X4 -> X4 [mass-action k=1.0] 2 X5 -> 3 X5 [mass-action k=1.0] … 48 more
Generated by the uploader with chemart push; the hub never runs uploaded code.