Jevo._WeightCacheType
_WeightCache::LRU{Int, <:Array{Float32}}

Stores developed tensors of weights for genes. Keys are tensor dimensions and the last gene id used. For a weight of dimensions (a, b) containing gene ids 1, 2, 3, _WeightCache[3, (a,b)] would map to a tensor equivalent to tensor(gene_1) + tensor(gene_2) + tensor(gene_3).

source
Jevo.AllVsAllMatchMakerType
AllVsAllMatchMaker(ids::Vector{String}=String[];kwargs...)

Creates an Operator that creates all vs all matches between individuals in populations with ids in ids.

source
Jevo.AssertorMethod
Assertor(;kwargs...)

Creates an Operator that asserts some condition. You probably want to override the retriever operator fields.

source
Jevo.CloneUniformReproducerType
CloneUniformReproducer(pop_size::Int, ids::Vector{String}=String[]; kwargs...)

Creates an Operator that choose individuals uniformly at random and clones them, creating children with identical DNA, until the population reaches pop_size individuals.

Should be used after a selector.

See also: TruncationSelector

source
Jevo.CompositePopulationType
CompositePopulation(id::String, populations::Vector{<:AbstractPopulation})

A population composed of subpopulations. Can be used to hierarchically organize populations.

source
Jevo.CompositeWeightType
struct CompositeWeight{T<:AbstractWeights} <: AbstractWeights
    dims::Tuple{Vararg{Int}}
    weights::Vector{T}
end

A collection of weights which are added together. Each element must develop to the same size

source
Jevo.CounterType
Counter(type::Type)

Holds an integer to increase by 1 with inc!(counter::Counter). Used for tracking gene ids, generations, individual ids, etc. Counters have a default value of 1.

source
Jevo.CreatorType
struct Creator{T} <: AbstractCreator where T
    type::Type{T}
    kwargs::Union{NamedTuple,Tuple}
end

A creator is a struct that contains a type to create and the arguments to pass to the constructor. If arguments contain other creators, those are recursively created first, unless enclosed in a PassThrough. We use a creator to allow for creating multiple objects which may include random initialization with a single creator.

See also: PassThrough, create

source
Jevo.DeltaType
Delta{G} <: AbstractGenotype where {G <: AbstractGenotype}

A delta is a change in a genotype. It can be applied to a genotype to create a new genotype, with the differences applied.

source
Jevo.FactorWeightType
struct FactorWeight{F1<:AbstractWeights, F2<:AbstractWeights} <: AbstractWeights
    dims::Tuple{Vararg{Int}}
    A::F1
    B::F2
end

Low-rank factorization of a weight matrix

source
Jevo.IndividualType
mutable struct Individual{G,D,I} <: AbstractIndividual where 
    {G <: AbstractGenotype,
     D <: AbstractCreator,
     I <: AbstractInteraction}
    id::Int
    generation::Int
    parents::Vector{Int}
    genotype::G
    developer::D
    records::Vector{AbstractRecord}
    interactions::Vector{I}
    data::Vector
end

An individual is a single entity in the population. Each individual should have a unique id generated from an AbstractIndividual Counter. An individual's developer is a creator that turns a genotype into a phenotype.

source
Jevo.IndividualMethod
Individual(counters::Vector{<:AbstractCounter},
           genotype_creator::Creator,
           developer::AbstractCreator)

Create new individual with no parents

source
Jevo.InitializePhylogenyType
InitializePhylogeny(ids::Vector{String}=String[];kwargs...)

Initializes a phylogenetic tree for populations with ids in ids. The tree is initialized with the current generation's individuals as the genesis individuals. The tree is initialized only once, and will throw an error if called multiple times on the same population.

See also LogPhylogeny, UpdatePhylogeny, PurgePhylogeny

source
Jevo.LogPhylogenyType
LogPhylogeny(ids::Vector{String}=String[]; kwargs...)

Adds recent individuals to a phylogeny file called $(pop.id)-phylo.csv in the current directory. The file is formatted as a CSV with columns id and ancestor_list, according to the ALIFE Data Standard

source
Jevo.MatchType
struct Match{I,E} <: AbstractMatch where {I <: AbstractIndividual, E <: AbstractEnvironment}
    id::Int
    individuals::Vector{I}
    environment_creator::Creator{E}
end
source
Jevo.MaxMRsType

Consists of a genotype with at most one gene per weight. Each gene has the largest MR in the genepool for that weight. The ids, seeds, and inits are irrelevant for these.

source
Jevo.MutatorType
Mutator(ids::Vector{String}=String[]; time::Bool=false, condition=always, kwargs...)

Operator that mutates the genotypes of individuals in populations with ids in ids. Calls mutate! on each individual in each population.

source
Jevo.NetworkGeneType
struct NetworkGene <: AbstractMutation
    id::Int
    seed::UInt64
    mr::Float32
    init!::Union{AbstractInitializer,Function}
end

Gene for a Weights object, used to generate a tensor of Float32. A StableRNG object is created with seed seed, which is then passed into init! to generate the tensor. The tensor is then mutated by mutation rate mr. id is a unique identifier for the gene.

source
Jevo.OperatorType
Operator <: AbstractOperator

All operator structs should be defined with the @define_op macro, and all operators should be created with the create_op function. Each operator should have the following fields:

condition::Function
retriever::Union{Function, AbstractRetriever}
operator::Function
updater::Union{Function, AbstractUpdater}
data::Vector{<:AbstractData}
time::Bool

condition is a function that takes the state and returns a boolean. If condition(state) == false, the operator will not be executed. Ex: always, first_gen

retriever is a function/object that takes the state and the operator and returns an object or list of objects to operate on. Should not update state. Ex: get_individuals, PopulationRetriever

operator is a function that takes the state and the retrieved object(s) and returns the modified object(s). Should perform none or trivial state updates, like incrementing a counter. Ex: Jevo.make_all_v_all_matches

updater is a function/object that takes the state and the modified object(s) and updates the state. Ex: ReccordAdder!, ComputeInteractions!

data is a vector of data objects that can be stored in the operator. Currently unused.

time is a boolean that determines if the time taken to execute the operator should be logged. Defaults to false

source
Jevo.PassThroughType
struct PassThrough <: AbstractCreator
    creator::AbstractCreator
end

A PassThrough is a struct that contains a creator to create. When the first create call is made, say on a population, the passthrough creator will return the creator, instead of actually performing the creation. This allows us to pass through genotype creators and developers to instantiated populations without creating them.

source
Jevo.PerformerType
        Performer <: AbstractOperator

Runs all matches in state.matches, and adds interactions to the individuals in the matches. This operator is intended to be used after a MatchMaker has created matches.

source
Jevo.PopSizeAssertorType
PopSizeAssertor(size::Int, pop_ids::Vector{String}=String[];kwargs...)

Asserts each population with an id in pop_ids has size individuals.

source
Jevo.PopulationType
Population(id::String, individuals::Vector{<:AbstractIndividual})

Create a population with a given id and individuals.

Population(id::String, individuals::Vector{<:AbstractIndividual}) =

Create pop with predefined inds and no data

source
Jevo.PopulationRetrieverType

Retrieves Vector{Vector{AbstractIndividual}} from state

For example, a two-pop all vs all matchmaker with the following population hierarchy:

ecosystem
├── composite1
│   ├── pop1a: ind1a1, ind1a2
│   └── pop1b: ind1b1, ind1b2
└── composite2
    ├── pop2a: ind2a1, ind2a2
    └── pop2b: ind2b1, ind2b2

ids = ["ecosystem"] or [] will fetch: [inds1a1, ind1a2, ind1b1, ind1b2, ind2a1, ind2a2, ind2b1, ind2b2]]

ids = ["composite1"] will fetch: [ind1a1, ind1a2, ind1b1, ind1b2]]

ids = ["pop1a"] will fetch: [[ind1a1, ind1a2]]

source
Jevo.PopulationRetrieverMethod

Traverses the population tree and returns references to all vectors of individuals to an arbitrary depth. If ids is not empty, it only returns individuals from the specified populations

source
Jevo.RandomEvaluatorType
RandomEvaluator(ids::Vector{String}=String[]; kwargs...)

Operator that record with a random fitness score to each individual in populations with ids in ids. Typically used for testing.

source
Jevo.ReccordAdder!Type
ReccordAdder!(;ids=String[])

Creates an Updater that adds records to individuals in populations with ids in ids.

function(adder::ReccordAdder!)(state::AbstractState, records::Vector{<:Vector{<:Vector{<:AbstractRecord}}})
source
Jevo.ReporterType
Reporter(;kwargs...)

