Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/operation/problem_template.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,29 @@ function finalize_template!(template::AbstractProblemTemplate, args...)
)
end

"""
share_template_references!(template_::AbstractProblemTemplate, template::AbstractProblemTemplate)

Extension point for template types whose build-time copy must share some objects with
the caller's `template` by reference instead of by `deepcopy` — for instance objects a
build mutates that callers then inspect on the instance they passed in. The model
constructors call it on the fresh copy `template_`; the default shares nothing.
"""
function share_template_references!(::AbstractProblemTemplate, ::AbstractProblemTemplate)
return
end

function _deepcopy_template(template::AbstractProblemTemplate)
template_ = _deepcopy_sharing_network_data(template)
share_template_references!(template_, template)
return template_
end

# Deep-copy a template while sharing the network source and derived data by reference:
# both can hold PNM matrices whose solver caches carry raw factorization handles and
# deliberately error on deepcopy (PNM #312). Sharing is safe because instantiation
# replaces the copy's `network_data` outright rather than mutating the original's.
function _deepcopy_template(template::AbstractProblemTemplate)
function _deepcopy_sharing_network_data(template::AbstractProblemTemplate)
network_model = get_network_model(template)
network_model === nothing && return deepcopy(template)
source = network_model.network_source
Expand Down
1 change: 1 addition & 0 deletions test/InfrastructureOptimizationModelsTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ function run_tests()
# TODO outputs_by_time.jl
# TODO service_model.jl
include(joinpath(TEST_DIR, "test_settings.jl"))
include(joinpath(TEST_DIR, "test_problem_template.jl"))
# standard_variables_expressions.jl: low complexity
# time_series_parameter_types.jl: low complexity

Expand Down
43 changes: 43 additions & 0 deletions test/test_problem_template.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Unit tests for the template deep-copy path and its `share_template_references!` hook.
"""

using Test
using InfrastructureOptimizationModels

# Minimal templates: one shares a field through the hook, one relies on the default.
mutable struct SharingTestTemplate <: IOM.AbstractProblemTemplate
shared::Vector{Int}
cloned::Vector{Int}
end
IOM.get_network_model(::SharingTestTemplate) = nothing
function IOM.share_template_references!(
template_::SharingTestTemplate,
template::SharingTestTemplate,
)
template_.shared = template.shared
return
end

mutable struct DefaultCopyTestTemplate <: IOM.AbstractProblemTemplate
data::Vector{Int}
end
IOM.get_network_model(::DefaultCopyTestTemplate) = nothing

@testset "Template deep copy" begin
@testset "share_template_references! runs on the copy" begin
template = SharingTestTemplate([1], [2])
template_ = IOM._deepcopy_template(template)
@test template_ !== template
@test template_.shared === template.shared
@test template_.cloned == template.cloned
@test template_.cloned !== template.cloned
end

@testset "default hook shares nothing" begin
template = DefaultCopyTestTemplate([1])
template_ = IOM._deepcopy_template(template)
@test template_.data == template.data
@test template_.data !== template.data
end
end
Loading