Skip to content

Commit

Permalink
allow original NLPs without free variables
Browse files Browse the repository at this point in the history
- do not catch this case in TNLPAdapter, but let Ipopt initialize all its
  structures and detect optimality/infeasibility in the convergence check
- this way, we get a proper solution report and statistics (ref #417)
- get rid of NO_FREE_VARIABLES_... exceptions
  • Loading branch information
svigerske committed Mar 23, 2021
1 parent 38edd30 commit 49a0d3a
Show file tree
Hide file tree
Showing 5 changed files with 7 additions and 101 deletions.
7 changes: 7 additions & 0 deletions src/Algorithm/IpOptErrorConvCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ ConvergenceCheck::ConvergenceStatus OptimalityErrorConvergenceCheck::CheckConver
return ConvergenceCheck::CONVERGED;
}

if( IpData().curr()->x()->Dim() == 0 )
{
if( constr_viol <= constr_viol_tol_ )
return ConvergenceCheck::CONVERGED;
THROW_EXCEPTION(LOCALLY_INFEASIBLE, "All variables are fixed and constraint violation is above tolerance. The problem is infeasible.");
}

if( acceptable_iter_ > 0 && CurrentIsAcceptable() )
{
IpData().Append_info_string("A");
Expand Down
1 change: 0 additions & 1 deletion src/Algorithm/IpOrigIpoptNLP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ bool OrigIpoptNLP::InitializeStructures(
c_space_->Dim(), x_space_->Dim());
THROW_EXCEPTION(TOO_FEW_DOF, msg);
}
ASSERT_EXCEPTION(x_space_->Dim() > 0, TOO_FEW_DOF, "Too few degrees of freedom (no free variables)!");

// cannot have any null pointers, want zero length vectors
// instead of null - this will later need to be changed for _h;
Expand Down
2 changes: 0 additions & 2 deletions src/Interfaces/IpAlgTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ DECLARE_STD_EXCEPTION(ACCEPTABLE_POINT_REACHED);
DECLARE_STD_EXCEPTION(FEASIBILITY_PROBLEM_SOLVED);
DECLARE_STD_EXCEPTION(INVALID_WARMSTART);
DECLARE_STD_EXCEPTION(INTERNAL_ABORT);
DECLARE_STD_EXCEPTION(NO_FREE_VARIABLES_BUT_FEASIBLE);
DECLARE_STD_EXCEPTION(NO_FREE_VARIABLES_AND_INFEASIBLE);
DECLARE_STD_EXCEPTION(INCONSISTENT_BOUNDS);
/** Exception FAILED_INITIALIZATION for problem during
* initialization of a strategy object (or other problems).
Expand Down
16 changes: 0 additions & 16 deletions src/Interfaces/IpIpoptApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,22 +1131,6 @@ ApplicationReturnStatus IpoptApplication::call_optimize()
retValue = Invalid_Option;
status = INVALID_OPTION;
}
catch( NO_FREE_VARIABLES_BUT_FEASIBLE& exc )
{
exc.ReportException(*jnlst_, J_MOREDETAILED);
jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Optimal Solution Found.\n");
retValue = Solve_Succeeded;
status = SUCCESS;
skip_finalize_solution_call = true; /* has already been called by TNLPAdapter (and we don't know the correct primal solution) */
}
catch( NO_FREE_VARIABLES_AND_INFEASIBLE& exc )
{
exc.ReportException(*jnlst_, J_MOREDETAILED);
jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Problem has only fixed variables and constraints are infeasible.\n");
retValue = Infeasible_Problem_Detected;
status = LOCAL_INFEASIBILITY;
skip_finalize_solution_call = true; /* has already been called by TNLPAdapter (and we don't know the correct primal solution) */
}
catch( INCONSISTENT_BOUNDS& exc )
{
exc.ReportException(*jnlst_, J_MOREDETAILED);
Expand Down
82 changes: 0 additions & 82 deletions src/Interfaces/IpTNLPAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,88 +605,6 @@ bool TNLPAdapter::GetSpaces(
}
} // while (!done)

if( n_x_var == 0 )
{
// Check of all constraints are satisfied:
for( Index i = 0; i < n_full_x_; i++ )
{
DBG_ASSERT(x_l[i] == x_u[i]);
full_x_[i] = x_l[i];
}
bool retval = tnlp_->eval_g(n_full_x_, full_x_, true, n_full_g_, full_g_);
ASSERT_EXCEPTION(retval, IpoptNLP::Eval_Error,
"All variables are fixed, but constraints cannot be evaluated at fixed point.");
Number max_viol = 0.;
for( Index i = 0; i < n_full_g_; i++ )
{
//printf("%d %23.16e %23.16e %23.16e\n",i,full_g_[i], g_l[i], g_u[i]);
max_viol = Max(max_viol, full_g_[i] - g_u[i], g_l[i] - full_g_[i]);
}

SolverReturn status;
if( max_viol <= tol_ ) //ToDo: base also on (acceptable) (constraint violation) tolerance
{
status = SUCCESS;
}
else
{
status = LOCAL_INFEASIBILITY;
}

Number obj_value;
retval = tnlp_->eval_f(n_full_x_, full_x_, false, obj_value);
ASSERT_EXCEPTION(retval, IpoptNLP::Eval_Error,
"All variables are fixed, but objective cannot be evaluated at fixed point.");
// Call finalize_solution so that user has required information
Number* full_z_L = new Number[n_full_x_];
Number* full_z_U = new Number[n_full_x_];
Number* full_lambda = new Number[n_full_g_];
// For now, we return zeros as multipliers... (ToDo?)
const Number zero = 0.;
IpBlasCopy(n_full_x_, &zero, 0, full_z_L, 1);
IpBlasCopy(n_full_x_, &zero, 0, full_z_U, 1);
IpBlasCopy(n_full_g_, &zero, 0, full_lambda, 1);
tnlp_->finalize_solution(status, n_full_x_, full_x_, full_z_L, full_z_U, n_full_g_, full_g_, full_lambda,
obj_value, NULL, NULL);
delete[] full_z_L;
delete[] full_z_U;
delete[] full_lambda;

// Free memory
delete[] x_not_fixed_map;
delete[] x_l_map;
delete[] x_u_map;
delete[] c_map;
delete[] d_map;
delete[] d_l_map;
delete[] d_u_map;
delete[] x_l;
delete[] x_u;
delete[] g_l;
delete[] g_u;

// NOTE: we have passed the primal solution to the user, but not to Ipopt
// that is, Ipopt's data object still holds none or another solution
// However, since IpoptApplication will not call finalize_solution with this point if
// it gets a NO_FREE_VARIABLES_* exception, this should be good enough.
char string[128];
Snprintf(string, 127, "All variables are fixed, and constraint violation is %e", max_viol);
if( status == SUCCESS )
{
jnlst_->Printf(J_WARNING, J_INITIALIZATION,
"All variables are fixed and constraint violation %e\n is below tolerance %e. Declaring success.\n",
max_viol, tol_);
THROW_EXCEPTION(NO_FREE_VARIABLES_BUT_FEASIBLE, string);
}
else
{
jnlst_->Printf(J_WARNING, J_INITIALIZATION,
"All variables are fixed and constraint violation %e\n is above tolerance %e. Declaring that problem is infeasible.\n",
max_viol, tol_);
THROW_EXCEPTION(NO_FREE_VARIABLES_AND_INFEASIBLE, string);
}
}

// If requested, check if there are linearly dependent equality
// constraints
if( n_c > 0 && IsValid(dependency_detector_) )
Expand Down

0 comments on commit 49a0d3a

Please sign in to comment.