-
Notifications
You must be signed in to change notification settings - Fork 0
/
boxconstr_lbfgspp_interface.cpp
132 lines (119 loc) · 3.7 KB
/
boxconstr_lbfgspp_interface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (C) 2023 Yixuan Qiu <yixuan.qiu@cos.name>
// Under MIT license
#include "interface.h"
#include <LBFGSB.h>
using namespace LBFGSpp;
void boxconstr_lbfgspp_stat(CUTEstStat& stat, bool verbose)
{
using Vector = Eigen::Matrix<doublereal, Eigen::Dynamic, 1>;
// Open problem description file OUTSDIF.d
const char fname[] = "OUTSDIF.d";
// FORTRAN unit number for OUTSDIF.d
integer funit = 42;
// Exit flag from OPEN and CLOSE
integer ierr = 0;
FORTRAN_open(&funit, fname, &ierr);
if(ierr)
{
stat.flag = 2;
stat.msg = "Error opening file OUTSDIF.d.";
return;
}
// Determine problem size
// Exit flag from CUTEst tools
integer status;
// Number of variables
integer CUTEst_nvar;
// Number of general constraints
integer CUTEst_nconstr;
CUTEST_cdimen(&status, &funit, &CUTEst_nvar, &CUTEst_nconstr);
if(status)
{
stat.flag = 2;
stat.msg = "Error getting problem dimension.";
return;
}
if(CUTEst_nconstr > 0)
{
stat.flag = 2;
stat.msg = "Problem contains general constrints.";
return;
}
if(verbose)
std::cout << "nvar = " << CUTEst_nvar << std::endl;
// Reserve memory for variables, bounds, and multipliers,
// and call appropriate initialization routine for CUTEst
Vector x(CUTEst_nvar);
Vector lb(CUTEst_nvar);
Vector ub(CUTEst_nvar);
// FORTRAN unit number for error output
integer iout = 6;
// FORTRAN unit internal input/output
integer io_buffer = 11;
CUTEST_usetup(&status, &funit, &iout, &io_buffer,
&CUTEst_nvar, x.data(), lb.data(), ub.data());
if(status)
{
stat.flag = 2;
stat.msg = "Error setting up problem.";
CUTEST_uterminate(&status);
return;
}
if(verbose)
{
std::cout << "x0 = " << x.transpose().head(10) << " ... " << x.transpose().tail(10) << std::endl;
std::cout << "lb = " << lb.transpose().head(10) << " ... " << lb.transpose().tail(10) << std::endl;
std::cout << "ub = " << ub.transpose().head(10) << " ... " << ub.transpose().tail(10) << std::endl << std::endl;
}
// Problem name
char prob_name[16];
std::fill(prob_name, prob_name + 16, 0);
CUTEST_probname(&status, prob_name);
if(status)
{
stat.flag = 2;
stat.msg = "Error getting problem name.";
CUTEST_uterminate(&status);
return;
}
// Set up LBFGS++ parameters
LBFGSBParam<doublereal> param;
param.m = 6;
param.max_iterations = 10000;
param.epsilon = 1e-5;
param.epsilon_rel = 0.0;
param.past = 1;
// param.delta = 0.0;
param.delta = 1e7 * std::numeric_limits<doublereal>::epsilon();
param.max_submin = 0;
param.max_linesearch = 100;
// Objective function
CUTEstProblem fun(CUTEst_nvar);
doublereal fx;
// Solver
LBFGSBSolver<doublereal> solver(param);
int niter;
try {
niter = solver.minimize(fun, x, fx, lb, ub);
} catch (std::exception& e) {
stat.prob = std::string(prob_name);
stat.nvar = CUTEst_nvar;
stat.flag = 1;
stat.msg = e.what();
CUTEST_uterminate(&status);
return;
}
doublereal calls[4], time[2];
CUTEST_ureport(&status, calls, time);
if(verbose)
std::cout << "x = " << x.transpose().head(5) << " ... " << x.transpose().tail(5) << std::endl << std::endl;
stat.prob = std::string(prob_name);
stat.nvar = CUTEst_nvar;
stat.niter = niter;
stat.nfun = calls[0];
stat.objval = fx;
stat.proj_grad = solver.final_grad_norm();
stat.setup_time = time[0];
stat.solve_time = time[1];
CUTEST_uterminate(&status);
}