Add Optimization interface, add greedy optimizer, add some functionality to CDCost

This commit is contained in:
Anton Reinhard 2023-11-20 19:07:05 +01:00
parent c73053f991
commit 1e0e699e6d
7 changed files with 92 additions and 5 deletions

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View 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

View File

@ -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

View 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!")