| 148 | } |
| 149 | |
| 150 | void PythonModel::evaluate_lagrangian_hessian(const Vector<double>& x, double objective_multiplier, const Vector<double>& multipliers, |
| 151 | double* hessian_values) const { |
| 152 | if (this->user_model.lagrangian_hessian.has_value()) { |
| 153 | objective_multiplier *= this->optimization_sense; |
| 154 | // if the model has a different sign convention for the Lagrangian than Uno, flip the signs of the multipliers |
| 155 | if (this->user_model.lagrangian_sign_convention == UNO_MULTIPLIER_POSITIVE) { |
| 156 | const_cast<Vector<double>&>(multipliers).scale(-1.); |
| 157 | } |
| 158 | const auto x_py = to_const_array(x.data(), this->number_variables); |
| 159 | const auto multipliers_py = to_const_array(multipliers.data(), this->number_constraints); |
| 160 | auto hessian_py = to_array(hessian_values, this->number_hessian_nonzeros()); |
| 161 | |
| 162 | // evaluate Lagrangian Hessian |
| 163 | try { |
| 164 | (*this->user_model.lagrangian_hessian)(x_py, objective_multiplier, multipliers_py, hessian_py); |
| 165 | ++this->number_model_evaluations.hessian; |
| 166 | } |
| 167 | catch (const std::exception&) { |
| 168 | // flip the signs of the multipliers back |
| 169 | if (this->user_model.lagrangian_sign_convention == UNO_MULTIPLIER_POSITIVE) { |
| 170 | const_cast<Vector<double>&>(multipliers).scale(-1.); |
| 171 | } |
| 172 | throw HessianEvaluationError(); |
| 173 | } |
| 174 | // flip the signs of the multipliers back |
| 175 | if (this->user_model.lagrangian_sign_convention == UNO_MULTIPLIER_POSITIVE) { |
| 176 | const_cast<Vector<double>&>(multipliers).scale(-1.); |
| 177 | } |
| 178 | } |
| 179 | else { |
| 180 | throw std::runtime_error("evaluate_lagrangian_hessian not implemented"); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | void PythonModel::compute_jacobian_vector_product(const double* x, const double* vector, double* result) const { |
| 185 | if (this->user_model.jacobian_operator.has_value()) { |
nothing calls this directly
no test coverage detected