@@ -483,11 +483,11 @@ void PreprocessScaling::undo(PreprocessorPoint& point, const Model& model,
483483
484484 // set variables that were ignored
485485 for (Int i = 0 ; i < n_post; ++i) {
486- if (!model.hasLb (i)) {
486+ if (!model.hasLb (i) || model. is_free_ [i] ) {
487487 point.xl [i] = kHighsInf ;
488488 point.zl [i] = 0.0 ;
489489 }
490- if (!model.hasUb (i)) {
490+ if (!model.hasUb (i) || model. is_free_ [i] ) {
491491 point.xu [i] = kHighsInf ;
492492 point.zu [i] = 0.0 ;
493493 }
@@ -561,11 +561,11 @@ void PreprocessFormulation::undo(PreprocessorPoint& point, const Model& model,
561561
562562 // force unused entries to have correct value
563563 for (Int i = 0 ; i < n_pre; ++i) {
564- if (!model.hasLb (i)) {
564+ if (!model.hasLb (i) || model. is_free_ [i] ) {
565565 point.xl [i] = kHighsInf ;
566566 point.zl [i] = 0.0 ;
567567 }
568- if (!model.hasUb (i)) {
568+ if (!model.hasUb (i) || model. is_free_ [i] ) {
569569 point.xu [i] = kHighsInf ;
570570 point.zu [i] = 0.0 ;
571571 }
@@ -617,6 +617,49 @@ void PreprocessFormulation::print(std::stringstream& stream) const {
617617 stream << " Added " << n_post - n_pre << " slacks\n " ;
618618}
619619
620+ void PreprocessFreeVars::apply (Model& model) {
621+ Int& n = model.n_ ;
622+ Int& m = model.m_ ;
623+ HighsSparseMatrix& A = model.A_ ;
624+ std::vector<double >& b = model.b_ ;
625+ std::vector<double >& c = model.c_ ;
626+ std::vector<double >& lower = model.lower_ ;
627+ std::vector<double >& upper = model.upper_ ;
628+ std::vector<char >& constraints = model.constraints_ ;
629+ HighsHessian& Q = model.Q_ ;
630+ std::vector<bool >& is_free = model.is_free_ ;
631+
632+ n_pre = n;
633+ m_pre = m;
634+
635+ is_free.assign (n, false );
636+
637+ for (Int i = 0 ; i < n; ++i) {
638+ if (!std::isfinite (lower[i]) && !std::isfinite (upper[i]) &&
639+ lower[i] != upper[i]) {
640+ // free variable
641+ is_free[i] = true ;
642+ ++free_vars;
643+ lower[i] = -kFreeVarsInitialBound ;
644+ upper[i] = kFreeVarsInitialBound ;
645+ }
646+ }
647+
648+ n_post = n;
649+ m_post = m;
650+ }
651+
652+ void PreprocessFreeVars::undo (PreprocessorPoint& point, const Model& model,
653+ const Iterate& it) const {
654+ point.assertConsistency (n_post, m_post);
655+ //
656+ point.assertConsistency (n_pre, m_pre);
657+ }
658+
659+ void PreprocessFreeVars::print (std::stringstream& stream) const {
660+ if (free_vars > 0 ) stream << " Found " << free_vars << " free variables\n " ;
661+ }
662+
620663#define APPLY_ACTION (T ) \
621664 stack.push_back(std::unique_ptr<PreprocessAction>(new T)); \
622665 stack.back()->apply (model);
@@ -629,6 +672,7 @@ void Preprocessor::apply(Model& model) {
629672 APPLY_ACTION (PreprocessEmptyRows);
630673 APPLY_ACTION (PreprocessScaling);
631674 APPLY_ACTION (PreprocessFormulation);
675+ APPLY_ACTION (PreprocessFreeVars);
632676}
633677void Preprocessor::undo (PreprocessorPoint& point, const Model& model,
634678 const Iterate& it) const {
0 commit comments