Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Marguerite.jl

A minimal, differentiable Frank-Wolfe solver for constrained convex optimization in Julia.

Named in honor of Marguerite Frank (1927--2024), co-inventor of the Frank-Wolfe algorithm (1956).

Docs Build Status Julia License

Finds parameterized solutions to constrained convex programs of the form

$$ x_\star(\theta) \in \arg\min_{x \in \mathcal{C}(\theta)}, f(x;\theta), $$

where $\mathcal{C}(\theta)$ is a compact convex set parameterized by $\theta$, accessed via a linear minimization oracle (LMO). The LMO returns solutions to the linear subproblem

$$ v_\star(\theta) \in \arg\min_{v \in \mathcal{C}(\theta)} \ \langle \nabla f, v \rangle. $$

Scalable bilevel programming

Marguerite.jl is built for simple and fast bilevel optimization, meaning optimization programs that appear as

$$ \begin{align*} & \min_{\theta \in \Theta} \quad u(x_\star(\theta)) \\ & \mathsf{s.t.} \quad x_\star(\theta) \in \arg\min_{x \in \mathcal{C}(\theta)}, f(x;\theta). \end{align*} $$

Marguerite implements implicit differentiation through the KKT conditions of the inner problem, using the active constraint structure of each oracle to build efficient pullbacks. The solver, differentiation, and bilevel interface share a single solve entry point.

Quick Start

using Marguerite, LinearAlgebra

# -- Constrained optimization ---------------------
Q = [4.0 1.0; 1.0 2.0]; c = [-3.0, -1.0]
f(x) = 0.5 * dot(x, Q * x) + dot(c, x)
∇f!(g, x) = (g .= Q * x .+ c)

x, result = solve(f, ProbSimplex(), [0.5, 0.5]; grad=∇f!)

# -- Bilevel optimization -------------------------
x_target = [0.7, 0.3]; θ = zeros(2); η = 0.1

inner(x, θ) = 0.5 * dot(x, x) - dot(θ, x)
outer(x) = sum((x .- x_target).^2)

x_curr = [0.5, 0.5]
for _ in 1:50
    x, dθ, _ = bilevel_solve(outer, inner, ProbSimplex(),
                               x_curr, θ)
    x_curr .= x
    θ .-= η .*end
println("x_curr = ", round.(x_curr; digits=3))  # x_curr ≈ x_target

Omit grad= for automatic differentiation via ForwardDiff.

Why Marguerite.jl?

When to use Marguerite

  • You have a constrained convex problem and a linear minimization oracle (LMO) for the constraint set
  • You want differentiable optimization -- gradients through the solver via implicit differentiation
  • You need projection-free optimization (simplex, knapsack, matroid, flow polytopes, etc.)
  • You want bilevel optimization with constrained inner problems
  • You value a simple, minimal API with zero-allocation inner loops

Features

  • Single entry point: solve(f, lmo, x0; grad=∇f!, ...), with or without automatic gradients and differentiable parameters
  • Pre-allocated buffers for allocation-free inner loops (@inbounds hot paths)
  • Seven built-in oracles: simplex, probability simplex, knapsack, masked knapsack, box, weighted simplex, spectraplex
  • Custom oracles: any (v, g) -> v callable for primal solves; differentiated custom oracles should also implement active_set
  • Differentiable solve via ChainRulesCore.rrule for $\partial x^* / \partial \theta$ (implicit differentiation)
  • Bilevel optimization: bilevel_solve backpropagates through the solver to learn parameters of constrained problems

See also

Other great packages in the Frank-Wolfe ecosystem:

Documentation

See the full documentation for tutorials, examples, and API reference.

Installation

Requires Julia 1.12+. Install directly from the repository:

using Pkg
Pkg.add(url="https://github.com/samtalki/Marguerite.jl")

Testing

Run the default representative suite:

julia --project=. -e 'using Pkg; Pkg.test()'

Run the exhaustive suite with the full differentiation, bilevel, and verification sweeps:

MARGUERITE_TEST_GROUP=all julia --project=. -e 'using Pkg; Pkg.test()'

Citing

If you use Marguerite.jl in your research, please cite:

@software{talkington2026marguerite,
  author  = {Talkington, Samuel},
  title   = {Marguerite.jl: A Minimal, Differentiable Frank-Wolfe Solver},
  year    = {2026},
  url     = {https://github.com/samtalki/Marguerite.jl},
  version = {0.2.0}
}

References

About

A differentiable Frank-Wolfe solver - minimal and in pure Julia.

Topics

Resources

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages