From f51c5260a7a1b90e052929f25775149d809c219b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Arnstr=C3=B6m?= <55484604+darnstrom@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:27:49 +0100 Subject: [PATCH] v0.2.1 (#12) * Normalize and rows in general parameter constraints * only normalize if norm_factor > 0 * v0.2.1 --- Project.toml | 2 +- src/mpsolve.jl | 7 ++++++- src/utils.jl | 28 ++++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Project.toml b/Project.toml index a5e0ae4..2a9bd4c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ParametricDAQP" uuid = "19f72acb-e2a9-45c8-96b9-4d5487c8db2e" authors = ["Daniel Arnström "] -version = "0.2.0" +version = "0.2.1" [deps] DAQP = "c47d62df-3981-49c8-9651-128b1cd08617" diff --git a/src/mpsolve.jl b/src/mpsolve.jl index 7564358..2092261 100644 --- a/src/mpsolve.jl +++ b/src/mpsolve.jl @@ -27,6 +27,11 @@ function mpsolve(mpQP,Θ;opts=nothing, AS0 = nothing) # bounds_table as option # Setup parametric problem and normalize prob = setup_mpp(mpQP;fix_ids,fix_vals) prob, Θ, tf = normalize_parameters(prob,Θ) + if(isnothing(prob)) # Θ makes the problem trivially infeasible + @warn "The parameter region of interest is empty" + F,info = CriticalRegion[], (solve_time = 0, nCR = 0, nLPs = 0, nExplored = 0,status=:EmptyParameterRegion) + end + if(isnothing(AS0)) AS0 = compute_AS0(prob,Θ) @@ -50,7 +55,7 @@ function mpdaqp_explicit(prob,Θ,AS0;opts = Settings()) if(length(id_cands) < m) id_zeros = findall(prob.norm_factors .≤ opts.eps_zero) opts.verbose > 0 && @warn "Rows $id_zeros in A are zero → seen as parameter constraints" - if hasproperty(Θ,:Ath) + if hasproperty(Θ,:A) A = [Θ.A -prob.d[1:end-1,id_zeros]] b = [Θ.b; prob.d[end,id_zeros]] else diff --git a/src/utils.jl b/src/utils.jl index a9377c6..3691682 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -48,8 +48,10 @@ function setup_mpp(mpQP;normalize=true, fix_ids=Int[],fix_vals=zeros(0)) norm_factor = 0 for i in 1:m norm_factor = norm(view(M,i,:),2) - M[i,:]./=norm_factor - d[:,i]./=norm_factor + if(norm_factor > 0) + M[i,:]./=norm_factor + d[:,i]./=norm_factor + end norm_factors[i]= norm_factor end end @@ -65,7 +67,7 @@ function setup_mpp(mpQP;normalize=true, fix_ids=Int[],fix_vals=zeros(0)) end ## Normalize parameters to -1 ≤ θ ≤ 1 -function normalize_parameters(prob::MPLDP,Θ) +function normalize_parameters(prob::MPLDP,Θ;eps_zero=1e-12) if(isempty(Θ.ub)) # assume already normalized return prob,Θ,(center=0,scaling = 1) end @@ -80,8 +82,26 @@ function normalize_parameters(prob::MPLDP,Θ) Ath = haskey(Θ,:A) ? Θ.A : zeros(nth,0); bth = haskey(Θ,:b) ? Θ.b : zeros(0); - Θ =(A=norm_factors.*Ath, b = bth-(center'*Ath)[:], # TODO: verify + + # Normalize A to box -1 ≤ θ ≤ 1 + A = norm_factors.*Ath + b = bth-(center'*Ath)[:] + + # Normalize A + is_nonzero = falses(length(b)) + for i in 1:length(b) + norm_factor = norm(view(A,:,i),2); + if(norm_factor>eps_zero) + rdiv!(view(A,:,i),norm_factor) + b[i]/=norm_factor + is_nonzero[i] = true + else + (b[i]<-eps_zero) && return nothing,nothing,nothing # trivially infeasible + end + end + Θ =(A=A[:,is_nonzero], b = b[is_nonzero], # TODO: verify lb = -ones(nth), ub = ones(nth)); + return prob, Θ,(center=center, scaling = 1 ./ norm_factors) end function normalize_parameters(prob::MPQP,Θ)