1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the class library */ 4 /* SoPlex --- the Sequential object-oriented simPlex. */ 5 /* */ 6 /* Copyright (c) 1996-2023 Zuse Institute Berlin (ZIB) */ 7 /* */ 8 /* Licensed under the Apache License, Version 2.0 (the "License"); */ 9 /* you may not use this file except in compliance with the License. */ 10 /* You may obtain a copy of the License at */ 11 /* */ 12 /* http://www.apache.org/licenses/LICENSE-2.0 */ 13 /* */ 14 /* Unless required by applicable law or agreed to in writing, software */ 15 /* distributed under the License is distributed on an "AS IS" BASIS, */ 16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ 17 /* See the License for the specific language governing permissions and */ 18 /* limitations under the License. */ 19 /* */ 20 /* You should have received a copy of the Apache-2.0 license */ 21 /* along with SoPlex; see the file LICENSE. If not email to soplex@zib.de. */ 22 /* */ 23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 24 25 /**@file validation.hpp 26 * @brief Validation object for soplex solutions 27 */ 28 29 namespace soplex 30 { 31 32 template <class R> 33 bool Validation<R>::updateExternalSolution(const std::string& solution) 34 { 35 validate = true; 36 validatesolution = solution; 37 38 if(solution == "+infinity") 39 { 40 return true; 41 } 42 else if(solution == "-infinity") 43 { 44 return true; 45 } 46 else 47 { 48 char* tailptr; 49 strtod(solution.c_str(), &tailptr); 50 51 if(*tailptr) 52 { 53 //conversion failed because the input wasn't a number 54 return false; 55 } 56 } 57 58 return true; 59 } 60 61 62 /// updates the tolerance used for validation 63 template <class R> 64 bool Validation<R>::updateValidationTolerance(const std::string& tolerance) 65 { 66 char* tailptr; 67 validatetolerance = strtod(tolerance.c_str(), &tailptr); 68 69 if(*tailptr) 70 { 71 //conversion failed because the input wasn't a number 72 return false; 73 } 74 75 return true; 76 } 77 78 template <class R> 79 void Validation<R>::validateSolveReal(SoPlexBase<R>& soplex) 80 { 81 bool passedValidation = true; 82 std::string reason = ""; 83 R objViolation = 0.0; 84 R maxBoundViolation = 0.0; 85 R maxRowViolation = 0.0; 86 R maxRedCostViolation = 0.0; 87 R maxDualViolation = 0.0; 88 R sumBoundViolation = 0.0; 89 R sumRowViolation = 0.0; 90 R sumRedCostViolation = 0.0; 91 R sumDualViolation = 0.0; 92 R sol; 93 94 std::ostream& os = soplex.spxout.getStream(SPxOut::INFO1); 95 96 if(validatesolution == "+infinity") 97 { 98 sol = soplex.realParam(SoPlexBase<R>::INFTY); 99 } 100 else if(validatesolution == "-infinity") 101 { 102 sol = -soplex.realParam(SoPlexBase<R>::INFTY); 103 } 104 else 105 { 106 sol = atof(validatesolution.c_str()); 107 } 108 109 objViolation = spxAbs(sol - soplex.objValueReal()); 110 111 // skip check in case presolving detected infeasibility/unboundedness 112 if(SPxSolverBase<R>::INForUNBD == soplex.status() && 113 (sol == soplex.realParam(SoPlexBase<R>::INFTY) 114 || sol == -soplex.realParam(SoPlexBase<R>::INFTY))) 115 objViolation = 0.0; 116 117 if(! EQ(objViolation, R(0.0), validatetolerance)) 118 { 119 passedValidation = false; 120 reason += "Objective Violation; "; 121 } 122 123 if(SPxSolverBase<R>::OPTIMAL == soplex.status()) 124 { 125 soplex.getBoundViolation(maxBoundViolation, sumBoundViolation); 126 soplex.getRowViolation(maxRowViolation, sumRowViolation); 127 soplex.getRedCostViolation(maxRedCostViolation, sumRedCostViolation); 128 soplex.getDualViolation(maxDualViolation, sumDualViolation); 129 130 if(! LE(maxBoundViolation, validatetolerance, soplex.tolerances()->epsilon())) 131 { 132 passedValidation = false; 133 reason += "Bound Violation; "; 134 } 135 136 if(! LE(maxRowViolation, validatetolerance, soplex.tolerances()->epsilon())) 137 { 138 passedValidation = false; 139 reason += "Row Violation; "; 140 } 141 142 if(! LE(maxRedCostViolation, validatetolerance, soplex.tolerances()->epsilon())) 143 { 144 passedValidation = false; 145 reason += "Reduced Cost Violation; "; 146 } 147 148 if(! LE(maxDualViolation, validatetolerance, soplex.tolerances()->epsilon())) 149 { 150 passedValidation = false; 151 reason += "Dual Violation; "; 152 } 153 } 154 155 os << "\n"; 156 os << "Validation :"; 157 158 if(passedValidation) 159 os << " Success\n"; 160 else 161 { 162 reason[reason.length() - 2] = ']'; 163 os << " Fail [" + reason + "\n"; 164 } 165 166 os << " Objective : " << std::scientific << std::setprecision( 167 8) << objViolation << std::fixed << "\n"; 168 os << " Bound : " << std::scientific << std::setprecision( 169 8) << maxBoundViolation << std::fixed << "\n"; 170 os << " Row : " << std::scientific << std::setprecision( 171 8) << maxRowViolation << std::fixed << "\n"; 172 os << " Reduced Cost : " << std::scientific << std::setprecision( 173 8) << maxRedCostViolation << std::fixed << "\n"; 174 os << " Dual : " << std::scientific << std::setprecision( 175 8) << maxDualViolation << std::fixed << "\n"; 176 } 177 178 } // namespace soplex 179