Skip to content

Commit

Permalink
Merge pull request #917 from open-AIMS/factor-bounds-setting
Browse files Browse the repository at this point in the history
Updated factor bounds setting method
  • Loading branch information
Zapiano authored Feb 25, 2025
2 parents dcd9a23 + 24cc04e commit 3c2f7cb
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 25 deletions.
55 changes: 46 additions & 9 deletions src/io/sampling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,18 @@ function fix_factor!(d::Domain, factor::Symbol, val::Real)::Nothing
return nothing
end
function fix_factor!(d::Domain, factors::Vector{Symbol})::Nothing
for f in factors
fix_factor!(d, f)
end
params = DataFrame(d.model)
factor_rows = findall(in(factors), params.fieldname)

# Get current values and dist_params lengths
vals = params[factor_rows, :val]
dist_lens = length.(params[factor_rows, :dist_params])

# Create new dist_params tuples
new_params = [Tuple(fill(v, len)) for (v, len) in zip(vals, dist_lens)]
params[factor_rows, :dist_params] .= new_params

update!(d, params)
return nothing
end
function fix_factor!(d::Domain; factors...)::Nothing
Expand Down Expand Up @@ -480,8 +488,8 @@ function get_attr(dom::Domain, factor::Symbol, attr::Symbol)
end

"""
set_factor_bounds(dom::Domain, factor::Symbol, new_bounds::Tuple)::Nothing
set_factor_bounds(dom::Domain; factors...)::Nothing
set_factor_bounds!(dom::Domain, factor::Symbol, new_bounds::Tuple)::Nothing
set_factor_bounds!(dom::Domain; factors...)::Nothing
Set new bound values for a given parameter. Sampled values for a parameter will lie
within the range `lower_bound ≤ s ≤ upper_bound`, for every sample value `s`.
Expand All @@ -504,6 +512,13 @@ set_factor_bounds(dom, :wave_stress, (0.1, 0.2))
```
"""
function set_factor_bounds(dom::Domain, factor::Symbol, new_dist_params::Tuple)::Domain
Base.@warn "set_factor_bounds is deprecated, use set_factor_bounds! instead" maxlog =
1 _category = :deprecation

set_factor_bounds!(dom, factor, new_dist_params)
return dom
end
function set_factor_bounds!(dom::Domain, factor::Symbol, new_dist_params::Tuple)::Domain
old_val = get_attr(dom, factor, :val)
new_val = mean(new_dist_params[1:2])

Expand All @@ -514,14 +529,36 @@ function set_factor_bounds(dom::Domain, factor::Symbol, new_dist_params::Tuple):
ms[!, :is_constant] .= (ms[!, :lower_bound] .== ms[!, :upper_bound])

update!(dom, ms)

return dom
end

function set_factor_bounds(dom::Domain; factors...)::Domain
for (factor, bounds) in factors
dom = set_factor_bounds(dom, factor, bounds)
end
Base.@warn "set_factor_bounds is deprecated, use set_factor_bounds! instead" maxlog =
1 _category = :deprecation

set_factor_bounds!(dom; factors...)
return dom
end
function set_factor_bounds!(dom::Domain; factors...)::Domain
ms = model_spec(dom)
factor_symbols = collect(keys(factors))
factor_rows = findall(in(factor_symbols), ms.fieldname)

# Update dist_params and values in bulk
new_params = collect(values(factors))
ms[factor_rows, :dist_params] .= new_params

# Calculate new values preserving types
old_vals = ms[factor_rows, :val]
new_vals = mean.(zip(first.(new_params), last.(new_params)))
ms[factor_rows, :val] .= [
v isa Int ? round(n) : n for (v, n) in zip(old_vals, new_vals)
]

# Update `is_constant` column
ms[!, :is_constant] .= (ms[!, :lower_bound] .== ms[!, :upper_bound])

update!(dom, ms)
return dom
end

Expand Down
32 changes: 16 additions & 16 deletions test/sampling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ end
end

@testset "Set new sampling bounds" begin
set_factor_bounds = ADRIA.set_factor_bounds
set_factor_bounds! = ADRIA.set_factor_bounds!

dom = ADRIA.load_domain(TEST_DOMAIN_PATH)
num_samples = 32
Expand All @@ -223,10 +223,10 @@ end
factors = ms[factor_mask, :]
factor_fieldnames = (factors.fieldname...,)

@testset "set_factor_bounds" begin
@testset "set_factor_bounds!" begin
bounds_ranges = [range(b[1], b[2], 5) for b in factors.default_dist_params]
new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2)))
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
scens = ADRIA.sample_guided(dom, num_samples)

_test_bounds(scens, factor_mask, bounds_ranges)
Expand All @@ -235,7 +235,7 @@ end
@testset "set to default bounds" begin
new_bounds =
ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params])
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)

factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1]
@test all(factor_params.dist_params .== factor_params.default_dist_params)
Expand All @@ -250,10 +250,10 @@ end
factors = ms[factor_mask, :]
factor_fieldnames = (factors.fieldname...,)

@testset "set_factor_bounds" begin
@testset "set_factor_bounds!" begin
bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params]
new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2)))
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
scens = ADRIA.sample_guided(dom, num_samples)

_test_bounds(scens, factor_mask, bounds_ranges)
Expand All @@ -262,7 +262,7 @@ end
@testset "get_default_dist_params" begin
new_bounds =
ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params])
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)

factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1]
@test all(factor_params.dist_params .== factor_params.default_dist_params)
Expand All @@ -279,12 +279,12 @@ end
ms.dist .== ADRIA.DiscreteOrderedUniformDist
factors = ms[factor_mask, :]
factor_fieldnames = (factors.fieldname...,)
@testset "set_factor_bounds" begin
@testset "set_factor_bounds!" begin
bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params]
new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2)))
new_steps = [ceil((nb[2] - nb[1]) / 10) for nb in new_bounds]
new_dist_params = [(b[1], b[2], s) for (b, s) in zip(new_bounds, new_steps)]
dom = set_factor_bounds(
dom = set_factor_bounds!(
dom; NamedTuple{factor_fieldnames}(new_dist_params)...
)
scens = ADRIA.sample_guided(dom, num_samples)
Expand All @@ -295,7 +295,7 @@ end
@testset "get_default_dist_params" begin
new_bounds =
ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params])
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)

factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1]
@test all(factor_params.dist_params .== factor_params.default_dist_params)
Expand All @@ -309,13 +309,13 @@ end
factor_mask = ms.component .∈ [test_components] .&& ms.dist .== TriangularDist
factors = ms[factor_mask, :]
factor_fieldnames = (factors.fieldname...,)
@testset "set_factor_bounds" begin
@testset "set_factor_bounds!" begin
bounds_ranges = [range(b[1], b[2], 5) for b in factors.default_dist_params]
new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2)))
mode_ranges = [range(nb[1], nb[2], 5) for nb in new_bounds]
new_modes = (rand.(mode_ranges))
new_dist_params = [(b[1], b[2], p) for (b, p) in zip(new_bounds, new_modes)]
dom = set_factor_bounds(
dom = set_factor_bounds!(
dom; NamedTuple{factor_fieldnames}(new_dist_params)...
)
scens = ADRIA.sample_guided(dom, num_samples)
Expand All @@ -326,7 +326,7 @@ end
@testset "get_default_dist_params" begin
new_bounds =
ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params])
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)

factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1]
@test all(factor_params.dist_params .== factor_params.default_dist_params)
Expand All @@ -342,13 +342,13 @@ end
ms.dist .== ADRIA.DiscreteTriangularDist
factors = ms[factor_mask, :]
factor_fieldnames = (factors.fieldname...,)
@testset "set_factor_bounds" begin
@testset "set_factor_bounds!" begin
bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params]
new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2)))
new_mode_ranges = [nb[1]:nb[2] for nb in new_bounds]
new_peaks = (rand.(new_mode_ranges))
new_dist_params = [(b[1], b[2], p) for (b, p) in zip(new_bounds, new_peaks)]
dom = set_factor_bounds(
dom = set_factor_bounds!(
dom; NamedTuple{factor_fieldnames}(new_dist_params)...
)
scens = ADRIA.sample_guided(dom, num_samples)
Expand All @@ -359,7 +359,7 @@ end
@testset "get_default_dist_params" begin
new_bounds =
ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params])
dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...)
dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...)

factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1]
@test all(factor_params.dist_params .== factor_params.default_dist_params)
Expand Down

0 comments on commit 3c2f7cb

Please sign in to comment.