Skip to content

Commit ddb24c5

Browse files
authored
Merge pull request #774 from mimiframework/delete
add `delete_unbound_comp_params` kwarg to `delete!`
2 parents 555b493 + b55d09f commit ddb24c5

File tree

6 files changed

+117
-14
lines changed

6 files changed

+117
-14
lines changed

docs/src/ref/ref_API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Model
77
add_comp!
88
connect_param!
99
create_marginal_model
10+
delete_param!
1011
dim_count
1112
dim_keys
1213
dim_key_dict

src/Mimi.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export
1919
# components,
2020
connect_param!,
2121
create_marginal_model,
22+
delete_param!,
2223
dim_count,
2324
dim_keys,
2425
dim_key_dict,

src/core/defs.jl

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,65 @@ find_first_period(comp_def::AbstractComponentDef) = @or(first_period(comp_def),
5858
find_last_period(comp_def::AbstractComponentDef) = @or(last_period(comp_def), last_period(get_root(comp_def)))
5959

6060
"""
61-
delete!(obj::AbstractCompositeComponentDef, component::Symbol)
61+
delete!(md::ModelDef, comp_name::Symbol; deep::Bool=false)
6262
63-
Delete a `component` by name from composite `ccd`.
63+
Delete a `component` by name from `md`.
64+
If `deep=true` then any external model parameters connected only to
65+
this component will also be deleted.
6466
"""
65-
function Base.delete!(ccd::AbstractCompositeComponentDef, comp_name::Symbol)
66-
if ! has_comp(ccd, comp_name)
67+
function Base.delete!(md::ModelDef, comp_name::Symbol; deep::Bool=false)
68+
if ! has_comp(md, comp_name)
6769
error("Cannot delete '$comp_name': component does not exist.")
6870
end
6971

70-
comp_def = compdef(ccd, comp_name)
71-
delete!(ccd.namespace, comp_name)
72+
comp_def = compdef(md, comp_name)
73+
delete!(md.namespace, comp_name)
7274

7375
# Remove references to the deleted comp
7476
comp_path = comp_def.comp_path
7577

76-
# TBD: find and delete external_params associated with deleted component? Currently no record of this.
77-
78+
# Remove internal parameter connections
7879
ipc_filter = x -> x.src_comp_path != comp_path && x.dst_comp_path != comp_path
79-
filter!(ipc_filter, ccd.internal_param_conns)
80+
filter!(ipc_filter, md.internal_param_conns)
81+
82+
# Remove external parameter connections
83+
84+
if deep # Find and delete external_params that were connected only to the deleted component if specified
85+
# Get all external parameters this component is connected to
86+
comp_ext_params = map(x -> x.external_param, filter(x -> x.comp_path == comp_path, md.external_param_conns))
87+
88+
# Identify which ones are not connected to any other components
89+
unbound_filter = x -> length(filter(epc -> epc.external_param == x, md.external_param_conns)) == 1
90+
unbound_comp_params = filter(unbound_filter, comp_ext_params)
91+
92+
# Delete these parameters (the delete_param! function also deletes the associated external_param_conns)
93+
[delete_param!(md, param_name) for param_name in unbound_comp_params]
94+
95+
else # only delete the external connections for this component but leave all external parameters
96+
epc_filter = x -> x.comp_path != comp_path
97+
filter!(epc_filter, md.external_param_conns)
98+
end
99+
dirty!(md)
100+
end
101+
102+
"""
103+
delete_param!(md::ModelDef, external_param_name::Symbol)
104+
105+
Delete `external_param_name` from `md`'s list of external parameters, and also
106+
remove all external parameters connections that were connected to `external_param_name`.
107+
"""
108+
function delete_param!(md::ModelDef, external_param_name::Symbol)
109+
if external_param_name in keys(md.external_params)
110+
delete!(md.external_params, external_param_name)
111+
else
112+
error("Cannot delete $external_param_name, not found in external parameter list.")
113+
end
114+
115+
# Remove external parameter connections
116+
epc_filter = x -> x.external_param != external_param_name
117+
filter!(epc_filter, md.external_param_conns)
80118

81-
epc_filter = x -> x.comp_path != comp_path
82-
filter!(epc_filter, ccd.external_param_conns)
119+
dirty!(md)
83120
end
84121

85122
@delegate Base.haskey(comp::AbstractComponentDef, key::Symbol) => namespace

src/core/model.jl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,21 @@ Add a scalar type parameter `name` with value `value` to the model `m`.
369369
@delegate set_external_scalar_param!(m::Model, name::Symbol, value::Any) => md
370370

371371
"""
372-
delete!(m::Model, component::Symbol
372+
delete!(m::Model, component::Symbol; deep::Bool=false)
373373
374-
Delete a `component`` by name from a model `m`'s ModelDef, and nullify the ModelInstance.
374+
Delete a `component` by name from a model `m`'s ModelDef, and nullify the ModelInstance.
375+
If `deep=true` then any external model parameters connected only to
376+
this component will also be deleted.
375377
"""
376-
@delegate Base.delete!(m::Model, comp_name::Symbol) => md
378+
@delegate Base.delete!(m::Model, comp_name::Symbol; deep::Bool=false) => md
379+
380+
"""
381+
delete_param!(m::Model, external_param_name::Symbol)
382+
383+
Delete `external_param_name` from a model `m`'s ModelDef's list of external parameters, and
384+
also remove all external parameters connections that were connected to `external_param_name`.
385+
"""
386+
@delegate delete_param!(m::Model, external_param_name::Symbol) => md
377387

378388
"""
379389
set_param!(m::Model, comp_name::Symbol, param_name::Symbol, value; dims=nothing)

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ Electron.prep_test_env()
4747
@info("test_model_structure_variabletimestep.jl")
4848
@time include("test_model_structure_variabletimestep.jl")
4949

50+
@info("test_delete.jl")
51+
@time include("test_delete.jl")
52+
5053
@info("test_replace_comp.jl")
5154
@time include("test_replace_comp.jl")
5255

test/test_delete.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
module TestDelete
2+
3+
# Test the behavior of the `delete!` function with and without the `deep` kwarg.
4+
5+
using Mimi
6+
using Test
7+
8+
@defcomp A begin
9+
p1 = Parameter()
10+
p2 = Parameter()
11+
end
12+
13+
function _get_model()
14+
m = Model()
15+
set_dimension!(m, :time, 1:2)
16+
add_comp!(m, A, :A1)
17+
add_comp!(m, A, :A2)
18+
set_param!(m, :p1, 1)
19+
set_param!(m, :A1, :p2, :p2_A1, 21)
20+
set_param!(m, :A2, :p2, :p2_A2, 22)
21+
return m
22+
end
23+
24+
# Test component deletion without removing unbound component parameters
25+
m1 = _get_model()
26+
run(m1)
27+
@test length(Mimi.components(m1)) == 2
28+
@test length(m1.md.external_param_conns) == 4 # two components with two connections each
29+
@test length(m1.md.external_params) == 3 # three total external params
30+
delete!(m1, :A1)
31+
run(m1) # run before and after to test that `delete!` properly "dirties" the model, and builds a new instance on the next run
32+
@test length(Mimi.components(m1)) == 1
33+
@test length(m1.md.external_param_conns) == 2 # Component A1 deleted, so only two connections left
34+
@test length(m1.md.external_params) == 3 # but all three external params remain
35+
@test :p2_A1 in keys(m1.md.external_params)
36+
37+
# Test component deletion that removes unbound component parameters
38+
m2 = _get_model()
39+
delete!(m2, :A1, deep = true)
40+
@test length(Mimi.components(m2.md)) == 1
41+
@test length(m2.md.external_params) == 2 # :p2_A1 has been removed
42+
@test !(:p2_A1 in keys(m2.md.external_params))
43+
44+
# Test the `delete_param! function on its own
45+
m3 = _get_model()
46+
run(m3)
47+
delete_param!(m3, :p1)
48+
@test_throws ErrorException run(m3) # will not be able to run because p1 in both components aren't connected to anything
49+
@test length(m3.md.external_params) == 2
50+
@test length(m3.md.external_param_conns) == 2 # The external param connections to p1 have also been removed
51+
end

0 commit comments

Comments
 (0)