From f4624c70894bb052526f37578f4ac7acc99874f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Tue, 10 Oct 2023 13:27:08 +0200 Subject: [PATCH] convex hull (#436) --- src/polytope_oracles.jl | 23 +++++++++++++++++++++++ test/lmo.jl | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/polytope_oracles.jl b/src/polytope_oracles.jl index 7000f6c83..68af09574 100644 --- a/src/polytope_oracles.jl +++ b/src/polytope_oracles.jl @@ -216,3 +216,26 @@ function compute_extreme_point( v[idx] = ifelse(lower, lmo.lower_bounds[idx], lmo.upper_bounds[idx]) return v end + +""" + ConvexHullOracle{AT,VT} + +Convex hull of a finite number of vertices of type `AT`, stored in a vector of type `VT`. +""" +struct ConvexHullOracle{AT, VT <: AbstractVector{AT}} + vertices::VT +end + +function compute_extreme_point(lmo::ConvexHullOracle{AT}, direction; v=nothing, kwargs...) where {AT} + T = promote_type(eltype(direction), eltype(AT)) + best_val = T(Inf) + best_vertex = first(lmo.vertices) + for vertex in lmo.vertices + val = dot(vertex, direction) + if val < best_val + best_val = val + best_vertex = vertex + end + end + return best_vertex +end diff --git a/test/lmo.jl b/test/lmo.jl index 0abece6ea..821bcbd5a 100644 --- a/test/lmo.jl +++ b/test/lmo.jl @@ -788,3 +788,20 @@ end xv = JuMP.value.(x) @test dot(xv, d) ≈ dot(v, d) atol=1e-5*n end + +@testset "Convex hull" begin + lmo = FrankWolfe.ConvexHullOracle([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + ]) + for _ in 1:100 + d = randn(3) + v = FrankWolfe.compute_extreme_point(lmo, d) + v_simplex = FrankWolfe.compute_extreme_point(FrankWolfe.ProbabilitySimplexOracle(1), d) + @test v == v_simplex + end + d = zeros(3) + v = FrankWolfe.compute_extreme_point(lmo, d) + @test v == lmo.vertices[1] +end