@@ -8,6 +8,10 @@ use crate::{
88} ;
99use sprs:: CompressedStorage ;
1010
11+ use web_time:: Instant ;
12+
13+ pub ( crate ) type Deadline = Option < Instant > ;
14+
1115type CsMat = sprs:: CsMatI < f64 , usize > ;
1216
1317pub ( crate ) const MACHINE_EPS : f64 = f64:: EPSILON * 10.0 ;
@@ -25,9 +29,20 @@ pub(crate) fn float_ne(a: f64, b: f64) -> bool {
2529 !float_eq ( a, b)
2630}
2731
32+ #[ inline]
33+ fn check_deadline ( deadline : & Deadline ) -> Result < ( ) , Error > {
34+ if let Some ( dl) = deadline {
35+ if Instant :: now ( ) >= * dl {
36+ return Err ( Error :: Limit ) ;
37+ }
38+ }
39+ Ok ( ( ) )
40+ }
41+
2842#[ derive( Clone ) ]
2943pub ( crate ) struct Solver {
3044 pub ( crate ) num_vars : usize ,
45+ pub ( crate ) deadline : Deadline ,
3146
3247 orig_obj_coeffs : Vec < f64 > ,
3348 orig_var_mins : Vec < f64 > ,
@@ -138,6 +153,7 @@ impl Solver {
138153 var_maxs : & [ f64 ] ,
139154 constraints : & [ ( CsVec , ComparisonOp , f64 ) ] ,
140155 var_domains : & [ VarDomain ] ,
156+ deadline : Deadline ,
141157 ) -> Result < Self , Error > {
142158 let enable_steepest_edge = true ; // TODO: make user-settable.
143159
@@ -356,6 +372,7 @@ impl Solver {
356372 orig_constraints,
357373 orig_constraints_csc,
358374 orig_rhs,
375+ deadline,
359376 orig_var_domains : var_domains. to_vec ( ) ,
360377 /*orig_int_vars: var_domains
361378 .to_vec()
@@ -505,6 +522,8 @@ impl Solver {
505522 }
506523
507524 pub ( crate ) fn initial_solve ( & mut self ) -> Result < ( ) , Error > {
525+ check_deadline ( & self . deadline ) ?;
526+
508527 if !self . is_primal_feasible {
509528 self . restore_feasibility ( ) ?;
510529 }
@@ -549,6 +568,10 @@ impl Solver {
549568 } ;
550569
551570 for iter in 0 .. {
571+ if iter % 100 == 0 {
572+ check_deadline ( & self . deadline ) ?;
573+ }
574+
552575 //guaranteed to have at an element
553576 let cur_step = match dfs_stack. pop ( ) {
554577 Some ( step) => step,
@@ -622,6 +645,8 @@ impl Solver {
622645 fn optimize ( & mut self ) -> Result < ( ) , Error > {
623646 for iter in 0 .. {
624647 if iter % 1000 == 0 {
648+ check_deadline ( & self . deadline ) ?;
649+
625650 let ( num_vars, infeasibility) = self . calc_dual_infeasibility ( ) ;
626651 debug ! (
627652 "optimize iter {}: obj.: {}, non-optimal coeffs: {} ({})" ,
@@ -654,6 +679,8 @@ impl Solver {
654679
655680 for iter in 0 .. {
656681 if iter % 1000 == 0 {
682+ check_deadline ( & self . deadline ) ?;
683+
657684 let ( num_vars, infeasibility) = self . calc_primal_infeasibility ( ) ;
658685 debug ! (
659686 "restore feasibility iter {}: {}: {}, infeas. vars: {} ({})" ,
@@ -764,7 +791,6 @@ impl Solver {
764791 }
765792 }
766793
767-
768794 self . is_primal_feasible = false ;
769795 self . restore_feasibility ( )
770796 }
@@ -1621,6 +1647,7 @@ mod tests {
16211647 ( to_sparse ( & [ 0.0 , 1.0 ] ) , ComparisonOp :: Eq , 3.0 ) ,
16221648 ] ,
16231649 & [ VarDomain :: Real , VarDomain :: Real ] ,
1650+ Default :: default ( ) ,
16241651 )
16251652 . unwrap ( ) ;
16261653
@@ -1719,6 +1746,7 @@ mod tests {
17191746 ( to_sparse ( & [ -1.0 , 4.0 ] ) , ComparisonOp :: Le , 20.0 ) ,
17201747 ] ,
17211748 & [ VarDomain :: Real , VarDomain :: Real ] ,
1749+ Default :: default ( ) ,
17221750 )
17231751 . unwrap ( ) ;
17241752 sol. initial_solve ( ) . unwrap ( ) ;
@@ -1742,6 +1770,7 @@ mod tests {
17421770 ( to_sparse ( & [ 1.0 , 1.0 ] ) , ComparisonOp :: Le , 5.0 ) ,
17431771 ] ,
17441772 & [ VarDomain :: Real , VarDomain :: Real ] ,
1773+ Default :: default ( ) ,
17451774 )
17461775 . unwrap ( )
17471776 . initial_solve ( ) ;
0 commit comments