This repository contains the current ACS2-based and CPU/GPU driven implementation of the Anticipatory Learning Classifier System library available at:
https://github.com/ounold/ALCS
The current implementation was developed in an AI-assisted programming workflow, with iterative human supervision, validation, and refinement of both the research code and the experimental tooling.
The codebase provides a unified entry point for running ACS2 experiments across:
cpu_singlefor sequential CPU execution,cpu_mpfor multiprocessing CPU execution,gpufor tensorized batched GPU execution,gpu_seqfor independently seeded sequential GPU execution.
The main executable is acs2.py. It supports full single-backend runs as well as mixed backend schedules across the three ACS2 phases:
exploreexploit1exploit2
After each run, the program generates a dashboard in reports/ summarizing learning progress, exploit performance, rule-population behavior, and selected structural metrics.
For a full parameter reference, see parameter_guide.md.
- Unified ACS2 runner through
acs2.py - Four execution backends:
cpu_single,cpu_mp,gpu,gpu_seq - Mixed-mode execution through
UniversalRunner - Dashboard generation after each run
- Support for maze, multiplexer, binary-classification, and Gymnasium environments
- Batch maze benchmarking through
run_maze_benchmarks.py - Optional
no_subsumptionmode for ablation and backend-comparison studies - Reproducible execution through an explicit
seedparameter
git clone https://github.com/ounold/ALCS.git
cd ALCSWindows:
python -m venv .venv
.\.venv\Scripts\activateLinux/macOS:
python -m venv .venv
source .venv/bin/activatepip install torch gymnasium numpy pandas matplotlib pyyaml.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode cpu_single --exploit_mode cpu_single --device cpu.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode cpu_mp --exploit_mode cpu_mp --device cpu.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode gpu --exploit_mode gpu --device cudaUse this mode when you want statistically cleaner repeated GPU runs with one independently seeded GPU execution per experiment:
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode gpu_seq --exploit_mode gpu_seq --device cudaGPU in explore, CPU in both exploit phases:
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode gpu --exploit_mode cpu_mp --device cuda.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode cpu_single --exploit_mode cpu_single --device cpu --no_subsumption trueThe main script:
- loads YAML defaults,
- applies CLI overrides,
- builds an experiment configuration,
- runs all three phases through
UniversalRunner, - computes final summary metrics,
- generates a dashboard in
reports/.
.\.venv\Scripts\python.exe acs2.py --config <config.yaml> --explore_mode <cpu_single|cpu_mp|gpu|gpu_seq> --exploit_mode <cpu_single|cpu_mp|gpu|gpu_seq> --device <cpu|cuda|auto>If --exploit_mode is omitted, acs2.py defaults to cpu_single for exploit1 and exploit2.
Maze environments are resolved by name from environment/acs2_mazes.
Example: Woods1
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --environment_type grid_maze --environment_name Woods1 --explore_mode cpu_single --exploit_mode cpu_single --device cpuExample: MazeE3 with multiprocessing
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --environment_type grid_maze --environment_name MazeE3 --explore_mode cpu_mp --exploit_mode cpu_mp --device cpu --no_subsumption trueExample: full GPU maze run
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --environment_type grid_maze --environment_name Cassandra4x4 --explore_mode gpu --exploit_mode gpu --device cuda --no_subsumption trueExample: statistically independent GPU maze run
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --environment_type grid_maze --environment_name Cassandra4x4 --explore_mode gpu_seq --exploit_mode gpu_seq --device cuda --no_subsumption trueFor multiplexer tasks, use environment_type=multiplexer.
Example:
.\.venv\Scripts\python.exe acs2.py --environment_type multiplexer --environment_name mux_11 --address_bits 3 --sampling random --n_steps 1 --n_exp 10 --explore_mode cpu_mp --exploit_mode cpu_mp --device cpuA 3-bit address multiplexer implies 3 + 2^3 = 11 input bits.
For multiplexer-like tasks, n_steps=1 is usually the correct setting.
Example: even parity
.\.venv\Scripts\python.exe acs2.py --environment_type binary_classification --environment_name even_parity_6 --problem_kind even_parity --input_bits 6 --n_steps 1 --explore_mode cpu_single --exploit_mode cpu_single --device cpuExample: carry
.\.venv\Scripts\python.exe acs2.py --environment_type binary_classification --environment_name carry_8 --problem_kind carry --left_bits 4 --right_bits 4 --n_steps 1 --explore_mode cpu_mp --exploit_mode cpu_mp --device cpuGymnasium environments use environment_type=gymnasium.
Example: FrozenLake
.\.venv\Scripts\python.exe acs2.py --environment_type gymnasium --environment_name FrozenLake-v1 --env_id FrozenLake-v1 --is_slippery false --observation_encoding auto --n_exp 10 --n_steps 100 --explore_mode cpu_single --exploit_mode cpu_single --device cpuExample: CartPole with binned observations
.\.venv\Scripts\python.exe acs2.py --environment_type gymnasium --environment_name CartPole-v1 --env_id CartPole-v1 --observation_encoding binned --bins 8 8 8 8 --n_exp 10 --n_steps 200 --explore_mode cpu_single --exploit_mode cpu_single --device cpuThe helper script run_maze_benchmarks.py runs the maze benchmark over:
- all mazes from
environment/acs2_mazes, or a selected subset from YAML, - all modes from YAML, or the default set:
CPU SingleCPU MPGPUGPU SeqGPU (PyTorch CPU)GPU Seq (PyTorch CPU)GPU CUDAGPU Seq CUDA
It stores a CSV with:
total_time_savg_exp_time_sstd_exp_time_sexploit_avg_stepsexploit_avg_steps_stdmicro_pop_exploit2_avgmacro_pop_exploit2_avgmicro_pop_rel_exploit2_avgmacro_pop_rel_exploit2_avg- GPU timing breakdown columns
The population columns are averaged over the exploit2 phase so they align with the exploit-step quality metric. Here:
micro_pop_exploit2_avgcounts all classifiers with numerosity,macro_pop_exploit2_avgcounts unique classifiers,*_rel_*restricts the population to reliable classifiers only.
.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/batch_mazes.yaml.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/batch_mazes.yaml --output reports\maze_benchmarks_full.csv.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/batch_mazes.yaml --no_subsumption --output reports\maze_benchmarks_no_subsumption.csv.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/batch_mazes.yaml --mode gpu_seq --output reports\maze_benchmarks_gpu_seq.csvThis is the most direct way to answer whether the tensorized PyTorch implementation is competitive on CPU alone:
modes:
- cpu_single
- cpu_mp
- gpu_cpu
- gpu_seq_cpuThen run:
.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/my_cpu_comparison.yaml --output reports\maze_benchmarks_torch_cpu_vs_cpu.csvMode meaning in the benchmark script:
gpu_cpu: batched tensorized backend forced todevice=cpugpu_seq_cpu: independently seeded sequential tensorized backend forced todevice=cpugpu_cuda: batched tensorized backend forced todevice=cudagpu_seq_cuda: independently seeded sequential tensorized backend forced todevice=cuda
run_maze_benchmarks.py also supports YAML keys:
mazes:modes:
Example:
mazes:
- Woods1
- MazeE3
modes:
- cpu_single
- cpu_mp
- gpu_seq_cpu
- gpu_seq_cudaThen run:
.\.venv\Scripts\python.exe run_maze_benchmarks.py --config experiments/configs/my_subset.yamlAfter every acs2.py run, a dashboard PNG is saved in reports/.
The dashboard includes:
- steps to goal over episodes,
- population size,
- knowledge and generalization,
- reward and quality,
- policy map,
- top rules,
- rule-origin distributions,
- creation-distribution summaries,
- final textual summary.
.\.venv\Scripts\python.exe acs2.py --config experiments/configs/batch_mazes.yaml --explore_mode cpu_single --exploit_mode cpu_single --device cpu --save_dashboard_data.\.venv\Scripts\python.exe acs2.py --load_dashboard_data <timestamp> --plot_all_dashboardsYou can also render only selected plots with:
--plot_steps--plot_population--plot_knowledge--plot_reward_quality--plot_policy_map--plot_top_rules--plot_origin_distribution--plot_origin_distribution_abs--plot_creation_dist <key>
ALCS/
|-- acs2.py
|-- run_maze_benchmarks.py
|-- experiments/
| `-- configs/
|-- environment/
| |-- acs2_mazes/
| |-- registry.py
| |-- runtime_cpu3.py
| `-- runtime_gpu4.py
|-- reports/
| `-- saved_states/
|-- src/
| |-- universal_runner.py
| |-- hybrid_utils.py
| |-- configCPU3.py
| |-- configGPU4.py
| |-- experiment_runnerCPU3.py
| |-- experiment_runnerGPU4.py
| |-- visualizationCPU3.py
| `-- visualizationGPU4.py
`-- parameter_guide.md
cpu_singleandcpu_mpuse the same ACS2 learner;cpu_mpparallelizes independent experiments.gpuis a tensorized backend and is not behaviorally identical to the CPU implementations.Exploit Avg. Stepsis computed from theexploit2slice ofstats_steps.- Maze names passed through
--environment_namenow resolve correctly to the real ACS2 maze definitions.
- Main parameter reference: parameter_guide.md
- Benchmark helper: run_maze_benchmarks.py
- Main entry point: acs2.py
If you use this library, please cite the repository:
Olgierd Unold. 2026. A high-performance ACS2 based on vectorization and GPU.
In Proceedings of the Genetic and Evolutionary Computation Conference Companion. ACM.
URL: https://github.com/ounold/ALCS
Please feel free to contact me at: olgierd.unold@pwr.edu.pl
This project is licensed under the MIT License.