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

Any plan to add SCIPcreateExprPow ? #140

Open
youngzhaozju opened this issue Apr 12, 2024 · 5 comments
Open

Any plan to add SCIPcreateExprPow ? #140

youngzhaozju opened this issue Apr 12, 2024 · 5 comments

Comments

@youngzhaozju
Copy link

Hey, I want to use the function of "SCIPcreateExprPow". It is not available currently.

Therefore, I want to add it by my self.

pub(crate) fn create_pow_expr(
&mut self,
base: &Variable,
exponent: f64,
) -> Result<Expr, Retcode> {
let mut expr_ptr = MaybeUninit::uninit();
scip_call! { ffi::SCIPcreateExprPow(
self.raw,
expr_ptr.as_mut_ptr(),
base.raw as *mut _,
exponent,
None,
std::ptr::null_mut(),
) };

    let expr_ptr = unsafe { expr_ptr.assume_init() };
    Ok(Expr { raw: expr_ptr })
}

pub fn add_pow_expr(&mut self, base: &Variable, exponent: f64) -> Rc {
let exp = self
.scip
.create_pow_expr(base, exponent)
.expect("Failed to create express power in state ProblemCreated");
let exp_rc = Rc::new(exp);
return exp_rc;
}

Here is an example to utilize it,

// Create model
let mut model = Model::new()
.hide_output()
.include_default_plugins()
.create_prob("test")
.set_obj_sense(ObjSense::Maximize);

  // Add variables
  let x1 = model.add_var(0., f64::INFINITY, 3., "x1", VarType::Integer);
  let xx = model.add_pow_expr(&x1, 2.0);

  model.add_cons(
    vec![x1.clone(), **xx.clone()**],
    &[2., 1.],
    -f64::INFINITY,
    100.,
    "c1",
);

I found that I cannot utilize it in model.add_cons .
Is any suggestion?

Thank you!
Young

@youngzhaozju
Copy link
Author

I solved it. Thanks!

@mmghannam
Copy link
Member

@youngzhaozju Great! would you mind sharing how? and/or the code? to help others with the same issue and to help me understand what is needed to be added to the interface.

@youngzhaozju
Copy link
Author

youngzhaozju commented Apr 14, 2024

I found the most important interface for me is SCIPparseExpr. It allows to add complex expression. It helps me a lot to make my codes simple. Using the current version 0.3.4, I have to write a lot of codes to make constraints. Here are the coding for your consideration:

in scrip.rs, add following:

 fn add_Expression_by_txt(
        &mut self,
        content:&str
    )->Expr{
        let exp_rc = self.scip.crate_Expr_by_parse_string(content).expect(format!("Failed to prase txt in state ProblemCreated:{}", content).as_str());
        return exp_rc;
    }

 pub(crate) fn crate_Expr_by_parse_string(&mut self, content: &str) -> Result<Expr, Retcode> {
        let c_content = CString::new(content).expect("Failed to convert string to CString");
        let mut scip_Expr = MaybeUninit::uninit();

        let mut final_pos = ptr::null();

        scip_call! { ffi::SCIPparseExpr(
            self.raw,
            scip_Expr.as_mut_ptr(),
            c_content.as_ptr(),
            &mut final_pos,
            None,
            std::ptr::null_mut(),
        ) };

        let scip_Expr = unsafe { scip_Expr.assume_init() };

        Ok(Expr { raw: scip_Expr })
    }

Here is another important interface for me. it allows to use the above expression to make constraint directly:

            fn add_basic_nonlinear_cons(
                &mut self,
                express: Expr,
                lhs: f64,
                rhs: f64,
                name: &str,
            ) -> Rc<Constraint> {
                let cons = self
                    .scip.create_cons_basic_nonlinear(express.raw,lhs,rhs,name).expect("Failed to create basic nonlinear constraint in state ProblemCreated");
                let cons = Rc::new(cons);
                self.state.conss.borrow_mut().push(cons.clone());
                cons
            }

 fn add_Expression_text_to_eq_zero(
            &mut self,
            content:&str,
            name:&str,
        ) {
            let exp_rc = self.scip.crate_Expr_by_parse_string(content).expect(format!("Failed to prase txt in state ProblemCreated:{}", content).as_str());
             self
            .scip.create_cons_basic_nonlinear(exp_rc.raw,0.0,0.0,name).expect("Failed to create basic nonlinear constraint in state ProblemCreated");

        }

Here is an example:

 // Create model
    let mut model = Model::new()
        .hide_output()
        .include_default_plugins()
        .create_prob("test")
        .set_obj_sense(ObjSense::Minimize);

    // Add variables
    let x1 = model.add_var(-10., 4.0, 1., "x1", VarType::Continuous);

    let x2 = model.add_var(1.0, 5.0, 1.0, "x2", VarType::Continuous);


    let mut x1_expr = model.add_expr_var(&x1);


    let x2_expr = model.add_Expression_by_txt("<x2>*<x1> +  <x1>^2.0 - <x1>*<x2>*<x2>");
 

    model.add_basic_nonlinear_cons(x2_expr, 1.0, 1.0, "name");

    let solved_model = model.solve();

    let status = solved_model.status();
    println!("Solved with status {:?}", status);

    let obj_val = solved_model.obj_val();
    println!("Objective value: {}", obj_val);

    let sol = solved_model.best_sol().unwrap();
    let vars = solved_model.vars();

    for var in vars {
        println!("{} = {}", &var.name(), sol.val(var));
    }

    let model = solved_model.free_transform();

    println!("end");
    ```

@mmghannam
Copy link
Member

Very cool! I could happily copy this code and add it to the repo, but maybe you want to open a PR? so that your contribution is counted in the commit history?

@youngzhaozju
Copy link
Author

Thanks. I do not want to open a PR since I could not make continues contributions to this project. Anyway, thanks so much for your nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants