This file is indexed.

/usr/include/qsopt_ex/exact.h is in libqsopt-ex-dev 2.5.10.3-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/* ========================================================================= */
/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
 * and algorithms commons in solving MIP's
 *
 * Copyright (C) 2005 Daniel Espinoza.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * */
/* ========================================================================= */
#ifndef __EXACT_H__
#define __EXACT_H__

#include <gmp.h>

#include "basicdefs.h"
#include "eg_io.h"
#include "eg_lpnum.h"
#include "eg_lpnum.dbl.h"
#include "eg_lpnum.mpq.h"
#include "eg_lpnum.mpf.h"
#include "lpdata_dbl.h"
#include "lpdata_mpq.h"
#include "lpdata_mpf.h"
#include "qsopt_mpf.h" /* mpf_QSset_precision */
#include "qstruct_dbl.h"
#include "qstruct_mpq.h"
#include "qstruct_mpf.h"

/* ========================================================================= */
/** @defgroup Esolver Esolver
 * Here we define an interface to solve LP's (#QSexact_solver) and MIP's 
 * exactly. 
 * @par History:
 * Revision 0.1
 * - 2005-11-14
 * 						- Fix handling of infeasibility testing, the problem is that
 * 						sometimes, the QSget_infeas_array only work after calling primal
 * 						simplex, so, if we are doing dual, ans finish with infeasibility
 * 						status, the call will fail, the fix is to call primal simples on
 * 						those cases before calling the infeasibility proof.
 * - 2005-10-05
 * 						- If one of the floating point approximations fail, keep going
 * 						to the next floating point approximation. A floating point
 * 						approximation may fail because the basis is singular within the
 * 						used precision.
 * - 2005-09-29
 * 						- If the plain double approximation return unbounded we re-try
 * 						in extended precision, but when the extended precision LP solver
 * 						return with QS_LP_UNBOUNDED status, we just give-up and return
 * 						QS_LP_UNBOUNDED status.
 * - 2005-08-17
 * 						- Improve reliability of optimality test.
 * - 2005-07-07
 * 						- Load optimal soplution into the cache.
 * 						- Change the behavior of QSopt, when he wants to re-start simplex,
 * 							we instead increase the precision of the numbers, this behavior
 * 							is managed by DO_NUMER and DO_SINGULAR.
 * - 2005-05-31
 * 						- If the status of the ending call is not optimal, we don't load
 * 						the previous basis, this is because in some examples doing so lead
 * 						to bad behavior of the overall code.
 * - 2005-05-11
 * 						- First definition and implementation
 *
 * */
/** @file
 * @ingroup Esolver */
/** @addtogroup Esolver */
/** @{ */
/* ========================================================================= */

/* ========================================================================= */
/** @brief If enabled, save the last problem proved to be optimal, and its
 * solution. */
#define QSEXACT_SAVE_OPTIMAL 0

/* ========================================================================= */
/** @brief If enabled, save the intermediate problems created by the functions
 * #QScopy_prob_mpq_dbl and #QScopy_prob_mpq_mpf */
#define QSEXACT_SAVE_INT 0

/* ========================================================================= */
/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
 * problem (dbl_QSdata) */
dbl_QSdata *QScopy_prob_mpq_dbl (mpq_QSdata * p,
																 const char *newname);

/* ========================================================================= */
/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
 * problem (dbl_QSdata) */
mpf_QSdata *QScopy_prob_mpq_mpf (mpq_QSdata * p,
																 const char *newname);

/* ========================================================================= */
/** @brief Test if a given primal/dual solution is feasible and has the same
 * objective value.
 * @param p original problem.
 * @param p_sol primal solution candidate.
 * @param d_sol dual solution candidate.
 * @param basis Basis for wich the current primal/dual vector is a solution.
 * @return one if the given primal/dual solution is optimal, zero otherwise. 
 * @par Description:
 * The input problem has the form \f[ \begin{array}{l}\min cx\\
  s.t. \begin{array}{lcl}Ax&=&b\end{array}\\
  l\leq x\leq u\end{array} \f]
 * where some of the bounds can be \f$\infty\f$ or \f$-\infty\f$. Note that from
 * this the dual problem is allways feasible (we treat \f$\infty\f$ as a
 * suitable large number) because it looks like 
 * \f[ \begin{array}{l}\max by + d_uu-d_ll\\
  s.t. \begin{array}{lcl}A^ty-Id_l+Id_u & =& c \end{array}\\
  d_u,d_l\geq0\end{array} \f] thus we just need to check primal 
 * feasibility and complementary slackness (just to be sure we also check that
 * both dual and primal objective values coincide.
 *
 * If the optimality test is true (i.e. the basis and the given solution, wich
 * might have been modified inside the function) then this function store the
 * optimal solution into the cache of the problem.
 *
 * @note We assume that p_sol and d_sol have the right size for the problem. and
 * moreover, we assume that the problem already has the logical variables added
 * in (to transform it into standard form), this allow us to fix somewhat the
 * primal vector solution to try to get an optimality certificate.
 * */
int QSexact_optimal_test (mpq_QSdata * p,
													mpq_t * p_sol,
													mpq_t * d_sol,
													QSbasis * basis);

/* ========================================================================= */
/** @brief Print into a file the optimal solution.
 * @param p original problem.
 * @param out_f file where to write the solution.
 * @return zero on success, non-zero otherwise.
 * */
int QSexact_print_sol (mpq_QSdata * p,
											 EGioFile_t * out_f);

/* ========================================================================= */
/** @brief Check if the given dual vector is a proof of infeasibility for the
 * given exact problem. 
 * @param p pointer to the problem data structure.
 * @param d_sol array of length at least nrows with the suposed proof of
 * infeasibility.
 * @return zero if the given dual vector is indeed a proof of infeasibility for
 * the problem, non zero otherwise.
 * @par Description:
 * Note that for infeasibility, we just need to proof that the problem 
 \f[ \begin{array}{ll} \min & 0\\ s.t. & Ax = b\\ & l\leq x\leq b\\ 
 \end{array} \f]
 * is infeasible, but it's dual is
 \f[ \begin{array}{ll} \max & by - ud_u + ld_l\\ s.t. & A^ty +Id_l - Id_u = 0\\ 
 & d_u,d_l\geq0\\ \end{array} \f]
 * wich is always feasible (provided \f$y\geq0\f$ (set \f$ (y,d_u,d_l)=0\f$), 
 * and thus we just need to check whether the objective value is \f$\neq 0\f$ 
 * and we have a proof of infeasibility for the primal. That's what this 
 * function perform as a test.
 * */
int QSexact_infeasible_test (mpq_QSdata * p,
														 mpq_t * d_sol);

/* ========================================================================= */
/** @brief create a copy of a mpq_t array into a double array.
 * @param array mpq_t array from where we will create the values. */
#define QScopy_array_mpq_dbl(array) ({ \
	mpq_t*__larray = (array);\
	register unsigned __lsz = __EGlpNumArraySize(__larray);\
	double*__lres = dbl_EGlpNumAllocArray(__lsz);\
	while(__lsz--)\
	{\
		if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
			__lres[__lsz] = dbl_ILL_MAXDOUBLE;\
		else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
			__lres[__lsz] = dbl_ILL_MINDOUBLE;\
		else __lres[__lsz] = mpq_get_d(__larray[__lsz]);\
	}\
	__lres;})

/* ========================================================================= */
/** @brief create a copy of a mpq_t array into a mpf_t array.
 * @param array mpq_t array from where we will create the values. */
#define QScopy_array_mpq_mpf(array) ({ \
	mpq_t*__larray = (array);\
	register unsigned __lsz = __EGlpNumArraySize(__larray);\
	mpf_t*__lres = mpf_EGlpNumAllocArray(__lsz);\
	while(__lsz--)\
	{\
		if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
			mpf_set(__lres[__lsz], mpf_ILL_MAXDOUBLE);\
		else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
			mpf_set(__lres[__lsz], mpf_ILL_MINDOUBLE);\
		else mpf_set_q(__lres[__lsz],__larray[__lsz]);\
	}\
	__lres;})

/* ========================================================================= */
/** @brief create a copy of a double array into mpq_t array.
 * @param array original array of double values (note that this array must have
 * been allocated with dbl_EGlpNumAllocArray for this function to work). */
#define QScopy_array_dbl_mpq(array) ({ \
	double*__larray = (array);\
	register unsigned __lsz = __EGlpNumArraySize(__larray);\
	mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
	while(__lsz--)\
	{\
		if(__larray[__lsz] == dbl_ILL_MAXDOUBLE)\
			mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
		else if(__larray[__lsz] == dbl_ILL_MINDOUBLE)\
			mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
		else mpq_EGlpNumSet(__lres[__lsz],__larray[__lsz]);\
	}\
	__lres;})

/* ========================================================================= */
/** @brief create a copy of a mpf_t array into mpq_t array.
 * @param array original array of double values (note that this array must have
 * been allocated with __EGlpNumAllocArray for this function to work). */
