Skip to content
Snippets Groups Projects
Verified Commit 76eb8062 authored by Michiel Cottaar's avatar Michiel Cottaar
Browse files

Replace variables with numbers after optimisation

parent d77c0cbc
No related branches found
No related tags found
No related merge requests found
module BuildSequences
import JuMP: Model, optimizer_with_attributes, optimize!
import JuMP: Model, optimizer_with_attributes, optimize!, AbstractJuMPScalar, value
import Ipopt
import Juniper
import ..Scanners: Scanner
......@@ -44,7 +44,7 @@ function build_sequence(f::Function, scanner::Scanner, model::Model)
try
sequence = f(model)
optimize!(model)
return sequence
return fixed(sequence)
finally
GLOBAL_MODEL[] = prev_model
GLOBAL_SCANNER[] = prev_scanner
......@@ -74,4 +74,17 @@ function global_scanner()
end
"""
fixed(building_block)
Returns an equiavalent [`BuildingBlock`](@ref) with all free variables replaced by numbers.
This will only work after calling [`optimize!`](@ref)([`global_model`](@ref)()).
It is used internally by [`build_sequence`](@ref).
"""
fixed(some_value) = some_value
fixed(jump_variable::AbstractJuMPScalar) = value(jump_variable)
fixed(jump_variable::AbstractArray) = fixed.(jump_variable)
end
\ No newline at end of file
......@@ -2,7 +2,7 @@ module BuildingBlocks
import JuMP: value, Model, @constraint, @objective, objective_function, AbstractJuMPScalar
import Printf: @sprintf
import ..Variables: variables, start_time, duration, end_time, gradient_strength, slew_rate, effective_time, VariableType, qval_square
import ..BuildSequences: global_model, global_scanner
import ..BuildSequences: global_model, global_scanner, fixed
import ..Scanners: Scanner
"""
......@@ -10,7 +10,6 @@ Parent type for all individual components out of which a sequence can be built.
Required methods:
- [`duration`](@ref)(block, parameters): Return block duration in ms.
- [`fixed`](block): Return the equivalent fixed BuildingBlock (i.e., `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`). These all have in common that they have no free variables and explicitly set any gradient and RF pulse profiles.
- [`variables`](@ref): A list of all functions that are used to compute variables of the building block. Any of these can be used in constraints or objective functions.
"""
abstract type BuildingBlock end
......@@ -101,17 +100,6 @@ Function used internally to convert a wide variety of objects into [`BuildingBlo
to_block(bb::BuildingBlock) = bb
"""
fixed(block::BuildingBlock)
Return the fixed equivalent of the `BuildingBlock`
Possible return types are `FixedSequence`, `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`.
These all have in common that they have no free variables and explicitly set any gradient and RF pulse profiles.
"""
function fixed end
"""
variables(building_block)
......@@ -251,7 +239,7 @@ apply_simple_constraint!(variable, ::Nothing) = nothing
apply_simple_constraint!(variable, value::Symbol) = apply_simple_constraint!(variable, Val(value))
apply_simple_constraint!(variable, ::Val{:min}) = @objective global_model() Min objective_function(global_model()) + variable
apply_simple_constraint!(variable, ::Val{:max}) = @objective global_model() Min objective_function(global_model()) - variable
apply_simple_constraint!(variable, value::VariableType) = @constraint model variable == value
apply_simple_constraint!(variable, value::VariableType) = @constraint global_model() variable == value
apply_simple_constraint!(variable::AbstractVector, value::AbstractVector) = [apply_simple_constraint!(v1, v2) for (v1, v2) in zip(variable, value)]
......@@ -318,4 +306,13 @@ function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner, f
end
end
function fixed(bb::BuildingBlock)
arguments = []
for name in propertynames(bb)
push!(arguments, fixed(getproperty(bb, name)))
end
return typeof(bb)(arguments...)
end
end
\ No newline at end of file
......@@ -3,7 +3,7 @@ import StaticArrays: SVector
import ...Variables: VariableType, variables, get_free_variable
import ...BuildingBlocks: GradientBlock
import ...Variables: qvec, bmat_gradient, gradient_strength, slew_rate, duration, variables, VariableType
import ...BuildingBlocks: GradientBlock, fixed, RFPulseBlock
import ...BuildingBlocks: GradientBlock, RFPulseBlock
"""
ChangingGradientBlock(grad1, slew_rate, duration, rotate, scale)
......
......@@ -3,7 +3,7 @@ import StaticArrays: SVector
import ...Variables: VariableType, variables
import ...BuildingBlocks: GradientBlock
import ...Variables: qvec, bmat_gradient, gradient_strength, slew_rate, duration, variables, VariableType
import ...BuildingBlocks: GradientBlock, fixed, RFPulseBlock
import ...BuildingBlocks: GradientBlock, RFPulseBlock
import ..ChangingGradientBlocks: split_gradient
"""
......
......@@ -66,7 +66,7 @@ function SpoiltSliceSelect(pulse; orientation=[0, 0, 1], rotate=nothing, spoiler
@constraint model (qvec(res, nothing, 1)[dim] ./ res.orientation[dim]) >= 2π * 1e-3 / spoiler_scale
end
end
set_simple_constraints!(model, res, kwargs)
set_simple_constraints!(res, kwargs)
max_time = gradient_strength(global_scanner()) / res.slew_rate
@constraint model rise_time(res)[1] <= max_time
......
......@@ -7,7 +7,7 @@ import JuMP: @constraint, @variable, VariableRef, value
import StaticArrays: SVector
import LinearAlgebra: norm
import ...Variables: qvec, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_slice_thickness, inverse_bandwidth, effective_time
import ...BuildingBlocks: duration, set_simple_constraints!, fixed, RFPulseBlock, scanner_constraints!
import ...BuildingBlocks: duration, set_simple_constraints!, RFPulseBlock, scanner_constraints!
import ...BuildSequences: global_model
import ...Gradients: ChangingGradientBlock, ConstantGradientBlock
import ..Abstract: interruptions, waveform, AbstractOverlapping
......
module ConstantPulses
import JuMP: VariableRef, @constraint, @variable, value
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!
import ...Variables: variables, get_free_variable, flip_angle, phase, amplitude, frequency, start_time, end_time, VariableType, duration, effective_time, inverse_bandwidth
import ...BuildSequences: global_model
import ..FixedPulses: FixedPulse
"""
ConstantPulse(; variables...)
......
module InstantPulses
import JuMP: @constraint, @variable, VariableRef, value
import ...BuildingBlocks: RFPulseBlock, fixed
import ...BuildingBlocks: RFPulseBlock
import ...Variables: flip_angle, phase, start_time, variables, duration, get_free_variable, VariableType, effective_time, inverse_bandwidth
import ...BuildSequences: global_model
import ..FixedPulses: FixedInstantPulse
......
......@@ -3,7 +3,7 @@ module SincPulses
import JuMP: VariableRef, @constraint, @variable, value
import QuadGK: quadgk
import Polynomials: fit, Polynomial
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!
import ...Variables: flip_angle, phase, amplitude, frequency, VariableType, variables, get_free_variable, duration, effective_time, inverse_bandwidth
import ...BuildSequences: global_model
import ..FixedPulses: FixedPulse
......@@ -69,7 +69,7 @@ function SincPulse(;
if !symmetric
@constraint model res.N_right >= 1
end
set_simple_constraints!(model, res, kwargs)
set_simple_constraints!(res, kwargs)
return res
end
......
module InstantReadouts
import ...BuildingBlocks: BuildingBlock, to_block, fixed, effective_time
import ...BuildingBlocks: BuildingBlock, to_block, effective_time
import ...Variables: variables, duration
"""
......@@ -15,6 +15,5 @@ end
variables(::Type{<:InstantReadout}) = []
to_block(::Type{<:InstantReadout}) = InstantReadout()
duration(::InstantReadout) = 0.
fixed(i::InstantReadout) = i
effective_time(::InstantReadout) = 0.
end
\ No newline at end of file
......@@ -6,7 +6,7 @@ import Printf: @sprintf
import JuMP: @constraint
import ...BuildSequences: global_model
import ...Variables: variables, start_time, duration, VariableType, get_free_variable, TR, end_time
import ...BuildingBlocks: BuildingBlock, ContainerBlock, to_block, get_children_indices, fixed, BuildingBlockPrinter, _robust_value, get_children_blocks
import ...BuildingBlocks: BuildingBlock, ContainerBlock, to_block, get_children_indices, fixed, BuildingBlockPrinter, _robust_value, get_children_blocks, fixed
"""
Sequence(building_blocks...; TR=nothing)
......@@ -36,6 +36,7 @@ struct Sequence <: ContainerBlock
end
Sequence(blocks...; TR=nothing) = Sequence([blocks...]; TR=TR)
fixed(seq::Sequence) = fixed.(seq._blocks, TR=fixed(seq.TR))
Base.length(seq::Sequence) = length(seq._blocks)
Base.getindex(seq::Sequence, index) = seq._blocks[index]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment