Skip to main content

seachange

seachange runs generational evolutionary algorithms and keeps every individual in a SQLite database. You write each step of a generation (evaluate, select, mutate, retire) as a plain function that takes a population and returns one. The engine runs those functions in order once per generation and saves the result. Because every generation is on disk, you can stop a run, query it afterwards, or restart it from any generation.

It started as the evolution engine of ARIEL, a robot evolution framework, and holds the parts that have nothing to do with robots: the engine, random generators and mutators for integer and float genomes, crossover operators, and a RevDE optimizer.

Installation

seachange needs Python 3.13 or later. It is not on PyPI yet, so install it from a local clone:

git clone https://github.com/Jacopo-DM/seachange seachange
uv add ./seachange

Example

One-max: evolve 20-bit strings until every bit is 1. Each generation adds one mutated child per parent from the better half, scores the new individuals, and retires the worst so twenty stay alive.

from typing import cast

from seachange import (
    EA,
    EAOperation,
    Individual,
    IntegerMutator,
    IntegersGenerator,
    Population,
)

SIZE, LENGTH = 20, 20


def random_individual() -> Individual:
    individual = Individual()
    individual.genotype = IntegersGenerator.integers(
        low=0, high=1, size=LENGTH, endpoint=True
    )
    return individual


def evaluate(population: Population) -> Population:
    for individual in population.unevaluated:
        individual.fitness = sum(cast("list[int]", individual.genotype))
    return population


def reproduce(population: Population) -> Population:
    for parent in population.best(n=SIZE // 2):
        child = Individual()
        child.genotype = IntegerMutator.random_reset(
            cast("list[int]", parent.genotype),
            low=0,
            high=1,
            mutation_probability=1 / LENGTH,
        )
        population.append(child)
    return population


def retire_worst(population: Population) -> Population:
    for individual in population.sort()[SIZE:]:
        individual.alive = False
    return population


first = Population([random_individual() for _ in range(SIZE)])
ea = EA(
    evaluate(first),
    [EAOperation(reproduce), EAOperation(evaluate), EAOperation(retire_worst)],
    num_steps=50,
)
ea.run()
print(ea.get_solution("best").genotype)

It prints a progress bar and then the best bit string, all ones after 50 generations. The run is saved in __data__/database.db under the current folder; pass db_file_path= to EA to put it elsewhere. The same example, documented, is in examples/a1_one_max.py.

To continue a saved run, pass its database to EA.restart and give the new run its own file:

from pathlib import Path

ea = EA.restart(
    "__data__/database.db",
    operations,
    db_file_path=Path("__data__/continued.db"),
)

Without db_file_path, the new run would write to the default __data__/database.db, the file you are restarting from, so EA.restart raises ValueError instead of overwriting it. Pass generation= to continue from an earlier generation. The new file starts with the old run's history up to that generation, under the same ids and generation numbers, so it answers questions about the whole run on its own.

Genotypes

A genotype can be a list or dict of JSON values, or a numpy array, which comes back from the database as the same array, dtype and shape included, and is stored as raw bytes. Other types, such as PyTorch tensors, need a small codec registered with register_codec. docs/genotypes.md explains how genotypes are stored and typed, and examples/a3_numpy_genotypes.py evolves float32 weights.

License

GPL-3.0-or-later, the same as ARIEL, which seachange's code comes from. See LICENSE.

Documentation

Every public class and function has a NumPy-style docstring. The Sphinx sources are in docs/.

Metadata

Release files for seachange 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for seachange 0.1.0
File Size Uploaded Provenance
seachange-0.1.0.tar.gz 55.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for seachange 0.1.0
File Interpreter ABI Platform
seachange-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 117.4 kB

Release files / seachange-0.1.0.tar.gz

Download URL seachange-0.1.0.tar.gz
Size 55.4 kB
Tags Source
SHA-256 checksum
How to use checksums
39acbb3ef428c1ecc118738c7c9726466e88125de3737937018f055a61a875ae
BLAKE2b-256 checksum
How to use checksums
0c04670f9cd4709ed9c11e6f4f23d1ddcc0f1944dcf4ae778854e66e655d7924
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / seachange-0.1.0-py3-none-any.whl

Download URL seachange-0.1.0-py3-none-any.whl
Size 62.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5fd24414ec53fe4445bd1f34419789fbeecc1cdf4d69d182a238a411f6e05c5b
BLAKE2b-256 checksum
How to use checksums
6c57d549ac954bac5a15302ba85096bbd79459ba9c9cde7b65c18c3d27b29d8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for seachange 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page