Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
JuliaFormatter = "=2.10.1"
Manifolds = "0.11.28"
ManifoldsBase = "2.3.5"
Manopt = "0.6"
Manopt = "0.6.2"
PrecompileTools = "1"
ProgressMeter = "1.11.0"
RecursiveArrayTools = "4.3"
Expand Down
1 change: 1 addition & 0 deletions src/solvers/lbfgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ function solve_lbfgs(
stepsize = _lbfgs_linesearch(linesearch),
stopping_criterion = stopping,
debug = callbacks.debug_actions,
callbacks = callbacks.solver_callbacks,
count = [:Cost, :Gradient],
return_state = true,
)
Expand Down
1 change: 1 addition & 0 deletions src/solvers/lm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ function solve_lm(
sub_objective = sub_objective,
sub_state = sub_state,
debug = callbacks.debug_actions,
callbacks = callbacks.solver_callbacks,
return_state = true,
)

Expand Down
33 changes: 21 additions & 12 deletions src/solvers/manopt_helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ function _manopt_stopping(maxiter::Int, grad_stop_tol, dual_stop; extra = ())
)
end

# Create progress and debug callbacks shared by Manopt-backed solvers.
# Create progress, lifecycle callbacks, and debug actions shared by Manopt-backed solvers.
function _manopt_callbacks(
make_progress::Function,
maxiter::Int,
Expand All @@ -444,18 +444,21 @@ function _manopt_callbacks(
M;
diagnostics_recorder,
)
debug_actions = _solver_debug_actions(
verbose,
step_callback = _solver_callback_group(
post_step_callback,
diagnostics_callback,
progress_callback,
iteration_callbacks...,
)
solver_callbacks =
isnothing(step_callback) ? Any[] : Any[:Init=>step_callback, :Step=>step_callback]
debug_actions = _solver_debug_actions(verbose)
return (
progress = progress,
diagnostics_callback = diagnostics_callback,
progress_callback = progress_callback,
debug_actions = debug_actions,
solver_callbacks = solver_callbacks,
)
end

Expand Down Expand Up @@ -595,12 +598,20 @@ function _solver_stats(
)
end

# Collect only active Manopt debug callbacks, dropping omitted hooks.
_solver_debug_callbacks(callbacks...) = Any[cb for cb in callbacks if !isnothing(cb)]
# Combine active solver callbacks in their declared execution order.
function _solver_callback_group(callbacks...)
active_callbacks = Any[callback for callback in callbacks if !isnothing(callback)]
isempty(active_callbacks) && return nothing
return function (problem, state, k)
for callback in active_callbacks
callback(problem, state, k)
end
return nothing
end
end

# Build Manopt debug actions and attach TensorKitchen callback hooks.
function _solver_debug_actions(verbose::Union{Nothing,Bool}, callbacks...)
callback_actions = _solver_debug_callbacks(callbacks...)
# Build only Manopt display/debug actions; solver callbacks use `callbacks=`.
function _solver_debug_actions(verbose::Union{Nothing,Bool})
if verbose === true
io = _SOLVER_DEBUG_SINK
init_group = Manopt.DebugGroup([
Expand All @@ -619,11 +630,9 @@ function _solver_debug_actions(verbose::Union{Nothing,Bool}, callbacks...)
]),
100,
)
iteration_actions = Any[iter_group]
append!(iteration_actions, callback_actions)
return Any[:Start=>Any[init_group], :Iteration=>iteration_actions]
return Any[:Start=>Any[init_group], :Iteration=>Any[iter_group]]
end
return callback_actions
return Any[]
end

# Create a Manopt iteration callback that updates TensorKitchen progress output.
Expand Down
1 change: 1 addition & 0 deletions src/solvers/rcg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ function solve_rcg(
restart_condition = restart_rule,
stopping_criterion = stopping,
debug = callbacks.debug_actions,
callbacks = callbacks.solver_callbacks,
count = [:Cost, :Gradient],
return_state = true,
)
Expand Down
2 changes: 2 additions & 0 deletions src/solvers/rgd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ function solve_rgd(
stepsize = armijo,
stopping_criterion = stopping,
debug = callbacks.debug_actions,
callbacks = callbacks.solver_callbacks,
count = [:Cost, :Gradient],
return_state = true,
)
Expand Down Expand Up @@ -189,6 +190,7 @@ function solve_rgd_fixed(
stepsize = Manopt.ConstantStepsize(M, T(stepsize) * setup.objective_scale),
stopping_criterion = stopping,
debug = callbacks.debug_actions,
callbacks = callbacks.solver_callbacks,
count = [:Cost, :Gradient],
return_state = true,
)
Expand Down
5 changes: 4 additions & 1 deletion test/basic_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ end
@test res_init_sym.solver_info.function_evaluations >= 0
@test res_init_sym.solver_info.gradient_evaluations >= 1

res_trace = cpd(
res_trace = @test_logs min_level = Base.CoreLogging.Warn cpd(
A,
r;
solver = :rgd,
Expand Down Expand Up @@ -1202,6 +1202,9 @@ end
@test hasproperty(trace_info, :component_trace_rgrad_failed_count)
@test isfinite(trace_info.component_trace_start_rel_error)
@test trace_info.component_trace_rgrad_failed_count == 0
@test length(trace_info.component_trace_iterations) == res_trace.iterations
@test length(trace_info.component_trace_cost_history) == res_trace.iterations
@test length(trace_info.component_trace_max_delta_history) == res_trace.iterations
@test length(trace_info.component_trace_iterations) ==
length(trace_info.component_trace_max_delta_history)
@test length(trace_info.component_trace_delta_history) ==
Expand Down
Loading