Skip to content

Commit bfcf1f4

Browse files
committed
refactor: add missing parts of AbstractPopMember interface
1 parent 6d4d64f commit bfcf1f4

File tree

10 files changed

+286
-75
lines changed

10 files changed

+286
-75
lines changed

src/ExpressionBuilder.jl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ using DynamicExpressions:
1111
using ..CoreModule: AbstractOptions, Dataset
1212
using ..HallOfFameModule: HallOfFame
1313
using ..PopulationModule: Population
14-
using ..PopMemberModule: PopMember
14+
using ..PopMemberModule: PopMember, AbstractPopMember, create_child
15+
using ..ComplexityModule: compute_complexity
1516

1617
import DynamicExpressions: get_operators
1718
import ..CoreModule: create_expression
@@ -107,15 +108,16 @@ end
107108
return with_metadata(ex; init_params(options, dataset, ex, Val(true))...)
108109
end
109110
function embed_metadata(
110-
member::PopMember, options::AbstractOptions, dataset::Dataset{T,L}
111-
) where {T,L}
112-
return PopMember(
111+
member::PM, options::AbstractOptions, dataset::Dataset{T,L}
112+
) where {T,L,N,PM<:AbstractPopMember{T,L,N}}
113+
return create_child(
114+
member,
113115
embed_metadata(member.tree, options, dataset),
114116
member.cost,
115117
member.loss,
116-
nothing;
117-
member.ref,
118-
member.parent,
118+
options;
119+
complexity=compute_complexity(member, options),
120+
parent_ref=member.ref,
119121
deterministic=options.deterministic,
120122
)
121123
end
@@ -135,7 +137,7 @@ end
135137
end
136138
function embed_metadata(
137139
vec::Vector{H}, options::AbstractOptions, dataset::Dataset{T,L}
138-
) where {T,L,H<:Union{HallOfFame,Population,PopMember}}
140+
) where {T,L,H<:Union{HallOfFame,Population,AbstractPopMember}}
139141
return map(Fix{2}(Fix{3}(embed_metadata, dataset), options), vec)
140142
end
141143
end

src/HallOfFame.jl

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,36 @@ function HallOfFame(
7373
options::AbstractOptions, dataset::Dataset{T,L}
7474
) where {T<:DATA_TYPE,L<:LOSS_TYPE}
7575
base_tree = create_expression(init_value(T), options, dataset)
76+
PM = options.popmember_type
7677

77-
return HallOfFame{T,L,typeof(base_tree),PopMember{T,L,typeof(base_tree)}}(
78+
# Create a prototype member to get the concrete type
79+
prototype = PM(
80+
copy(base_tree),
81+
L(0),
82+
L(Inf),
83+
options,
84+
1; # complexity
85+
parent=-1,
86+
deterministic=options.deterministic,
87+
)
88+
89+
PMtype = typeof(prototype)
90+
91+
return HallOfFame{T,L,typeof(base_tree),PMtype}(
7892
[
79-
PopMember(
80-
copy(base_tree),
81-
L(0),
82-
L(Inf),
83-
options;
84-
parent=-1,
85-
deterministic=options.deterministic,
86-
) for i in 1:(options.maxsize)
93+
if i == 1
94+
prototype
95+
else
96+
PM(
97+
copy(base_tree),
98+
L(0),
99+
L(Inf),
100+
options,
101+
1; # complexity
102+
parent=-1,
103+
deterministic=options.deterministic,
104+
)
105+
end for i in 1:(options.maxsize)
87106
],
88107
[false for i in 1:(options.maxsize)],
89108
)

src/Mutate.jl

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ using ..MutationFunctionsModule:
4040
using ..ConstantOptimizationModule: optimize_constants
4141
using ..RecorderModule: @recorder
4242

43-
abstract type AbstractMutationResult{N<:AbstractExpression,P<:PopMember} end
43+
abstract type AbstractMutationResult{N<:AbstractExpression,P<:AbstractPopMember} end
4444

4545
"""
46-
MutationResult{N<:AbstractExpression,P<:PopMember}
46+
MutationResult{N<:AbstractExpression,P<:AbstractPopMember}
4747
4848
Represents the result of a mutation operation in the genetic programming algorithm. This struct is used to return values from `mutate!` functions.
4949
@@ -160,7 +160,7 @@ Use this to modify how `mutate_constant` changes for an expression type.
160160
function condition_mutate_constant!(
161161
::Type{<:AbstractExpression},
162162
weights::AbstractMutationWeights,
163-
member::PopMember,
163+
member::AbstractPopMember,
164164
options::AbstractOptions,
165165
curmaxsize::Int,
166166
)
@@ -352,7 +352,7 @@ end
352352

353353
@generated function _dispatch_mutations!(
354354
tree::AbstractExpression,
355-
member::PopMember,
355+
member::AbstractPopMember,
356356
mutation_choice::Symbol,
357357
weights::W,
358358
options::AbstractOptions;
@@ -381,7 +381,7 @@ end
381381
mutation_weights::AbstractMutationWeights,
382382
options::AbstractOptions;
383383
kws...,
384-
) where {N<:AbstractExpression,P<:PopMember,S}
384+
) where {N<:AbstractExpression,P<:AbstractPopMember,S}
385385
386386
Perform a mutation on the given `tree` and `member` using the specified mutation type `S`.
387387
Various `kws` are provided to access other data needed for some mutations.
@@ -409,7 +409,7 @@ so it can always return immediately.
409409
"""
410410
function mutate!(
411411
::N, ::P, ::Val{S}, ::AbstractMutationWeights, ::AbstractOptions; kws...
412-
) where {N<:AbstractExpression,P<:PopMember,S}
412+
) where {N<:AbstractExpression,P<:AbstractPopMember,S}
413413
return error("Unknown mutation choice: $S")
414414
end
415415

@@ -422,7 +422,7 @@ function mutate!(
422422
recorder::RecordType,
423423
temperature,
424424
kws...,
425-
) where {N<:AbstractExpression,P<:PopMember}
425+
) where {N<:AbstractExpression,P<:AbstractPopMember}
426426
tree = mutate_constant(tree, temperature, options)
427427
@recorder recorder["type"] = "mutate_constant"
428428
return MutationResult{N,P}(; tree=tree)
@@ -436,7 +436,7 @@ function mutate!(
436436
options::AbstractOptions;
437437
recorder::RecordType,
438438
kws...,
439-
) where {N<:AbstractExpression,P<:PopMember}
439+
) where {N<:AbstractExpression,P<:AbstractPopMember}
440440
tree = mutate_operator(tree, options)
441441
@recorder recorder["type"] = "mutate_operator"
442442
return MutationResult{N,P}(; tree=tree)
@@ -451,7 +451,7 @@ function mutate!(
451451
recorder::RecordType,
452452
nfeatures,
453453
kws...,
454-
) where {N<:AbstractExpression,P<:PopMember}
454+
) where {N<:AbstractExpression,P<:AbstractPopMember}
455455
tree = mutate_feature(tree, nfeatures)
456456
@recorder recorder["type"] = "mutate_feature"
457457
return MutationResult{N,P}(; tree=tree)
@@ -465,7 +465,7 @@ function mutate!(
465465
options::AbstractOptions;
466466
recorder::RecordType,
467467
kws...,
468-
) where {N<:AbstractExpression,P<:PopMember}
468+
) where {N<:AbstractExpression,P<:AbstractPopMember}
469469
tree = swap_operands(tree)
470470
@recorder recorder["type"] = "swap_operands"
471471
return MutationResult{N,P}(; tree=tree)
@@ -480,7 +480,7 @@ function mutate!(
480480
recorder::RecordType,
481481
nfeatures,
482482
kws...,
483-
) where {N<:AbstractExpression,P<:PopMember}
483+
) where {N<:AbstractExpression,P<:AbstractPopMember}
484484
if rand() < 0.5
485485
tree = append_random_op(tree, options, nfeatures)
486486
@recorder recorder["type"] = "add_node:append"
@@ -500,7 +500,7 @@ function mutate!(
500500
recorder::RecordType,
501501
nfeatures,
502502
kws...,
503-
) where {N<:AbstractExpression,P<:PopMember}
503+
) where {N<:AbstractExpression,P<:AbstractPopMember}
504504
tree = insert_random_op(tree, options, nfeatures)
505505
@recorder recorder["type"] = "insert_node"
506506
return MutationResult{N,P}(; tree=tree)
@@ -514,7 +514,7 @@ function mutate!(
514514
options::AbstractOptions;
515515
recorder::RecordType,
516516
kws...,
517-
) where {N<:AbstractExpression,P<:PopMember}
517+
) where {N<:AbstractExpression,P<:AbstractPopMember}
518518
tree = delete_random_op!(tree)
519519
@recorder recorder["type"] = "delete_node"
520520
return MutationResult{N,P}(; tree=tree)
@@ -528,7 +528,7 @@ function mutate!(
528528
options::AbstractOptions;
529529
recorder::RecordType,
530530
kws...,
531-
) where {N<:AbstractExpression,P<:PopMember}
531+
) where {N<:AbstractExpression,P<:AbstractPopMember}
532532
tree = form_random_connection!(tree)
533533
@recorder recorder["type"] = "form_connection"
534534
return MutationResult{N,P}(; tree=tree)
@@ -542,7 +542,7 @@ function mutate!(
542542
options::AbstractOptions;
543543
recorder::RecordType,
544544
kws...,
545-
) where {N<:AbstractExpression,P<:PopMember}
545+
) where {N<:AbstractExpression,P<:AbstractPopMember}
546546
tree = break_random_connection!(tree)
547547
@recorder recorder["type"] = "break_connection"
548548
return MutationResult{N,P}(; tree=tree)
@@ -556,7 +556,7 @@ function mutate!(
556556
options::AbstractOptions;
557557
recorder::RecordType,
558558
kws...,
559-
) where {N<:AbstractExpression,P<:PopMember}
559+
) where {N<:AbstractExpression,P<:AbstractPopMember}
560560
tree = randomly_rotate_tree!(tree)
561561
@recorder recorder["type"] = "rotate_tree"
562562
return MutationResult{N,P}(; tree=tree)
@@ -572,7 +572,7 @@ function mutate!(
572572
recorder::RecordType,
573573
parent_ref,
574574
kws...,
575-
) where {N<:AbstractExpression,P<:PopMember}
575+
) where {N<:AbstractExpression,P<:AbstractPopMember}
576576
@assert options.should_simplify
577577
simplify_tree!(tree, options.operators)
578578
tree = combine_operators(tree, options.operators)
@@ -593,7 +593,7 @@ function mutate!(
593593
curmaxsize,
594594
nfeatures,
595595
kws...,
596-
) where {T,N<:AbstractExpression{T},P<:PopMember}
596+
) where {T,N<:AbstractExpression{T},P<:AbstractPopMember}
597597
tree = randomize_tree(tree, curmaxsize, options, nfeatures)
598598
@recorder recorder["type"] = "randomize"
599599
return MutationResult{N,P}(; tree=tree)
@@ -608,7 +608,7 @@ function mutate!(
608608
recorder::RecordType,
609609
dataset::Dataset,
610610
kws...,
611-
) where {N<:AbstractExpression,P<:PopMember}
611+
) where {N<:AbstractExpression,P<:AbstractPopMember}
612612
cur_member, new_num_evals = optimize_constants(dataset, member, options)
613613
@recorder recorder["type"] = "optimize"
614614
return MutationResult{N,P}(;
@@ -625,7 +625,7 @@ function mutate!(
625625
recorder::RecordType,
626626
parent_ref,
627627
kws...,
628-
) where {N<:AbstractExpression,P<:PopMember}
628+
) where {N<:AbstractExpression,P<:AbstractPopMember}
629629
@recorder begin
630630
recorder["type"] = "identity"
631631
recorder["result"] = "accept"

