Add Optimization interface, add greedy optimizer, add some functionality to CDCost
This commit is contained in:
parent
c73053f991
commit
1e0e699e6d
@ -141,6 +141,9 @@ include("task/properties.jl")
|
||||
include("estimator/interface.jl")
|
||||
include("estimator/global_metric.jl")
|
||||
|
||||
include("optimization/interface.jl")
|
||||
include("optimization/greedy.jl")
|
||||
|
||||
include("models/interface.jl")
|
||||
include("models/print.jl")
|
||||
|
||||
|
@ -29,13 +29,21 @@ function -(cost1::CDCost, cost2::CDCost)::CDCost
|
||||
return (data = d, computeEffort = ce, computeIntensity = ce / d)::CDCost
|
||||
end
|
||||
|
||||
function isless(cost1::CDCost, cost2::CDCost)::Bool
|
||||
return cost1.data + cost1.computeEffort < cost2.data + cost2.computeEffort
|
||||
end
|
||||
|
||||
function zero(type::Type{CDCost})
|
||||
return (data = 0.0, computeEffort = 00.0, computeIntensity = 0.0)::CDCost
|
||||
end
|
||||
|
||||
function typemax(type::Type{CDCost})
|
||||
return (data = Inf, computeEffort = Inf, computeIntensity = 0.0)::CDCost
|
||||
end
|
||||
|
||||
struct GlobalMetricEstimator <: AbstractEstimator end
|
||||
|
||||
function cost_type(estimator::GlobalMetricEstimator)
|
||||
function cost_type(estimator::GlobalMetricEstimator)::Type{CDCost}
|
||||
return CDCost
|
||||
end
|
||||
|
||||
|
@ -2,7 +2,10 @@ import Base.iterate
|
||||
|
||||
const _POSSIBLE_OPERATIONS_FIELDS = fieldnames(PossibleOperations)
|
||||
|
||||
function iterate(possibleOperations::PossibleOperations)
|
||||
_POIteratorStateType =
|
||||
NamedTuple{(:result, :state), Tuple{Union{NodeFusion, NodeReduction, NodeSplit}, Tuple{Symbol, Int64}}}
|
||||
|
||||
@inline function iterate(possibleOperations::PossibleOperations)::Union{Nothing, _POIteratorStateType}
|
||||
for fieldname in _POSSIBLE_OPERATIONS_FIELDS
|
||||
iterator = iterate(getfield(possibleOperations, fieldname))
|
||||
if (!isnothing(iterator))
|
||||
@ -13,7 +16,7 @@ function iterate(possibleOperations::PossibleOperations)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function iterate(possibleOperations::PossibleOperations, state)
|
||||
@inline function iterate(possibleOperations::PossibleOperations, state)::Union{Nothing, _POIteratorStateType}
|
||||
newStateSym = state[1]
|
||||
newStateIt = iterate(getfield(possibleOperations, newStateSym), state[2])
|
||||
if !isnothing(newStateIt)
|
||||
|
@ -3,6 +3,30 @@
|
||||
|
||||
An implementation of the greedy optimization algorithm, simply choosing the best next option evaluated with the given estimator.
|
||||
"""
|
||||
struct GreedyOptimizer
|
||||
estimator::AbstractEstimator
|
||||
struct GreedyOptimizer{EstimatorType <: AbstractEstimator} <: AbstractOptimizer
|
||||
estimator::EstimatorType
|
||||
end
|
||||
|
||||
function optimize_step!(optimizer::GreedyOptimizer, graph::DAG)
|
||||
# generate all options
|
||||
operations = get_operations(graph)
|
||||
if isempty(operations)
|
||||
println("[warn] No operations left to apply")
|
||||
return nothing
|
||||
end
|
||||
|
||||
lowestCost = typemax(cost_type(optimizer.estimator))
|
||||
|
||||
result = reduce((acc, op) -> begin
|
||||
op_cost = operation_effect(optimizer.estimator, graph, op)
|
||||
if op_cost < lowestCost
|
||||
lowestCost = op_cost
|
||||
return op
|
||||
end
|
||||
return acc
|
||||
end, operations)
|
||||
|
||||
push_operation!(graph, result)
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
30
src/optimization/interface.jl
Normal file
30
src/optimization/interface.jl
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
"""
|
||||
AbstractOptimizer
|
||||
|
||||
Abstract base type for optimizer implementations.
|
||||
"""
|
||||
abstract type AbstractOptimizer end
|
||||
|
||||
"""
|
||||
optimize_step!(optimizer::AbstractOptimizer, graph::DAG)
|
||||
|
||||
Interface function that must be implemented by implementations of [`AbstractOptimizer`](@ref). Returns `nothing`.
|
||||
|
||||
It should do one smallest logical step on the given [`DAG`](@ref), muting the graph and, if necessary, the optimizer's state.
|
||||
"""
|
||||
function optimize_step! end
|
||||
|
||||
"""
|
||||
optimize!(optimizer::AbstractOptimizer, graph::DAG, n::Int)
|
||||
|
||||
Function calling the given optimizer `n` times, muting the graph. Returns `nothing`.
|
||||
|
||||
If a more efficient method exists, this can be overloaded for a specific optimizer.
|
||||
"""
|
||||
function optimize!(optimizer::AbstractOptimizer, graph::DAG, n::Int)
|
||||
for i in 1:n
|
||||
optimize_step!(optimizer, graph)
|
||||
end
|
||||
return nothing
|
||||
end
|
@ -11,6 +11,7 @@ using Test
|
||||
include("node_reduction.jl")
|
||||
include("unit_tests_graph.jl")
|
||||
include("unit_tests_execution.jl")
|
||||
include("unit_tests_optimization.jl")
|
||||
|
||||
include("known_graphs.jl")
|
||||
end
|
||||
|
18
test/unit_tests_optimization.jl
Normal file
18
test/unit_tests_optimization.jl
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
@testset "Unit Tests Optimization" begin
|
||||
graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->AB.txt"), ABCModel())
|
||||
|
||||
@testset "Greedy Optimizer" begin
|
||||
estimator = GlobalMetricEstimator()
|
||||
optimizer = GreedyOptimizer(estimator)
|
||||
|
||||
optimize_step!(optimizer, graph)
|
||||
|
||||
@test length(graph.operationsToApply) + length(graph.appliedOperations) == 1
|
||||
|
||||
optimize!(optimizer, graph, 10)
|
||||
|
||||
@test length(graph.operationsToApply) + length(graph.appliedOperations) == 11
|
||||
end
|
||||
end
|
||||
println("Optimization Unit Tests Complete!")
|
Loading…
x
Reference in New Issue
Block a user