Reporter(type::Type{<:AbstractMetric}; h5=true, txt=true, console=false, kwargs...)

Operator that "reports" some aspect of the state to either the console, a text file, or an hdf5 file. Allows us to log or record data anywhere in the pipeline.

source
Jevo.ScalarFitnessEvaluatorType
ScalarFitnessEvaluator(ids::Vector{String}=String[]; kwargs...)

Operator that computes the scalar fitness of each individual in populations with ids in ids. Requires all individuals to have at least one interaction.

The scalar fitness is the mean of the scores of each interaction, shifted by the minimum score.

source
Jevo.StateType
mutable struct State <: AbstractState
    id::String
    rng::AbstractRNG
    creators::Vector{AbstractCreator}
    operators::Vector{AbstractOperator}
    populations::Vector{AbstractPopulation}
    counters::Vector{AbstractCounter}
    matches::Vector{AbstractMatch}
    data::Vector    # for extensions
end

A mutable struct which holds all runtime data for an evolutionary simulation. See [`State(rng::AbstractRNG, creators::Vector{<:AbstractCreator}, operators::Vector{<:AbstractOperator})`](@ref) . each generation.

Example

using Jevo, StableRNGs
rng = StableRNG(1)

k = 1
n_dims = 2
n_inds = 2
n_species = 2
n_gens = 10

counters = default_counters()
ng_genotype_creator = Creator(VectorGenotype, (n=n_dims,rng=rng))
ng_developer = Creator(VectorPhenotype)

comp_pop_creator = Creator(CompositePopulation, ("species", [("p$i", n_inds, ng_genotype_creator, ng_developer) for i in 1:n_species], counters))
env_creator = Creator(CompareOnOne)

state = State("ng_phylogeny", rng,[comp_pop_creator, env_creator],
    [InitializeAllPopulations(),
    AllVsAllMatchMaker(),
    Performer(),
    ScalarFitnessEvaluator(),
    TruncationSelector(k),
    CloneUniformReproducer(n_inds),
    Mutator(),
    ClearInteractionsAndRecords(),
    Reporter(GenotypeSum, console=true)], counters=counters)

run!(state, n_gens)
source
Jevo.StateMethod
State(
    id::String,
    rng::AbstractRNG,
    creators::Vector{<:AbstractCreator},
    operators::Vector{<:AbstractOperator};
    counters::Vector{<:AbstractCounter}=default_counters(),
    populations::Vector{<:AbstractPopulation}=AbstractPopulation[],
    matches::Vector{<:AbstractMatch}=AbstractMatch[],
    data::Vector=[],
)

States are created from a random number generator, a list of creators, and a list of operators, and usually a list of counters.

creators should have at least on population creator and one environment creator. operators should contain an operator for each step of the evolutionary process. counters should contain a generation counter, individual id counter, gene counter, and match counter. All creators/operators should refer to the counter objects in state.

Use generation(state) to get the current generation number, initialized to one. The GenerationIncrementer operator is automatically appended to the operator list to advance the state to the next generation. Individuals created without any parents are of generation 0.

source
Jevo.TruncationSelectorType
TruncationSelector <: AbstractSelector

Selects the top k individuals from a population based on their fitness scores, purging the rest. The individuals are sorted by their fitness scores in descending order, and the top k individuals are selected. If there are fewer than k individuals in the population, raises an error.

source
Jevo.UpdateDeltaCacheType
UpdateDeltaCache(ids::Vector{String}=String[];kwargs...)

Updates the DeltaCache for a population with the current generation's individuals.

source
Jevo.UpdateGenePoolType
UpdateGenePool(ids::Vector{String}=String[]; after_gen::Int, n_latest::Int, time::Bool=false, kwargs...)

After generation after_gen, updates the gene pool for populations with ids in ids with the n_latest most recent deltas.

source
Jevo.UpdatePhylogenyType
UpdatePhylogeny(ids::Vector{String}=String[];kwargs...)

Updates the phylogenetic tree for populations with ids in ids. The tree is updated with the current generation's individuals as children of their parents. If an individual has no parent or more than one parent, an error is thrown.

See also LogPhylogeny, InitializePhylogeny, PurgePhylogeny

source
Jevo.WeightsType
struct Weights <: AbstractWeights
    dims::Tuple{Vararg{Int}}
    muts::Vector{NetworkGene}
