Genetic programming¶
Prefix-tree GP (loosely typed, strongly typed, ADFs) is still there. The following is extra.
generate()closes a type that has terminals but no primitives. A leaf-only type — a rolling window length is the usual case — can appear in a strongly typed tree.add_primitive(..., weight=)implements weighted primitive sampling. Equal weights keep the previous RNG stream. The same weights apply to node replacement and insert mutation. Terminals stay uniform.- A zero-arity callable terminal can format as
name()whenadd_terminal(..., call_zero=True), so the defaultevalcompile path calls it instead of looking up the function object. Action terminals (Santa Fe ant) stay uncalled names by default. tree_to_infixis an infix pretty-printer for logs and papers. It is display-only.make_column_pset(names)builds a strongly typed set with oneArrayinput per column. The type tags areArray(1Dfloat64),Mask(1Dbool), andWindow(int). Argument order is column order.add_numpy_primitivesregisters a vectorized kit: arithmetic, protectedvdiv/vlog/vsqrt, comparisons that produce aMask, mask logic, andvwhere. Protected ops only replace a non-finite result that the operation itself fabricated; an inputnancomes back out asnan.add_window_primitivesregisters causaldelay,diff,rolling_{sum,mean,std,min,max}, andema. The window is[t-n+1, t]; samples without enough history arenan. Look-ahead is forbidden.add_window_ephemeralsamples inclusive integer lengths.compile_treecaches the defaultevalbackend by expression text and context identity.backend="opcode"lowers the tree to a postfix tape and runs a NumPy stack machine.backend="numba"(thedeap-er[numba]extra) runs the same tape in one process-wide compiled interpreter. Custom kernels bind at or aboveUSER_BASEand pass one dispatcher; they are not a second interpreter.- Algorithms call
toolbox.evaluate_batch(invalids)when that operator is registered, otherwisetoolbox.map(toolbox.evaluate, invalids).ea_generate_updateandea_generate_update_restartsgo through the sameevaluate_invalidpath. A generation can be scored against one shared matrix without changingmap's contract. tools.clone_individualshallow-copies a list/array individual and deepcopies only the fitness. GP toolboxes should register it; the default Toolbox clone remainsdeepcopy.cx_semanticbuilds each child from a snapshot of the original parents. The second child is no longer derived from the already mutated first child.cx_one_pointalways groups nodes by return type. Anobjectroot on the first parent no longer disables strongly typed matching.static_limitreplaces an oversized offspring with aclone_individualcopy of a parent, so the two offspring slots never share one parent object.- HARM places the size cutoff on evaluated individuals only, scales the half-life by the cutoff (not by each individual's size), and does not crash on an empty candidate slice.
add_primitiveandadd_terminalreject a name that matches a primitive-set argument, so a compiled lambda parameter cannot shadow the symbol.rename_argumentsrejects the inverse: a new name that is already an argument, primitive, or terminal.mut_insertleaves the tree unchanged when a sibling type has no terminals, instead of raisingIndexError.add_pair_window_primitivesregisters causalrolling_corr,rolling_cov, androlling_betaover twoArrayarguments and aWindow. Moments use the population divisor; beta is the OLS slope of the first series on the second. Python, opcode, and Numba paths agree.add_ts_primitivesregisters causalts_rank,ts_argmax, andts_argmin. Rank is the average rank of the current sample scaled to \([0, 1]\); a window of 1 isnan. Arg-extremum is how many samples ago the extreme occurred (0is now); a tie keeps the most recent. Python, opcode, and Numba paths agree.interpret_tapesscores many tapes against one packed(rows, columns)matrix and returns(n_individuals, n_rows). The opcode path unpacks columns once. The Numba path is a compiled loop;parallel=Truegives each thread its own workspace. Unique programs are compiled once bystr(tree)and lowered from the tree object.tape_lookbackreturns the program's causal bound;suffix_rescorewrites a dirty suffix onto a cached prefix so the series matches that full-matrix oracle.SlimTreestores a GP head plus semantic delta blocks.mut_slim,mut_slim_inflate, andmut_slim_deflateappend or remove deltas without re-wrapping the whole tree;cx_slim_donorswaps a donor block size-preservingly.compile_slim_treeevaluates \(\mathrm{head} + \sum \delta_i\).PrimitiveTreeslice assignment treats a missing start as0.tree[:]andtree[:n]no longer raiseTypeErrorwhen the replacement is a complete tree.tune_ephemeralsextracts ephemeral floats andWindowints in documented prefix order (SlimTree: head, then deltas), runs a short boxedStrategy/StrategySeparablegenerate/updateloop, writes repaired values back, and invalidates fitness plus the compile-cache entry for the old expression.semantic_moments,semantic_solve_bits, andsemantic_projectturn aninterpret_tapes(n_individuals, n_rows)pack into a behavior descriptor (per-row moments, lexicase solve bits, or a caller PCA / random basis).semantic_nearestlooks up cosine or Euclidean neighbors on the finite /valid=mask.SemanticSurrogateis a last-generation linear or nearest-neighbor stand-in. Fitness stays onind.fitness; the archive still ranks a cell by fitness.promote_subtreelifts a complete typed subtree into the samePrimitiveSetTypedas a generated primitive (promo0, …). Latergenerate/ mutation can sample that name. The library is capped; the least-used promoted name is evicted, not a built-in. Columnar sets bind atUSER_BASEandlower_treeexpands the body so tapes stay on builtin opcodes.add_adfremains the static path.PrimitiveTree.from_stringaccepts anintliteral in aWindowslot.str(tree)writes window lengths as integers; the opcode backend no longerTypeErrors when compiling that text, and a stringified windowed tree round-trips.PrimitiveTree.from_stringrejects extra tokens and incomplete calls.add(ARG0, 2, 3)andadd(ARG0)no longer stringify as a leftover leaf and compile as the constant \(3\) or the identity.affine_scalefits Keijzer \(a + b\,f(x)\) on the samevalid=mask ascase_errors. Darwinian callers use the scaled series only for fitness / case errors. Lamarckianwrite_affine_scalewrites \(a\) and \(b\) back as ephemerals wrapping aPrimitiveTree, or as wrapping Slim deltas, then invalidates fitness and the compile cache for that expression.LinearPolicyProgram,PushPolicyProgram, andstep_policy_loopimplement the private Push GP loop behind the P11–P14 firewall.policy_observesupplies summary observations;linear_policy_decide/push_policy_decideemit discrete action tokens;apply_policy_actiondispatches them. No column loads, noWindowPush type, and no publicPushTreeongportools. Tapes remain the onlyinterpret_tapestarget. Not a second public genome (Push GP P19).interpret_tapeshash-conses postfix subexpressions across a batch and evaluates each unique sub-tape once against the packed matrix. Shared suffixes are stitched from one oracle result per node. The return shape, warmupnancontract, and per-tapefillsemantics are unchanged. See the columnar GP tutorial.- HARM
natural_histogramdoes not wraphist[-1]when a tree has size \(0\). The left-neighbor bin is updated only forind_size >= 1, matching the existingind_size - 2guard. register_gpwires the standard tree-GP toolbox:clone_individual,compile_tree, half-and-half init, one-point crossover, uniform mutation, and a heightstatic_limit.columnar_psetbuilds the typed column set and registers the NumPy / window kits (optional pair-window, time-series, and window ephemeral) in one call.evaluate_columnaris theevaluate_batchhelper: unique trees are lowered once, scored withinterpret_tapes, and warmupnansamples are dropped from the MSE. DEAP leaves that wiring on every caller.MEMETIC_DEFAULT_N_GENandMEMETIC_MAX_N_GENdocument the recommended memetic polish.tune_ephemerals_budgetcaps innern_gento remainingn_evals, defaults to the small generation count, and judges trials on a caller-marked held-out exam when one exists.cap_tune_n_genandestimate_tune_ephemerals_evalsshare the tune cost model withPolicyActionGuard. Rawtune_ephemeralsis unchanged; policy caps stay on the guard.bounds_from_matrix,tape_interval, andtape_flagspropagate column bounds through the builtin opcode kit and certificate identically-nan, constant, or warmup-hidingvwhereprograms beforeinterpret_tapes.evaluate_columnar(..., static_filter=True)skips them with the existingemptysentinel. Not a substitute for the runtime warmup contract orcase_errors(..., valid=).cx_homologousswaps subtrees at the same root-to-node path when return types match, otherwise falling back to type-matched one-point.cx_one_point_semanticpicks the type-matched partner whoseinterpret_taperow is nearest to the anchor subtree viasemantic_neareston batchedinterpret_tapesrows.cx_one_pointremains the default mate.
The columnar contract is in the columnar GP tutorial. The private Push policy loop is in the Push GP tutorial. Shared-array evaluation is in the multiprocessing tutorial.