Skip to main content

gurobi/
env.rs

1// Copyright (c) 2016 Yusuke Sasaki
2//
3// This software is released under the MIT License.
4// See http://opensource.org/licenses/mit-license.php or <LICENSE>.
5
6use ffi;
7
8use std::ffi::CString;
9use std::ptr::null_mut;
10
11use error::{Error, Result};
12use model::Model;
13use parameter::Param;
14use util;
15
16/// Gurobi environment object
17pub struct Env {
18  env: *mut ffi::GRBenv,
19  require_drop: bool
20}
21
22impl Env {
23  /// Create an environment with log file
24  pub fn new(logfilename: &str) -> Result<Env> {
25    let mut env = null_mut();
26    let logfilename = try!(CString::new(logfilename));
27    let error = unsafe { ffi::GRBloadenv(&mut env, logfilename.as_ptr()) };
28    if error != 0 {
29      return Err(Error::FromAPI(get_error_msg(env), error));
30    }
31    Ok(Env {
32      env: env,
33      require_drop: true
34    })
35  }
36
37  /// Create a client environment on a computer server with log file
38  pub fn new_client(logfilename: &str, computeserver: &str, port: i32, password: &str, priority: i32, timeout: f64)
39                    -> Result<Env> {
40    let mut env = null_mut();
41    let logfilename = try!(CString::new(logfilename));
42    let computeserver = try!(CString::new(computeserver));
43    let password = try!(CString::new(password));
44    let error = unsafe {
45      ffi::GRBloadclientenv(&mut env,
46                            logfilename.as_ptr(),
47                            computeserver.as_ptr(),
48                            port,
49                            password.as_ptr(),
50                            priority,
51                            timeout)
52    };
53    if error != 0 {
54      return Err(Error::FromAPI(get_error_msg(env), error));
55    }
56    Ok(Env {
57      env: env,
58      require_drop: true
59    })
60  }
61
62  /// Create an empty Gurobi model from the environment
63  #[deprecated]
64  pub fn new_model(&self, modelname: &str) -> Result<Model> { Model::new(modelname, self) }
65
66  /// Read a model from a file
67  #[deprecated]
68  pub fn read_model(&self, filename: &str) -> Result<Model> { Model::read_from(filename, self) }
69
70  /// Query the value of a parameter
71  pub fn get<P: Param>(&self, param: P) -> Result<P::Out> {
72    use util::AsRawPtr;
73    let mut value: P::Buf = util::Init::init();
74    try!(self.check_apicall(unsafe { P::get_param(self.env, param.into().as_ptr(), value.as_rawptr()) }));
75
76    Ok(util::Into::into(value))
77  }
78
79  /// Set the value of a parameter
80  pub fn set<P: Param>(&mut self, param: P, value: P::Out) -> Result<()> {
81    self.check_apicall(unsafe { P::set_param(self.env, param.into().as_ptr(), util::FromRaw::from(value)) })
82  }
83
84  /// Import a set of parameter values from a file
85  pub fn read_params(&mut self, filename: &str) -> Result<()> {
86    let filename = try!(CString::new(filename));
87    self.check_apicall(unsafe { ffi::GRBreadparams(self.env, filename.as_ptr()) })
88  }
89
90  /// Write the set of parameter values to a file
91  pub fn write_params(&self, filename: &str) -> Result<()> {
92    let filename = try!(CString::new(filename));
93    self.check_apicall(unsafe { ffi::GRBwriteparams(self.env, filename.as_ptr()) })
94  }
95
96  /// Insert a message into log file.
97  ///
98  /// When **message** cannot convert to raw C string, a panic is occurred.
99  #[allow(temporary_cstring_as_ptr)]
100  pub fn message(&self, message: &str) { unsafe { ffi::GRBmsg(self.env, CString::new(message).unwrap().as_ptr()) }; }
101}
102
103pub trait EnvAPI {
104  fn get_ptr(&self) -> *mut ffi::GRBenv;
105  fn check_apicall(&self, error: ffi::c_int) -> Result<()>;
106}
107
108impl EnvAPI for Env {
109  fn get_ptr(&self) -> *mut ffi::GRBenv { self.env }
110
111  fn check_apicall(&self, error: ffi::c_int) -> Result<()> {
112    if error != 0 {
113      return Err(self.error_from_api(error));
114    }
115    Ok(())
116  }
117}
118
119impl Drop for Env {
120  fn drop(&mut self) {
121    if self.require_drop {
122      unsafe { ffi::GRBfreeenv(self.env) };
123      self.env = null_mut();
124    }
125  }
126}
127
128
129pub trait ErrorFromAPI {
130  fn error_from_api(&self, error: ffi::c_int) -> Error;
131}
132
133impl ErrorFromAPI for Env {
134  fn error_from_api(&self, error: ffi::c_int) -> Error { Error::FromAPI(get_error_msg(self.env), error) }
135}
136
137pub trait FromRaw {
138  fn from_raw(env: *mut ffi::GRBenv) -> Self;
139}
140
141impl FromRaw for Env {
142  fn from_raw(env: *mut ffi::GRBenv) -> Env {
143    Env {
144      env: env,
145      require_drop: false
146    }
147  }
148}
149
150
151fn get_error_msg(env: *mut ffi::GRBenv) -> String { unsafe { util::from_c_str(ffi::GRBgeterrormsg(env)) } }
152
153
154// #[test]
155// fn env_with_logfile() {
156//   use std::path::Path;
157//   use std::fs::remove_file;
158//
159//   let path = Path::new("test_env.log");
160//
161//   if path.exists() {
162//     remove_file(path).unwrap();
163//   }
164//
165//   {
166//     let env = Env::new(path.to_str().unwrap()).unwrap();
167//   }
168//
169//   assert!(path.exists());
170//   remove_file(path).unwrap();
171// }
172
173#[test]
174fn param_accesors_should_be_valid() {
175  use super::param;
176  let mut env = Env::new("").unwrap();
177  env.set(param::IISMethod, 1).unwrap();
178  let iis_method = env.get(param::IISMethod).unwrap();
179  assert_eq!(iis_method, 1);
180}