end

A collection of genes which generate a tensor of Float32 when developed. Each gene in muts is developed into a tensor and added together to form the final tensor. A _WeightCache can be used to cache intermediate tensors to avoid redundant computation.

source
Jevo.WeightsCollectionType
struct WeightsCollection{T<:AbstractWeights} <: AbstractWeights
    dims::Tuple{Vararg{Int}}
    weights::Array{T}
end

Concatenation of multiple weight blocks into a single weight tensor, to adjust subsets of weights independently

source
Base.map!Method
map!(f::Function, x::AbstractLayer)

Apply a function to all weights in a neural network.

source
Base.showMethod

Override Base.show to avoid printing empty containers

source
Jevo.add_matches!Method
add_matches!(state::AbstractState, matches::Vector{Match})

Updater which adds matches to the state.

source
Jevo.cloneMethod
clone(state::AbstractState, parent::AbstractIndividual)

Create a child with the same genotype as the parent, but with the id, generation, and parent changed.

source
Jevo.createMethod
create(x)

Calls create on all elements of x that are creators, and returns x otherwise. This recursively instantiates all creators. If a creator is enclosed in a PassThrough, the PassThrough wrapper is removed, and the creator is kept as is.

create(::AbstractState, x): Calls create(x), can be used in an Operator. create(c::AbstractCreator): Calls the creator function c. create(args::Tuple): Recursively creates elements of the tuple. create(kwargs::NamedTuple): Recursively creates values of the named tuple. create(cs::Vector{<:AbstractCreator}): Calls create for each element in the vector of creators. create(x): Returns x if x is not a creator and does not contain a creator

All calls to create eventually lead, someway or another, to a call to the following constructor

(creator::Creator{T})() where T = T(create(creator.kwargs)...)

which creates the object of type T with the arguments in creator.kwargs.

See also: Creator, PassThrough

source
Jevo.create_opMethod
create_op(
    type::Union{Type{<:AbstractOperator}, String};
    condition=always,
    retriever=noop,
    operator=noop,
    updater=noop,
    data=AbstractData[],
    time=false,
    additional_fields...
)

Create an Operator of type type with the specified fields. All fields are optional. The retriever, operator, and updater fields default to noop.

source
Jevo.findMethod
find(attr::Symbol, match::Any, v::Vector)

Find the first element in v where el.attr == match. Used for finding counters of a specific type.

source
Jevo.first_genMethod
first_gen(state::AbstractState)

Return true if the current generation is 1.

source
Jevo.generationMethod
generation(state::AbstractState)

Return the current generation number of the state stored in the AbstractGeneration counter.

source
Jevo.get_counterMethod
get_counter(type::Type, state::AbstractState)

Returns the counter of the given type in the state.

source
Jevo.getonlyMethod
getonly(f, itr::Union{Vector, Tuple})

Returns the only element in itr that satisfies the predicate f. If there are no elements or more than one element, an error is thrown.

source
Jevo.inc!Method
inc!(counter::Counter, n::Int=1)

Increment the value of the given counter by n in a thread-safe manner. Returns the value of before the increment.

source
Jevo.make_all_v_all_matchesMethod
make_all_v_all_matches(state::AbstractState, pops::Vector{Vector{Population}})

Returns a vector of Matches between all pairs of individuals in the populations.

source
Jevo.mutate!Method
mutate!(rng::AbstractRNG, state::AbstractState, population::AbstractPopulation, genotype::AbstractGenotype; kwargs...)
source
Jevo.noopMethod
noop([x...])

Returns the arguments passed

noop(::AbstractState, x)

Returns x. Used to perform no operation for retrievers, operators, and updaters.

source
Jevo.run!Method
run!(state::State, max_generations::Int)

Begin/continue evolution until generation max_generations

source
Jevo.skipMethod
skip iterating over certain hierarchical configurations. We currently use this to

avoid iterating over the embedding weights for both the Embed and EmbedDecoder layers.

source
Jevo.@define_opMacro
@define_op name [supertype=AbstractOperator, additional_fields=""]

Defines a a subtype of supertype called name with the following fields:

  • condition
  • retriever
  • operator
  • updater
  • data
  • time

See Operator for more information.

Example

@define_op "AllVsAllMatchMaker" "AbstractMatchMaker"
source