diff --git a/src/model.rs b/src/model.rs index 6691604..f1e96a5 100644 --- a/src/model.rs +++ b/src/model.rs @@ -14,6 +14,7 @@ use crate::{BranchRule, HeurTiming, Heuristic, Pricer}; use crate::{Conshdlr, Diver}; use crate::{Row, Separator, ffi, scip_call_panic}; use scip_sys::SCIP; +use std::ptr::NonNull; use std::rc::Rc; /// Represents an optimization model. @@ -423,8 +424,9 @@ impl Model { pub fn create_sol(&self) -> Solution { let sol_ptr = self .scip - .create_sol(false) + .create_sol(true) .expect("Failed to create solution in state ProblemCreated"); + let sol_ptr = NonNull::new(sol_ptr).expect("SCIP returned null solution pointer"); Solution { scip_ptr: self.scip.clone(), raw: sol_ptr, @@ -1061,6 +1063,7 @@ impl ProblemOrSolving for Model { .scip .create_sol(true) .expect("Failed to create solution in state ProblemCreated"); + let sol_ptr = NonNull::new(sol_ptr).expect("SCIP returned null solution pointer"); Solution { scip_ptr: self.scip.clone(), raw: sol_ptr, @@ -1429,7 +1432,8 @@ impl WithSolutions for Model { if self.n_sols() > 0 { let sol = Solution { scip_ptr: self.scip.clone(), - raw: self.scip.best_sol().unwrap(), + raw: std::ptr::NonNull::new(self.scip.best_sol().unwrap()) + .expect("SCIP returned null pointer for best solution"), }; Some(sol) } else { @@ -1445,17 +1449,17 @@ impl WithSolutions for Model { /// Returns a vector containing all solutions stored in the solution storage. fn get_sols(&self) -> Option> { if self.n_sols() > 0 { - let scip_sols = self - .scip + self.scip .get_sols() .unwrap() .into_iter() .map(|x| Solution { - raw: x, + raw: std::ptr::NonNull::new(x) + .expect("SCIP returned null pointer for solution"), scip_ptr: self.scip.clone(), }) - .collect(); - Some(scip_sols) + .collect::>() + .into() } else { None } diff --git a/src/scip.rs b/src/scip.rs index e3b5a14..5d4da0e 100644 --- a/src/scip.rs +++ b/src/scip.rs @@ -1256,7 +1256,7 @@ impl ScipPtr { assert!(!sol.is_null()); let solution = Solution { - raw: sol, + raw: std::ptr::NonNull::new(sol).expect("sol is null"), scip_ptr: scip_ptr.clone(), }; @@ -1472,26 +1472,29 @@ impl ScipPtr { Ok(node_ptr) } - pub(crate) fn add_sol(&self, mut sol: Solution) -> Result { + pub(crate) fn add_sol(&self, sol: Solution) -> Result { let mut feasible = 0; - assert!(!sol.raw.is_null()); - let is_orig = unsafe { ffi::SCIPsolIsOriginal(sol.raw) } == 1; + let is_orig = unsafe { ffi::SCIPsolIsOriginal(sol.raw.as_ptr()) } == 1; if is_orig { scip_call!(ffi::SCIPcheckSolOrig( self.raw, - sol.raw, + sol.raw.as_ptr(), &mut feasible, false.into(), true.into(), )); if feasible == 1 { - scip_call!(ffi::SCIPaddSolFree(self.raw, &mut sol.raw, &mut feasible)); + scip_call!(ffi::SCIPaddSolFree( + self.raw, + &mut sol.raw.as_ptr(), + &mut feasible + )); } return Ok(feasible != 0); } else { scip_call!(ffi::SCIPtrySol( self.raw, - sol.raw, + sol.raw.as_ptr(), false.into(), true.into(), true.into(), diff --git a/src/solution.rs b/src/solution.rs index a9c8c7e..9ae7e7c 100644 --- a/src/solution.rs +++ b/src/solution.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::ptr::NonNull; use std::rc::Rc; use crate::scip::ScipPtr; @@ -8,31 +9,31 @@ use crate::{ffi, scip_call_panic}; /// A wrapper for a SCIP solution. #[derive(Clone)] pub struct Solution { - pub(crate) raw: *mut ffi::SCIP_SOL, pub(crate) scip_ptr: Rc, + pub(crate) raw: NonNull, } impl Solution { /// Returns a raw pointer to the underlying `ffi::SCIP_SOL` struct. pub fn inner(&self) -> *mut ffi::SCIP_SOL { - self.raw + self.raw.as_ptr() } /// Returns the objective value of the solution. pub fn obj_val(&self) -> f64 { - unsafe { ffi::SCIPgetSolOrigObj(self.scip_ptr.raw, self.raw) } + unsafe { ffi::SCIPgetSolOrigObj(self.scip_ptr.raw, self.raw.as_ptr()) } } /// Returns the value of a variable in the solution. pub fn val(&self, var: &Variable) -> f64 { - unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw, var.raw) } + unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw.as_ptr(), var.raw) } } /// Sets the value of a variable in the solution. pub fn set_val(&self, var: &Variable, val: f64) { scip_call_panic!(ffi::SCIPsetSolVal( self.scip_ptr.raw, - self.raw, + self.raw.as_ptr(), var.raw, val )); @@ -45,7 +46,7 @@ impl Solution { let mut map = std::collections::HashMap::new(); for i in 0..n_vars { let var = unsafe { *vars.offset(i as isize) }; - let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw, var) }; + let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw.as_ptr(), var) }; let eps = unsafe { ffi::SCIPepsilon(self.scip_ptr.raw) }; if val > eps || val < -eps { let name_ptr = unsafe { ffi::SCIPvarGetName(var) }; @@ -64,7 +65,7 @@ impl Solution { let mut map = std::collections::HashMap::new(); for i in 0..n_vars { let var = unsafe { *vars.offset(i as isize) }; - let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw, var) }; + let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw.as_ptr(), var) }; let eps = unsafe { ffi::SCIPepsilon(self.scip_ptr.raw) }; if val > eps || val < -eps { let id = unsafe { ffi::SCIPvarGetProbindex(var) }; @@ -84,7 +85,7 @@ impl fmt::Debug for Solution { let n_vars = unsafe { ffi::SCIPgetNOrigVars(self.scip_ptr.raw) }; for i in 0..n_vars { let var = unsafe { *vars.offset(i as isize) }; - let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw, var) }; + let val = unsafe { ffi::SCIPgetSolVal(self.scip_ptr.raw, self.raw.as_ptr(), var) }; let eps = unsafe { ffi::SCIPepsilon(self.scip_ptr.raw) }; if val > eps || val < -eps { let name_ptr = unsafe { ffi::SCIPvarGetName(var) };