src/ParametricExpression.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ using ..CoreModule:
2424
AbstractExpressionSpec,
2525
get_indices,
2626
ExpressionSpecModule as ES
27-
using ..PopMemberModule: PopMember
27+
using ..PopMemberModule: PopMember, AbstractPopMember
2828
using ..InterfaceDynamicExpressionsModule: InterfaceDynamicExpressionsModule as IDE
2929
using ..LossFunctionsModule: LossFunctionsModule as LF
3030
using ..ExpressionBuilderModule: ExpressionBuilderModule as EB
@@ -102,7 +102,7 @@ end
102102
function MM.condition_mutate_constant!(
103103
::Type{<:ParametricExpression},
104104
weights::AbstractMutationWeights,
105-
member::PopMember,
105+
member::AbstractPopMember,
106106
options::AbstractOptions,
107107
curmaxsize::Int,
108108
)

src/PopMember.jl

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -198,35 +198,25 @@ function recompute_complexity!(
198198
return complexity
199199
end
200200

201-
# Interface for creating child members with custom field preservation
202201
"""
203-
create_child(parent::P, tree, cost, loss, options;
204-
complexity::Union{Int,Nothing}=nothing, parent_ref, kwargs...) where P<:AbstractPopMember
205-
206-
Create a new PopMember derived from a parent (mutation case).
207-
Custom types should override to preserve their additional fields.
202+
create_child(parent::P, tree::AbstractExpression{T}, cost, loss, options;
203+
complexity::Union{Int,Nothing}=nothing, parent_ref, kwargs...) where {T,L,P<:PopMember{T,L}}
208204
209-
# Arguments
210-
- `parent`: The parent member being mutated
211-
- `tree`: The new expression tree
212-
- `cost`: The new cost
213-
- `loss`: The new loss
214-
- `options`: The options
215-
- `complexity`: The complexity (computed if not provided)
216-
- `parent_ref`: Reference to parent for tracking
205+
Create a new PopMember with a potentially different expression type.
206+
Used by embed_metadata where the expression gains metadata.
217207
"""
218208
function create_child(
219209
parent::P,
220-
tree::N,
210+
tree::AbstractExpression{T},
221211
cost::L,
222212
loss::L,
223213
options;
224214
complexity::Union{Int,Nothing}=nothing,
225215
parent_ref,
226216
kwargs...,
227-
) where {T,L,N<:AbstractExpression{T},P<:PopMember{T,L,N}}
217+
) where {T,L,P<:PopMember{T,L}}
228218
actual_complexity = @something complexity compute_complexity(tree, options)
229-
return constructorof(P)(
219+
return PopMember(
230220
tree,
231221
cost,
232222
loss,
@@ -246,16 +236,16 @@ Custom types should override to blend their additional fields.
246236
"""
247237
function create_child(
248238
parents::Tuple{P,P},
249-
tree::N,
239+
tree::AbstractExpression{T},
250240
cost::L,
251241
loss::L,
252242
options;
253243
complexity::Union{Int,Nothing}=nothing,
254244
parent_ref,
255245
kwargs...,
256-
) where {T,L,N<:AbstractExpression{T},P<:PopMember{T,L,N}}
246+
) where {T,L,P<:PopMember{T,L}}
257247
actual_complexity = @something complexity compute_complexity(tree, options)
258-
return constructorof(P)(
248+
return PopMember(
259249
tree,
260250
cost,
261251
loss,

0 commit comments

Comments
 (0)