#define QScopy_array_mpf_mpq(array) ({ \
	mpf_t*__larray = (array);\
	register unsigned __lsz = __EGlpNumArraySize(__larray);\
	mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
	while(__lsz--)\
	{\
		if(mpf_cmp(__larray[__lsz],mpf_ILL_MAXDOUBLE)==0)\
			mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
		else if(mpf_cmp(__larray[__lsz],mpf_ILL_MINDOUBLE)==0)\
			mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
		mpq_set_f(__lres[__lsz],__larray[__lsz]);\
	}\
	__lres;})

/* ========================================================================= */
/** @brief Write a given row from the LP into the given stream, in exact
 * arithmetic */
void QSexact_write_row (EGioFile_t * out_f,
												mpq_ILLlpdata * lp,
												int row);

/* ========================================================================= */
/** @brief Set the number of bits to use with mpf_t type numbers and change all
 * internal constants as needed. */
#define QSexact_set_precision(precision) mpf_QSset_precision(precision)

#ifndef QS_EXACT_MAX_ITER
/* ========================================================================= */
/** @brief This constant define the maximum number of try's for the exact solver
 * with mpf_t numbers while incrementing the precision */
#define QS_EXACT_MAX_ITER 12
#endif

/* ========================================================================= */
/** @brief test whether given basis is primal and dual feasible in rational arithmetic. 
 * @param p_mpq   the problem data.
 * @param basis   basis to be tested.
 * @param result  where to store whether given basis is primal and dual feasible.
 * @param msg_lvl message level.
 */
int QSexact_basis_optimalstatus(
   mpq_QSdata * p_mpq,
   QSbasis* basis,
   char* result,
   const int msg_lvl
   );

/* ========================================================================= */
/** @brief test whether given basis is dual feasible in rational arithmetic. 
 * @param p_mpq   the problem data.
 * @param basis   basis to be tested.
 * @param result  where to store whether given basis is dual feasible.
 * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
 * @param msg_lvl message level.
 */
int QSexact_basis_dualstatus(
   mpq_QSdata * p_mpq,
   QSbasis* basis,
   char* result,
   mpq_t* dobjval,
   const int msg_lvl
   );

/* ========================================================================= */
/** @brief test whether given basis is dual feasible in rational arithmetic. 
 * if wanted it will first directly test the corresponding approximate dual and primal solution 
 * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
 * before performing the dual feasibility test on the more expensive exact basic solution. 
 * @param p_mpq   the problem data.
 * @param basis   basis to be tested.
 * @param useprestep whether to directly test approximate primal and dual solution first.
 * @param dbl_p_sol  approximate primal solution to use in prestep 
 *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
 * @param dbl_d_sol  approximate dual solution to use in prestep 
 *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
 * @param result  where to store whether given basis is dual feasible.
 * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
 * @param msg_lvl message level.
 */
int QSexact_verify (
   mpq_QSdata * p_mpq,
   QSbasis* basis,
   int useprestep,
   double* dbl_p_sol,
   double* dbl_d_sol,
   char* result,
   mpq_t* dobjval,
   const int msg_lvl
   );

/* ========================================================================= */
/** @brief Given an mpq_QSdata problem, solve it exactly.
 * @param x if not null, we store here the primal solution to the 
 * problem (if it exist).
 * @param y if not null, we store here the dual solution to the
 * problem, 
 * @param p_mpq problem to solve exactly.
 * @param status pointer to the integer where we will return the status
 * of the problem, either optimal, infeasible, or unbounded (we could also 
 * return time out).
 * @param simplexalgo whether to use primal or dual simplex while solving
 * to optimality the problem.
 * @param basis if not null, use the given basis to start the
 * iteration of simplex, and store here the optimal basis (if found).
 * @return zero on success, non-zero otherwise. */
int QSexact_solver (mpq_QSdata * p_mpq,
										mpq_t * const x,
										mpq_t * const y,
										QSbasis * const basis,
										int simplexalgo,
										int *status);

/* ========================================================================= */
/** @brief Initializator for global data, this is needed mainly for defining
 * constants in extended floating point precision and for rational precision.
 * This call should be done BEFORE any mpq_xxx mpf_xxx QSxx EGxx call */
extern void QSexactStart(void);
/* ========================================================================= */
/** @brief This function must be called at the end of the program to free all
 * internal data used in the QSexact structures, once this function is called
 * any operation on EGxxx mpq_xxx mpf_xx QSxx may fail.
 * */
extern void QSexactClear(void);
/* ========================================================================= */
/** @brief indicate if the global data needed for QSexact has been initialized,
 * if zero, initialization routine should be called. This is provided to allow
 * syncronization between libraries */
extern int __QSexact_setup;
/** @} */
/* ========================================================================= */
/* end of exact.h */
#endif