Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report dual objective values #70

Merged
merged 4 commits into from
Feb 26, 2024
Merged
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: 2 additions & 0 deletions src/julia/ClarabelRs/src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct SolutionJLRS
s::VectorJLRS{Float64}
status::UInt32 #0 indexed enum in RS/JL
obj_val::Float64
obj_val_dual::Float64
solve_time::Float64
iterations::UInt32
r_prim::Float64
Expand All @@ -81,6 +82,7 @@ function DefaultSolution(sol::SolutionJLRS)
Vector(sol.s),
Clarabel.SolverStatus(sol.status),
sol.obj_val,
sol.obj_val_dual,
sol.solve_time,
sol.iterations,
sol.r_prim,
Expand Down
2 changes: 2 additions & 0 deletions src/julia/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub(crate) struct SolutionJLRS {
pub s: VectorJLRS<f64>,
pub status: u32, //0 indexed enum in RS/JL
pub obj_val: f64,
pub obj_val_dual: f64,
pub solve_time: f64,
pub iterations: u32,
pub r_prim: f64,
Expand All @@ -124,6 +125,7 @@ impl From<&DefaultSolution<f64>> for SolutionJLRS {
s: VectorJLRS::<f64>::from(&sol.s),
status: sol.status as u32,
obj_val: sol.obj_val,
obj_val_dual: sol.obj_val_dual,
solve_time: sol.solve_time,
iterations: sol.iterations,
r_prim: sol.r_prim,
Expand Down
4 changes: 4 additions & 0 deletions src/solver/implementations/default/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub struct DefaultSolution<T> {
pub s: Vec<T>,
pub status: SolverStatus,
pub obj_val: T,
pub obj_val_dual: T,
pub solve_time: f64,
pub iterations: u32,
pub r_prim: T,
Expand All @@ -35,6 +36,7 @@ where
s,
status: SolverStatus::Unsolved,
obj_val: T::nan(),
obj_val_dual: T::nan(),
solve_time: 0f64,
iterations: 0,
r_prim: T::nan(),
Expand All @@ -59,6 +61,7 @@ where
) {
self.status = info.status;
self.obj_val = info.cost_primal;
self.obj_val_dual = info.cost_dual;

// if we have an infeasible problem, normalize
// using κ to get an infeasibility certificate.
Expand All @@ -67,6 +70,7 @@ where
if info.status.is_infeasible() {
scaleinv = T::recip(variables.κ);
self.obj_val = T::nan();
self.obj_val_dual = T::nan();
} else {
scaleinv = T::recip(variables.τ);
}
Expand Down
9 changes: 8 additions & 1 deletion tests/basic_lp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ fn test_lp_feasible() {
assert!(solver.solution.x.dist(&refsol) <= 1e-8);

let refobj = -3.;
assert!(f64::abs(solver.info.cost_primal - refobj) <= 1e-8);
assert!(f64::abs(solver.solution.obj_val - refobj) <= 1e-8);
assert!(f64::abs(solver.solution.obj_val_dual - refobj) <= 1e-8);
}

#[test]
Expand All @@ -60,6 +61,8 @@ fn test_lp_primal_infeasible() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::PrimalInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}

#[test]
Expand All @@ -76,6 +79,8 @@ fn test_lp_dual_infeasible() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::DualInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}

#[test]
Expand All @@ -93,4 +98,6 @@ fn test_lp_dual_infeasible_ill_cond() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::DualInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}
10 changes: 9 additions & 1 deletion tests/basic_qp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ fn test_qp_univariate() {

assert!(f64::abs(solver.solution.x[0]) <= 1e-6);
assert!(f64::abs(solver.solution.obj_val) <= 1e-6);
assert!(f64::abs(solver.solution.obj_val_dual) <= 1e-6);
}

#[test]
Expand All @@ -109,7 +110,8 @@ fn test_qp_feasible() {
assert!(solver.solution.x.dist(&refsol) <= 1e-6);

let refobj = 1.8800000298331538;
assert!(f64::abs(solver.info.cost_primal - refobj) <= 1e-6);
assert!(f64::abs(solver.solution.obj_val - refobj) <= 1e-6);
assert!(f64::abs(solver.solution.obj_val_dual - refobj) <= 1e-6);
}

#[test]
Expand All @@ -126,6 +128,8 @@ fn test_qp_primal_infeasible() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::PrimalInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}

#[test]
Expand All @@ -139,6 +143,8 @@ fn test_qp_dual_infeasible() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::DualInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}

#[test]
Expand All @@ -164,4 +170,6 @@ fn test_qp_dual_infeasible_ill_cond() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::DualInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}
5 changes: 4 additions & 1 deletion tests/basic_socp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ fn test_socp_feasible() {
assert!(solver.solution.x.dist(&refsol) <= 1e-4);

let refobj = -8.4590e-01;
assert!(f64::abs(solver.info.cost_primal - refobj) <= 1e-4);
assert!(f64::abs(solver.solution.obj_val - refobj) <= 1e-4);
assert!(f64::abs(solver.solution.obj_val_dual - refobj) <= 1e-4);
}

#[test]
Expand All @@ -85,4 +86,6 @@ fn test_socp_infeasible() {
solver.solve();

assert_eq!(solver.solution.status, SolverStatus::PrimalInfeasible);
assert!(solver.solution.obj_val.is_nan());
assert!(solver.solution.obj_val_dual.is_nan());
}