@@ -1706,15 +1706,20 @@ bool isBasisRightSize(const HighsLp& lp, const HighsBasis& basis) {
17061706 basis.row_status .size () == static_cast <size_t >(lp.num_row_ );
17071707}
17081708
1709- void reportLpKktFailures (const HighsLp& lp, const HighsOptions& options,
1710- const HighsInfo& info, const std::string& message) {
1709+ bool reportKktFailures (const HighsLp& lp, const HighsOptions& options,
1710+ const HighsInfo& info, const std::string& message) {
17111711 const HighsLogOptions& log_options = options.log_options ;
1712+ double mip_feasibility_tolerance = options.mip_feasibility_tolerance ;
17121713 double primal_feasibility_tolerance = options.primal_feasibility_tolerance ;
17131714 double dual_feasibility_tolerance = options.dual_feasibility_tolerance ;
17141715 double primal_residual_tolerance = options.primal_residual_tolerance ;
17151716 double dual_residual_tolerance = options.dual_residual_tolerance ;
17161717 double optimality_tolerance = options.optimality_tolerance ;
1717- if (options.kkt_tolerance != kDefaultKktTolerance ) {
1718+ const bool is_mip = lp.isMip ();
1719+ if (is_mip) {
1720+ primal_feasibility_tolerance = mip_feasibility_tolerance;
1721+ } else if (options.kkt_tolerance != kDefaultKktTolerance ) {
1722+ mip_feasibility_tolerance = options.kkt_tolerance ;
17181723 primal_feasibility_tolerance = options.kkt_tolerance ;
17191724 dual_feasibility_tolerance = options.kkt_tolerance ;
17201725 primal_residual_tolerance = options.kkt_tolerance ;
@@ -1723,34 +1728,44 @@ void reportLpKktFailures(const HighsLp& lp, const HighsOptions& options,
17231728 }
17241729
17251730 const bool force_report = false ;
1731+ const bool complementarity_error =
1732+ !is_mip && info.primal_dual_objective_error > optimality_tolerance;
1733+ const bool integrality_error =
1734+ is_mip && info.max_integrality_violation >= mip_feasibility_tolerance;
17261735 const bool has_kkt_failures =
1727- info.num_primal_infeasibilities > 0 ||
1736+ integrality_error || info.num_primal_infeasibilities > 0 ||
17281737 info.num_dual_infeasibilities > 0 ||
17291738 info.num_primal_residual_errors > 0 ||
1730- info.num_dual_residual_errors > 0 ||
1731- info.primal_dual_objective_error > optimality_tolerance;
1732- if (!has_kkt_failures && !force_report) return ;
1739+ info.num_dual_residual_errors > 0 || complementarity_error;
1740+ if (!has_kkt_failures && !force_report) return has_kkt_failures;
17331741
17341742 HighsLogType log_type =
17351743 has_kkt_failures ? HighsLogType::kWarning : HighsLogType::kInfo ;
17361744
1737- highsLogUser (log_options, log_type, " LP solution KKT conditions%s%s\n " ,
1745+ highsLogUser (log_options, log_type, " Solution optimality conditions%s%s\n " ,
17381746 message == " " ? " " : " : " , message == " " ? " " : message.c_str ());
1739-
1740- highsLogUser (
1741- log_options, HighsLogType::kInfo ,
1742- " num/max %6d / %8.3g (relative %6d / %8.3g) primal "
1743- " infeasibilities (tolerance = %4.0e)\n " ,
1744- int (info.num_primal_infeasibilities ), info.max_primal_infeasibility ,
1745- int (info.num_relative_primal_infeasibilities ),
1746- info.max_relative_primal_infeasibility , primal_feasibility_tolerance);
1747- highsLogUser (log_options, HighsLogType::kInfo ,
1748- " num/max %6d / %8.3g (relative %6d / %8.3g) dual "
1749- " infeasibilities (tolerance = %4.0e)\n " ,
1750- int (info.num_dual_infeasibilities ), info.max_dual_infeasibility ,
1751- int (info.num_relative_dual_infeasibilities ),
1752- info.max_relative_dual_infeasibility ,
1753- dual_feasibility_tolerance);
1747+ if (is_mip && info.max_integrality_violation >= 0 )
1748+ highsLogUser (log_options, HighsLogType::kInfo ,
1749+ " max %8.3g "
1750+ " integrality violations"
1751+ " (tolerance = %4.0e)\n " ,
1752+ info.max_integrality_violation , mip_feasibility_tolerance);
1753+ if (info.num_primal_infeasibilities >= 0 )
1754+ highsLogUser (
1755+ log_options, HighsLogType::kInfo ,
1756+ " num/max %6d / %8.3g (relative %6d / %8.3g) primal "
1757+ " infeasibilities (tolerance = %4.0e)\n " ,
1758+ int (info.num_primal_infeasibilities ), info.max_primal_infeasibility ,
1759+ int (info.num_relative_primal_infeasibilities ),
1760+ info.max_relative_primal_infeasibility , primal_feasibility_tolerance);
1761+ if (info.num_dual_infeasibilities >= 0 )
1762+ highsLogUser (
1763+ log_options, HighsLogType::kInfo ,
1764+ " num/max %6d / %8.3g (relative %6d / %8.3g) dual "
1765+ " infeasibilities (tolerance = %4.0e)\n " ,
1766+ int (info.num_dual_infeasibilities ), info.max_dual_infeasibility ,
1767+ int (info.num_relative_dual_infeasibilities ),
1768+ info.max_relative_dual_infeasibility , dual_feasibility_tolerance);
17541769 if (info.num_primal_residual_errors >= 0 )
17551770 highsLogUser (
17561771 log_options, HighsLogType::kInfo ,
@@ -1778,9 +1793,10 @@ void reportLpKktFailures(const HighsLp& lp, const HighsOptions& options,
17781793 info.primal_dual_objective_error , optimality_tolerance);
17791794 }
17801795 if (printf_kkt) {
1781- printf (" grepLpKktFailures ,%s,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%g\n " ,
1796+ printf (" grepKktFailures ,%s,%s,%s,%g ,%d,%d,%d,%d,%d,%d,%d,%d,%g\n " ,
17821797 options.solver .c_str (), lp.model_name_ .c_str (),
1783- lp.origin_name_ .c_str (), int (info.num_primal_infeasibilities ),
1798+ lp.origin_name_ .c_str (), info.max_integrality_violation ,
1799+ int (info.num_primal_infeasibilities ),
17841800 int (info.num_dual_infeasibilities ),
17851801 int (info.num_primal_residual_errors ),
17861802 int (info.num_dual_residual_errors ),
@@ -1790,6 +1806,7 @@ void reportLpKktFailures(const HighsLp& lp, const HighsOptions& options,
17901806 int (info.num_relative_dual_residual_errors ),
17911807 info.primal_dual_objective_error );
17921808 }
1809+ return has_kkt_failures;
17931810}
17941811
17951812bool HighsSolution::hasUndefined () const {
0 commit comments