Add graph references

This commit is contained in:
Abdelrahman Said
2026-06-28 13:49:01 +01:00
parent 0a9807e448
commit a11edf0c53
2578 changed files with 868045 additions and 0 deletions
+643
View File
@@ -0,0 +1,643 @@
/* npp.h (LP/MIP preprocessor) */
/***********************************************************************
* This code is part of GLPK (GNU Linear Programming Kit).
* Copyright (C) 2009-2017 Free Software Foundation, Inc.
* Written by Andrew Makhorin <mao@gnu.org>.
*
* GLPK is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPK 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 General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#ifndef NPP_H
#define NPP_H
#include "prob.h"
#if 0 /* 20/XI-2017 */
typedef struct NPP NPP;
#else
typedef struct glp_prep NPP;
#endif
typedef struct NPPROW NPPROW;
typedef struct NPPCOL NPPCOL;
typedef struct NPPAIJ NPPAIJ;
typedef struct NPPTSE NPPTSE;
typedef struct NPPLFE NPPLFE;
#if 0 /* 20/XI-2017 */
struct NPP
#else
struct glp_prep
#endif
{ /* LP/MIP preprocessor workspace */
/*--------------------------------------------------------------*/
/* original problem segment */
int orig_dir;
/* optimization direction flag:
GLP_MIN - minimization
GLP_MAX - maximization */
int orig_m;
/* number of rows */
int orig_n;
/* number of columns */
int orig_nnz;
/* number of non-zero constraint coefficients */
/*--------------------------------------------------------------*/
/* transformed problem segment (always minimization) */
DMP *pool;
/* memory pool to store problem components */
char *name;
/* problem name (1 to 255 chars); NULL means no name is assigned
to the problem */
char *obj;
/* objective function name (1 to 255 chars); NULL means no name
is assigned to the objective function */
double c0;
/* constant term of the objective function */
int nrows;
/* number of rows introduced into the problem; this count
increases by one every time a new row is added and never
decreases; thus, actual number of rows may be less than nrows
due to row deletions */
int ncols;
/* number of columns introduced into the problem; this count
increases by one every time a new column is added and never
decreases; thus, actual number of column may be less than
ncols due to column deletions */
NPPROW *r_head;
/* pointer to the beginning of the row list */
NPPROW *r_tail;
/* pointer to the end of the row list */
NPPCOL *c_head;
/* pointer to the beginning of the column list */
NPPCOL *c_tail;
/* pointer to the end of the column list */
/*--------------------------------------------------------------*/
/* transformation history */
DMP *stack;
/* memory pool to store transformation entries */
NPPTSE *top;
/* pointer to most recent transformation entry */
#if 0 /* 16/XII-2009 */
int count[1+25];
/* transformation statistics */
#endif
/*--------------------------------------------------------------*/
/* resultant (preprocessed) problem segment */
int m;
/* number of rows */
int n;
/* number of columns */
int nnz;
/* number of non-zero constraint coefficients */
int *row_ref; /* int row_ref[1+m]; */
/* row_ref[i], 1 <= i <= m, is the reference number assigned to
a row, which is i-th row of the resultant problem */
int *col_ref; /* int col_ref[1+n]; */
/* col_ref[j], 1 <= j <= n, is the reference number assigned to
a column, which is j-th column of the resultant problem */
/*--------------------------------------------------------------*/
/* recovered solution segment */
int sol;
/* solution indicator:
GLP_SOL - basic solution
GLP_IPT - interior-point solution
GLP_MIP - mixed integer solution */
int scaling;
/* scaling option:
GLP_OFF - scaling is disabled
GLP_ON - scaling is enabled */
int p_stat;
/* status of primal basic solution:
GLP_UNDEF - primal solution is undefined
GLP_FEAS - primal solution is feasible
GLP_INFEAS - primal solution is infeasible
GLP_NOFEAS - no primal feasible solution exists */
int d_stat;
/* status of dual basic solution:
GLP_UNDEF - dual solution is undefined
GLP_FEAS - dual solution is feasible
GLP_INFEAS - dual solution is infeasible
GLP_NOFEAS - no dual feasible solution exists */
int t_stat;
/* status of interior-point solution:
GLP_UNDEF - interior solution is undefined
GLP_OPT - interior solution is optimal */
int i_stat;
/* status of mixed integer solution:
GLP_UNDEF - integer solution is undefined
GLP_OPT - integer solution is optimal
GLP_FEAS - integer solution is feasible
GLP_NOFEAS - no integer solution exists */
char *r_stat; /* char r_stat[1+nrows]; */
/* r_stat[i], 1 <= i <= nrows, is status of i-th row:
GLP_BS - inactive constraint
GLP_NL - active constraint on lower bound
GLP_NU - active constraint on upper bound
GLP_NF - active free row
GLP_NS - active equality constraint */
char *c_stat; /* char c_stat[1+nrows]; */
/* c_stat[j], 1 <= j <= nrows, is status of j-th column:
GLP_BS - basic variable
GLP_NL - non-basic variable on lower bound
GLP_NU - non-basic variable on upper bound
GLP_NF - non-basic free variable
GLP_NS - non-basic fixed variable */
double *r_pi; /* double r_pi[1+nrows]; */
/* r_pi[i], 1 <= i <= nrows, is Lagrange multiplier (dual value)
for i-th row (constraint) */
double *c_value; /* double c_value[1+ncols]; */
/* c_value[j], 1 <= j <= ncols, is primal value of j-th column
(structural variable) */
};
struct NPPROW
{ /* row (constraint) */
int i;
/* reference number assigned to the row, 1 <= i <= nrows */
char *name;
/* row name (1 to 255 chars); NULL means no name is assigned to
the row */
double lb;
/* lower bound; -DBL_MAX means the row has no lower bound */
double ub;
/* upper bound; +DBL_MAX means the row has no upper bound */
NPPAIJ *ptr;
/* pointer to the linked list of constraint coefficients */
int temp;
/* working field used by preprocessor routines */
NPPROW *prev;
/* pointer to previous row in the row list */
NPPROW *next;
/* pointer to next row in the row list */
};
struct NPPCOL
{ /* column (variable) */
int j;
/* reference number assigned to the column, 1 <= j <= ncols */
char *name;
/* column name (1 to 255 chars); NULL means no name is assigned
to the column */
char is_int;
/* 0 means continuous variable; 1 means integer variable */
double lb;
/* lower bound; -DBL_MAX means the column has no lower bound */
double ub;
/* upper bound; +DBL_MAX means the column has no upper bound */
double coef;
/* objective coefficient */
NPPAIJ *ptr;
/* pointer to the linked list of constraint coefficients */
int temp;
/* working field used by preprocessor routines */
#if 1 /* 28/XII-2009 */
union
{ double ll;
/* implied column lower bound */
int pos;
/* vertex ordinal number corresponding to this binary column
in the conflict graph (0, if the vertex does not exist) */
} ll;
union
{ double uu;
/* implied column upper bound */
int neg;
/* vertex ordinal number corresponding to complement of this
binary column in the conflict graph (0, if the vertex does
not exist) */
} uu;
#endif
NPPCOL *prev;
/* pointer to previous column in the column list */
NPPCOL *next;
/* pointer to next column in the column list */
};
struct NPPAIJ
{ /* constraint coefficient */
NPPROW *row;
/* pointer to corresponding row */
NPPCOL *col;
/* pointer to corresponding column */
double val;
/* (non-zero) coefficient value */
NPPAIJ *r_prev;
/* pointer to previous coefficient in the same row */
NPPAIJ *r_next;
/* pointer to next coefficient in the same row */
NPPAIJ *c_prev;
/* pointer to previous coefficient in the same column */
NPPAIJ *c_next;
/* pointer to next coefficient in the same column */
};
struct NPPTSE
{ /* transformation stack entry */
int (*func)(NPP *npp, void *info);
/* pointer to routine performing back transformation */
void *info;
/* pointer to specific info (depends on the transformation) */
NPPTSE *link;
/* pointer to another entry created *before* this entry */
};
struct NPPLFE
{ /* linear form element */
int ref;
/* row/column reference number */
double val;
/* (non-zero) coefficient value */
NPPLFE *next;
/* pointer to another element */
};
#define npp_create_wksp _glp_npp_create_wksp
NPP *npp_create_wksp(void);
/* create LP/MIP preprocessor workspace */
#define npp_insert_row _glp_npp_insert_row
void npp_insert_row(NPP *npp, NPPROW *row, int where);
/* insert row to the row list */
#define npp_remove_row _glp_npp_remove_row
void npp_remove_row(NPP *npp, NPPROW *row);
/* remove row from the row list */
#define npp_activate_row _glp_npp_activate_row
void npp_activate_row(NPP *npp, NPPROW *row);
/* make row active */
#define npp_deactivate_row _glp_npp_deactivate_row
void npp_deactivate_row(NPP *npp, NPPROW *row);
/* make row inactive */
#define npp_insert_col _glp_npp_insert_col
void npp_insert_col(NPP *npp, NPPCOL *col, int where);
/* insert column to the column list */
#define npp_remove_col _glp_npp_remove_col
void npp_remove_col(NPP *npp, NPPCOL *col);
/* remove column from the column list */
#define npp_activate_col _glp_npp_activate_col
void npp_activate_col(NPP *npp, NPPCOL *col);
/* make column active */
#define npp_deactivate_col _glp_npp_deactivate_col
void npp_deactivate_col(NPP *npp, NPPCOL *col);
/* make column inactive */
#define npp_add_row _glp_npp_add_row
NPPROW *npp_add_row(NPP *npp);
/* add new row to the current problem */
#define npp_add_col _glp_npp_add_col
NPPCOL *npp_add_col(NPP *npp);
/* add new column to the current problem */
#define npp_add_aij _glp_npp_add_aij
NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val);
/* add new element to the constraint matrix */
#define npp_row_nnz _glp_npp_row_nnz
int npp_row_nnz(NPP *npp, NPPROW *row);
/* count number of non-zero coefficients in row */
#define npp_col_nnz _glp_npp_col_nnz
int npp_col_nnz(NPP *npp, NPPCOL *col);
/* count number of non-zero coefficients in column */
#define npp_push_tse _glp_npp_push_tse
void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info),
int size);
/* push new entry to the transformation stack */
#define npp_erase_row _glp_npp_erase_row
void npp_erase_row(NPP *npp, NPPROW *row);
/* erase row content to make it empty */
#define npp_del_row _glp_npp_del_row
void npp_del_row(NPP *npp, NPPROW *row);
/* remove row from the current problem */
#define npp_del_col _glp_npp_del_col
void npp_del_col(NPP *npp, NPPCOL *col);
/* remove column from the current problem */
#define npp_del_aij _glp_npp_del_aij
void npp_del_aij(NPP *npp, NPPAIJ *aij);
/* remove element from the constraint matrix */
#define npp_load_prob _glp_npp_load_prob
void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol,
int scaling);
/* load original problem into the preprocessor workspace */
#define npp_build_prob _glp_npp_build_prob
void npp_build_prob(NPP *npp, glp_prob *prob);
/* build resultant (preprocessed) problem */
#define npp_postprocess _glp_npp_postprocess
void npp_postprocess(NPP *npp, glp_prob *prob);
/* postprocess solution from the resultant problem */
#define npp_unload_sol _glp_npp_unload_sol
void npp_unload_sol(NPP *npp, glp_prob *orig);
/* store solution to the original problem */
#define npp_delete_wksp _glp_npp_delete_wksp
void npp_delete_wksp(NPP *npp);
/* delete LP/MIP preprocessor workspace */
#define npp_error()
#define npp_free_row _glp_npp_free_row
void npp_free_row(NPP *npp, NPPROW *p);
/* process free (unbounded) row */
#define npp_geq_row _glp_npp_geq_row
void npp_geq_row(NPP *npp, NPPROW *p);
/* process row of 'not less than' type */
#define npp_leq_row _glp_npp_leq_row
void npp_leq_row(NPP *npp, NPPROW *p);
/* process row of 'not greater than' type */
#define npp_free_col _glp_npp_free_col
void npp_free_col(NPP *npp, NPPCOL *q);
/* process free (unbounded) column */
#define npp_lbnd_col _glp_npp_lbnd_col
void npp_lbnd_col(NPP *npp, NPPCOL *q);
/* process column with (non-zero) lower bound */
#define npp_ubnd_col _glp_npp_ubnd_col
void npp_ubnd_col(NPP *npp, NPPCOL *q);
/* process column with upper bound */
#define npp_dbnd_col _glp_npp_dbnd_col
void npp_dbnd_col(NPP *npp, NPPCOL *q);
/* process non-negative column with upper bound */
#define npp_fixed_col _glp_npp_fixed_col
void npp_fixed_col(NPP *npp, NPPCOL *q);
/* process fixed column */
#define npp_make_equality _glp_npp_make_equality
int npp_make_equality(NPP *npp, NPPROW *p);
/* process row with almost identical bounds */
#define npp_make_fixed _glp_npp_make_fixed
int npp_make_fixed(NPP *npp, NPPCOL *q);
/* process column with almost identical bounds */
#define npp_empty_row _glp_npp_empty_row
int npp_empty_row(NPP *npp, NPPROW *p);
/* process empty row */
#define npp_empty_col _glp_npp_empty_col
int npp_empty_col(NPP *npp, NPPCOL *q);
/* process empty column */
#define npp_implied_value _glp_npp_implied_value
int npp_implied_value(NPP *npp, NPPCOL *q, double s);
/* process implied column value */
#define npp_eq_singlet _glp_npp_eq_singlet
int npp_eq_singlet(NPP *npp, NPPROW *p);
/* process row singleton (equality constraint) */
#define npp_implied_lower _glp_npp_implied_lower
int npp_implied_lower(NPP *npp, NPPCOL *q, double l);
/* process implied column lower bound */
#define npp_implied_upper _glp_npp_implied_upper
int npp_implied_upper(NPP *npp, NPPCOL *q, double u);
/* process implied upper bound of column */
#define npp_ineq_singlet _glp_npp_ineq_singlet
int npp_ineq_singlet(NPP *npp, NPPROW *p);
/* process row singleton (inequality constraint) */
#define npp_implied_slack _glp_npp_implied_slack
void npp_implied_slack(NPP *npp, NPPCOL *q);
/* process column singleton (implied slack variable) */
#define npp_implied_free _glp_npp_implied_free
int npp_implied_free(NPP *npp, NPPCOL *q);
/* process column singleton (implied free variable) */
#define npp_eq_doublet _glp_npp_eq_doublet
NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p);
/* process row doubleton (equality constraint) */
#define npp_forcing_row _glp_npp_forcing_row
int npp_forcing_row(NPP *npp, NPPROW *p, int at);
/* process forcing row */
#define npp_analyze_row _glp_npp_analyze_row
int npp_analyze_row(NPP *npp, NPPROW *p);
/* perform general row analysis */
#define npp_inactive_bound _glp_npp_inactive_bound
void npp_inactive_bound(NPP *npp, NPPROW *p, int which);
/* remove row lower/upper inactive bound */
#define npp_implied_bounds _glp_npp_implied_bounds
void npp_implied_bounds(NPP *npp, NPPROW *p);
/* determine implied column bounds */
#define npp_binarize_prob _glp_npp_binarize_prob
int npp_binarize_prob(NPP *npp);
/* binarize MIP problem */
#define npp_is_packing _glp_npp_is_packing
int npp_is_packing(NPP *npp, NPPROW *row);
/* test if constraint is packing inequality */
#define npp_hidden_packing _glp_npp_hidden_packing
int npp_hidden_packing(NPP *npp, NPPROW *row);
/* identify hidden packing inequality */
#define npp_implied_packing _glp_npp_implied_packing
int npp_implied_packing(NPP *npp, NPPROW *row, int which,
NPPCOL *var[], char set[]);
/* identify implied packing inequality */
#define npp_is_covering _glp_npp_is_covering
int npp_is_covering(NPP *npp, NPPROW *row);
/* test if constraint is covering inequality */
#define npp_hidden_covering _glp_npp_hidden_covering
int npp_hidden_covering(NPP *npp, NPPROW *row);
/* identify hidden covering inequality */
#define npp_is_partitioning _glp_npp_is_partitioning
int npp_is_partitioning(NPP *npp, NPPROW *row);
/* test if constraint is partitioning equality */
#define npp_reduce_ineq_coef _glp_npp_reduce_ineq_coef
int npp_reduce_ineq_coef(NPP *npp, NPPROW *row);
/* reduce inequality constraint coefficients */
#define npp_clean_prob _glp_npp_clean_prob
void npp_clean_prob(NPP *npp);
/* perform initial LP/MIP processing */
#define npp_process_row _glp_npp_process_row
int npp_process_row(NPP *npp, NPPROW *row, int hard);
/* perform basic row processing */
#define npp_improve_bounds _glp_npp_improve_bounds
int npp_improve_bounds(NPP *npp, NPPROW *row, int flag);
/* improve current column bounds */
#define npp_process_col _glp_npp_process_col
int npp_process_col(NPP *npp, NPPCOL *col);
/* perform basic column processing */
#define npp_process_prob _glp_npp_process_prob
int npp_process_prob(NPP *npp, int hard);
/* perform basic LP/MIP processing */
#define npp_simplex _glp_npp_simplex
int npp_simplex(NPP *npp, const glp_smcp *parm);
/* process LP prior to applying primal/dual simplex method */
#define npp_integer _glp_npp_integer
int npp_integer(NPP *npp, const glp_iocp *parm);
/* process MIP prior to applying branch-and-bound method */
/**********************************************************************/
#define npp_sat_free_row _glp_npp_sat_free_row
void npp_sat_free_row(NPP *npp, NPPROW *p);
/* process free (unbounded) row */
#define npp_sat_fixed_col _glp_npp_sat_fixed_col
int npp_sat_fixed_col(NPP *npp, NPPCOL *q);
/* process fixed column */
#define npp_sat_is_bin_comb _glp_npp_sat_is_bin_comb
int npp_sat_is_bin_comb(NPP *npp, NPPROW *row);
/* test if row is binary combination */
#define npp_sat_num_pos_coef _glp_npp_sat_num_pos_coef
int npp_sat_num_pos_coef(NPP *npp, NPPROW *row);
/* determine number of positive coefficients */
#define npp_sat_num_neg_coef _glp_npp_sat_num_neg_coef
int npp_sat_num_neg_coef(NPP *npp, NPPROW *row);
/* determine number of negative coefficients */
#define npp_sat_is_cover_ineq _glp_npp_sat_is_cover_ineq
int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row);
/* test if row is covering inequality */
#define npp_sat_is_pack_ineq _glp_npp_sat_is_pack_ineq
int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row);
/* test if row is packing inequality */
#define npp_sat_is_partn_eq _glp_npp_sat_is_partn_eq
int npp_sat_is_partn_eq(NPP *npp, NPPROW *row);
/* test if row is partitioning equality */
#define npp_sat_reverse_row _glp_npp_sat_reverse_row
int npp_sat_reverse_row(NPP *npp, NPPROW *row);
/* multiply both sides of row by -1 */
#define npp_sat_split_pack _glp_npp_sat_split_pack
NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nnn);
/* split packing inequality */
#define npp_sat_encode_pack _glp_npp_sat_encode_pack
void npp_sat_encode_pack(NPP *npp, NPPROW *row);
/* encode packing inequality */
typedef struct NPPLIT NPPLIT;
typedef struct NPPLSE NPPLSE;
typedef struct NPPSED NPPSED;
struct NPPLIT
{ /* literal (binary variable or its negation) */
NPPCOL *col;
/* pointer to binary variable; NULL means constant false */
int neg;
/* negation flag:
0 - literal is variable (or constant false)
1 - literal is negation of variable (or constant true) */
};
struct NPPLSE
{ /* literal set element */
NPPLIT lit;
/* literal */
NPPLSE *next;
/* pointer to another element */
};
struct NPPSED
{ /* summation encoding descriptor */
/* this struct describes the equality
x + y + z = s + 2 * c,
which was encoded as CNF and included into the transformed
problem; here x and y are literals, z is either a literal or
constant zero, s and c are binary variables modeling, resp.,
the low and high (carry) sum bits */
NPPLIT x, y, z;
/* literals; if z.col = NULL, z is constant zero */
NPPCOL *s, *c;
/* binary variables modeling the sum bits */
};
#define npp_sat_encode_sum2 _glp_npp_sat_encode_sum2
void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed);
/* encode 2-bit summation */
#define npp_sat_encode_sum3 _glp_npp_sat_encode_sum3
void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed);
/* encode 3-bit summation */
#define npp_sat_encode_sum_ax _glp_npp_sat_encode_sum_ax
int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]);
/* encode linear combination of 0-1 variables */
#define npp_sat_normalize_clause _glp_npp_sat_normalize_clause
int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]);
/* normalize clause */
#define npp_sat_encode_clause _glp_npp_sat_encode_clause
NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]);
/* translate clause to cover inequality */
#define npp_sat_encode_geq _glp_npp_sat_encode_geq
int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs);
/* encode "not less than" constraint */
#define npp_sat_encode_leq _glp_npp_sat_encode_leq
int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs);
/* encode "not greater than" constraint */
#define npp_sat_encode_row _glp_npp_sat_encode_row
int npp_sat_encode_row(NPP *npp, NPPROW *row);
/* encode constraint (row) of general type */
#define npp_sat_encode_prob _glp_npp_sat_encode_prob
int npp_sat_encode_prob(NPP *npp);
/* encode 0-1 feasibility problem */
#endif
/* eof */
+935
View File
@@ -0,0 +1,935 @@
/* npp1.c */
/***********************************************************************
* This code is part of GLPK (GNU Linear Programming Kit).
* Copyright (C) 2009-2017 Free Software Foundation, Inc.
* Written by Andrew Makhorin <mao@gnu.org>.
*
* GLPK is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPK 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 General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "env.h"
#include "npp.h"
NPP *npp_create_wksp(void)
{ /* create LP/MIP preprocessor workspace */
NPP *npp;
npp = xmalloc(sizeof(NPP));
npp->orig_dir = 0;
npp->orig_m = npp->orig_n = npp->orig_nnz = 0;
npp->pool = dmp_create_pool();
npp->name = npp->obj = NULL;
npp->c0 = 0.0;
npp->nrows = npp->ncols = 0;
npp->r_head = npp->r_tail = NULL;
npp->c_head = npp->c_tail = NULL;
npp->stack = dmp_create_pool();
npp->top = NULL;
#if 0 /* 16/XII-2009 */
memset(&npp->count, 0, sizeof(npp->count));
#endif
npp->m = npp->n = npp->nnz = 0;
npp->row_ref = npp->col_ref = NULL;
npp->sol = npp->scaling = 0;
npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0;
npp->r_stat = NULL;
/*npp->r_prim =*/ npp->r_pi = NULL;
npp->c_stat = NULL;
npp->c_value = /*npp->c_dual =*/ NULL;
return npp;
}
void npp_insert_row(NPP *npp, NPPROW *row, int where)
{ /* insert row to the row list */
if (where == 0)
{ /* insert row to the beginning of the row list */
row->prev = NULL;
row->next = npp->r_head;
if (row->next == NULL)
npp->r_tail = row;
else
row->next->prev = row;
npp->r_head = row;
}
else
{ /* insert row to the end of the row list */
row->prev = npp->r_tail;
row->next = NULL;
if (row->prev == NULL)
npp->r_head = row;
else
row->prev->next = row;
npp->r_tail = row;
}
return;
}
void npp_remove_row(NPP *npp, NPPROW *row)
{ /* remove row from the row list */
if (row->prev == NULL)
npp->r_head = row->next;
else
row->prev->next = row->next;
if (row->next == NULL)
npp->r_tail = row->prev;
else
row->next->prev = row->prev;
return;
}
void npp_activate_row(NPP *npp, NPPROW *row)
{ /* make row active */
if (!row->temp)
{ row->temp = 1;
/* move the row to the beginning of the row list */
npp_remove_row(npp, row);
npp_insert_row(npp, row, 0);
}
return;
}
void npp_deactivate_row(NPP *npp, NPPROW *row)
{ /* make row inactive */
if (row->temp)
{ row->temp = 0;
/* move the row to the end of the row list */
npp_remove_row(npp, row);
npp_insert_row(npp, row, 1);
}
return;
}
void npp_insert_col(NPP *npp, NPPCOL *col, int where)
{ /* insert column to the column list */
if (where == 0)
{ /* insert column to the beginning of the column list */
col->prev = NULL;
col->next = npp->c_head;
if (col->next == NULL)
npp->c_tail = col;
else
col->next->prev = col;
npp->c_head = col;
}
else
{ /* insert column to the end of the column list */
col->prev = npp->c_tail;
col->next = NULL;
if (col->prev == NULL)
npp->c_head = col;
else
col->prev->next = col;
npp->c_tail = col;
}
return;
}
void npp_remove_col(NPP *npp, NPPCOL *col)
{ /* remove column from the column list */
if (col->prev == NULL)
npp->c_head = col->next;
else
col->prev->next = col->next;
if (col->next == NULL)
npp->c_tail = col->prev;
else
col->next->prev = col->prev;
return;
}
void npp_activate_col(NPP *npp, NPPCOL *col)
{ /* make column active */
if (!col->temp)
{ col->temp = 1;
/* move the column to the beginning of the column list */
npp_remove_col(npp, col);
npp_insert_col(npp, col, 0);
}
return;
}
void npp_deactivate_col(NPP *npp, NPPCOL *col)
{ /* make column inactive */
if (col->temp)
{ col->temp = 0;
/* move the column to the end of the column list */
npp_remove_col(npp, col);
npp_insert_col(npp, col, 1);
}
return;
}
NPPROW *npp_add_row(NPP *npp)
{ /* add new row to the current problem */
NPPROW *row;
row = dmp_get_atom(npp->pool, sizeof(NPPROW));
row->i = ++(npp->nrows);
row->name = NULL;
row->lb = -DBL_MAX, row->ub = +DBL_MAX;
row->ptr = NULL;
row->temp = 0;
npp_insert_row(npp, row, 1);
return row;
}
NPPCOL *npp_add_col(NPP *npp)
{ /* add new column to the current problem */
NPPCOL *col;
col = dmp_get_atom(npp->pool, sizeof(NPPCOL));
col->j = ++(npp->ncols);
col->name = NULL;
#if 0
col->kind = GLP_CV;
#else
col->is_int = 0;
#endif
col->lb = col->ub = col->coef = 0.0;
col->ptr = NULL;
col->temp = 0;
npp_insert_col(npp, col, 1);
return col;
}
NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val)
{ /* add new element to the constraint matrix */
NPPAIJ *aij;
aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ));
aij->row = row;
aij->col = col;
aij->val = val;
aij->r_prev = NULL;
aij->r_next = row->ptr;
aij->c_prev = NULL;
aij->c_next = col->ptr;
if (aij->r_next != NULL)
aij->r_next->r_prev = aij;
if (aij->c_next != NULL)
aij->c_next->c_prev = aij;
row->ptr = col->ptr = aij;
return aij;
}
int npp_row_nnz(NPP *npp, NPPROW *row)
{ /* count number of non-zero coefficients in row */
NPPAIJ *aij;
int nnz;
xassert(npp == npp);
nnz = 0;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
nnz++;
return nnz;
}
int npp_col_nnz(NPP *npp, NPPCOL *col)
{ /* count number of non-zero coefficients in column */
NPPAIJ *aij;
int nnz;
xassert(npp == npp);
nnz = 0;
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
nnz++;
return nnz;
}
void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info),
int size)
{ /* push new entry to the transformation stack */
NPPTSE *tse;
tse = dmp_get_atom(npp->stack, sizeof(NPPTSE));
tse->func = func;
tse->info = dmp_get_atom(npp->stack, size);
tse->link = npp->top;
npp->top = tse;
return tse->info;
}
#if 1 /* 23/XII-2009 */
void npp_erase_row(NPP *npp, NPPROW *row)
{ /* erase row content to make it empty */
NPPAIJ *aij;
while (row->ptr != NULL)
{ aij = row->ptr;
row->ptr = aij->r_next;
if (aij->c_prev == NULL)
aij->col->ptr = aij->c_next;
else
aij->c_prev->c_next = aij->c_next;
if (aij->c_next == NULL)
;
else
aij->c_next->c_prev = aij->c_prev;
dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
}
return;
}
#endif
void npp_del_row(NPP *npp, NPPROW *row)
{ /* remove row from the current problem */
#if 0 /* 23/XII-2009 */
NPPAIJ *aij;
#endif
if (row->name != NULL)
dmp_free_atom(npp->pool, row->name, strlen(row->name)+1);
#if 0 /* 23/XII-2009 */
while (row->ptr != NULL)
{ aij = row->ptr;
row->ptr = aij->r_next;
if (aij->c_prev == NULL)
aij->col->ptr = aij->c_next;
else
aij->c_prev->c_next = aij->c_next;
if (aij->c_next == NULL)
;
else
aij->c_next->c_prev = aij->c_prev;
dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
}
#else
npp_erase_row(npp, row);
#endif
npp_remove_row(npp, row);
dmp_free_atom(npp->pool, row, sizeof(NPPROW));
return;
}
void npp_del_col(NPP *npp, NPPCOL *col)
{ /* remove column from the current problem */
NPPAIJ *aij;
if (col->name != NULL)
dmp_free_atom(npp->pool, col->name, strlen(col->name)+1);
while (col->ptr != NULL)
{ aij = col->ptr;
col->ptr = aij->c_next;
if (aij->r_prev == NULL)
aij->row->ptr = aij->r_next;
else
aij->r_prev->r_next = aij->r_next;
if (aij->r_next == NULL)
;
else
aij->r_next->r_prev = aij->r_prev;
dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
}
npp_remove_col(npp, col);
dmp_free_atom(npp->pool, col, sizeof(NPPCOL));
return;
}
void npp_del_aij(NPP *npp, NPPAIJ *aij)
{ /* remove element from the constraint matrix */
if (aij->r_prev == NULL)
aij->row->ptr = aij->r_next;
else
aij->r_prev->r_next = aij->r_next;
if (aij->r_next == NULL)
;
else
aij->r_next->r_prev = aij->r_prev;
if (aij->c_prev == NULL)
aij->col->ptr = aij->c_next;
else
aij->c_prev->c_next = aij->c_next;
if (aij->c_next == NULL)
;
else
aij->c_next->c_prev = aij->c_prev;
dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
return;
}
void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol,
int scaling)
{ /* load original problem into the preprocessor workspace */
int m = orig->m;
int n = orig->n;
NPPROW **link;
int i, j;
double dir;
xassert(names == GLP_OFF || names == GLP_ON);
xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP);
xassert(scaling == GLP_OFF || scaling == GLP_ON);
if (sol == GLP_MIP) xassert(!scaling);
npp->orig_dir = orig->dir;
if (npp->orig_dir == GLP_MIN)
dir = +1.0;
else if (npp->orig_dir == GLP_MAX)
dir = -1.0;
else
xassert(npp != npp);
npp->orig_m = m;
npp->orig_n = n;
npp->orig_nnz = orig->nnz;
if (names && orig->name != NULL)
{ npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1);
strcpy(npp->name, orig->name);
}
if (names && orig->obj != NULL)
{ npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1);
strcpy(npp->obj, orig->obj);
}
npp->c0 = dir * orig->c0;
/* load rows */
link = xcalloc(1+m, sizeof(NPPROW *));
for (i = 1; i <= m; i++)
{ GLPROW *rrr = orig->row[i];
NPPROW *row;
link[i] = row = npp_add_row(npp);
xassert(row->i == i);
if (names && rrr->name != NULL)
{ row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1);
strcpy(row->name, rrr->name);
}
if (!scaling)
{ if (rrr->type == GLP_FR)
row->lb = -DBL_MAX, row->ub = +DBL_MAX;
else if (rrr->type == GLP_LO)
row->lb = rrr->lb, row->ub = +DBL_MAX;
else if (rrr->type == GLP_UP)
row->lb = -DBL_MAX, row->ub = rrr->ub;
else if (rrr->type == GLP_DB)
row->lb = rrr->lb, row->ub = rrr->ub;
else if (rrr->type == GLP_FX)
row->lb = row->ub = rrr->lb;
else
xassert(rrr != rrr);
}
else
{ double rii = rrr->rii;
if (rrr->type == GLP_FR)
row->lb = -DBL_MAX, row->ub = +DBL_MAX;
else if (rrr->type == GLP_LO)
row->lb = rrr->lb * rii, row->ub = +DBL_MAX;
else if (rrr->type == GLP_UP)
row->lb = -DBL_MAX, row->ub = rrr->ub * rii;
else if (rrr->type == GLP_DB)
row->lb = rrr->lb * rii, row->ub = rrr->ub * rii;
else if (rrr->type == GLP_FX)
row->lb = row->ub = rrr->lb * rii;
else
xassert(rrr != rrr);
}
}
/* load columns and constraint coefficients */
for (j = 1; j <= n; j++)
{ GLPCOL *ccc = orig->col[j];
GLPAIJ *aaa;
NPPCOL *col;
col = npp_add_col(npp);
xassert(col->j == j);
if (names && ccc->name != NULL)
{ col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1);
strcpy(col->name, ccc->name);
}
if (sol == GLP_MIP)
#if 0
col->kind = ccc->kind;
#else
col->is_int = (char)(ccc->kind == GLP_IV);
#endif
if (!scaling)
{ if (ccc->type == GLP_FR)
col->lb = -DBL_MAX, col->ub = +DBL_MAX;
else if (ccc->type == GLP_LO)
col->lb = ccc->lb, col->ub = +DBL_MAX;
else if (ccc->type == GLP_UP)
col->lb = -DBL_MAX, col->ub = ccc->ub;
else if (ccc->type == GLP_DB)
col->lb = ccc->lb, col->ub = ccc->ub;
else if (ccc->type == GLP_FX)
col->lb = col->ub = ccc->lb;
else
xassert(ccc != ccc);
col->coef = dir * ccc->coef;
for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
npp_add_aij(npp, link[aaa->row->i], col, aaa->val);
}
else
{ double sjj = ccc->sjj;
if (ccc->type == GLP_FR)
col->lb = -DBL_MAX, col->ub = +DBL_MAX;
else if (ccc->type == GLP_LO)
col->lb = ccc->lb / sjj, col->ub = +DBL_MAX;
else if (ccc->type == GLP_UP)
col->lb = -DBL_MAX, col->ub = ccc->ub / sjj;
else if (ccc->type == GLP_DB)
col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj;
else if (ccc->type == GLP_FX)
col->lb = col->ub = ccc->lb / sjj;
else
xassert(ccc != ccc);
col->coef = dir * ccc->coef * sjj;
for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
npp_add_aij(npp, link[aaa->row->i], col,
aaa->row->rii * aaa->val * sjj);
}
}
xfree(link);
/* keep solution indicator and scaling option */
npp->sol = sol;
npp->scaling = scaling;
return;
}
void npp_build_prob(NPP *npp, glp_prob *prob)
{ /* build resultant (preprocessed) problem */
NPPROW *row;
NPPCOL *col;
NPPAIJ *aij;
int i, j, type, len, *ind;
double dir, *val;
glp_erase_prob(prob);
glp_set_prob_name(prob, npp->name);
glp_set_obj_name(prob, npp->obj);
glp_set_obj_dir(prob, npp->orig_dir);
if (npp->orig_dir == GLP_MIN)
dir = +1.0;
else if (npp->orig_dir == GLP_MAX)
dir = -1.0;
else
xassert(npp != npp);
glp_set_obj_coef(prob, 0, dir * npp->c0);
/* build rows */
for (row = npp->r_head; row != NULL; row = row->next)
{ row->temp = i = glp_add_rows(prob, 1);
glp_set_row_name(prob, i, row->name);
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
type = GLP_FR;
else if (row->ub == +DBL_MAX)
type = GLP_LO;
else if (row->lb == -DBL_MAX)
type = GLP_UP;
else if (row->lb != row->ub)
type = GLP_DB;
else
type = GLP_FX;
glp_set_row_bnds(prob, i, type, row->lb, row->ub);
}
/* build columns and the constraint matrix */
ind = xcalloc(1+prob->m, sizeof(int));
val = xcalloc(1+prob->m, sizeof(double));
for (col = npp->c_head; col != NULL; col = col->next)
{ j = glp_add_cols(prob, 1);
glp_set_col_name(prob, j, col->name);
#if 0
glp_set_col_kind(prob, j, col->kind);
#else
glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV);
#endif
if (col->lb == -DBL_MAX && col->ub == +DBL_MAX)
type = GLP_FR;
else if (col->ub == +DBL_MAX)
type = GLP_LO;
else if (col->lb == -DBL_MAX)
type = GLP_UP;
else if (col->lb != col->ub)
type = GLP_DB;
else
type = GLP_FX;
glp_set_col_bnds(prob, j, type, col->lb, col->ub);
glp_set_obj_coef(prob, j, dir * col->coef);
len = 0;
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
{ len++;
ind[len] = aij->row->temp;
val[len] = aij->val;
}
glp_set_mat_col(prob, j, len, ind, val);
}
xfree(ind);
xfree(val);
/* resultant problem has been built */
npp->m = prob->m;
npp->n = prob->n;
npp->nnz = prob->nnz;
npp->row_ref = xcalloc(1+npp->m, sizeof(int));
npp->col_ref = xcalloc(1+npp->n, sizeof(int));
for (row = npp->r_head, i = 0; row != NULL; row = row->next)
npp->row_ref[++i] = row->i;
for (col = npp->c_head, j = 0; col != NULL; col = col->next)
npp->col_ref[++j] = col->j;
/* transformed problem segment is no longer needed */
dmp_delete_pool(npp->pool), npp->pool = NULL;
npp->name = npp->obj = NULL;
npp->c0 = 0.0;
npp->r_head = npp->r_tail = NULL;
npp->c_head = npp->c_tail = NULL;
return;
}
void npp_postprocess(NPP *npp, glp_prob *prob)
{ /* postprocess solution from the resultant problem */
GLPROW *row;
GLPCOL *col;
NPPTSE *tse;
int i, j, k;
double dir;
xassert(npp->orig_dir == prob->dir);
if (npp->orig_dir == GLP_MIN)
dir = +1.0;
else if (npp->orig_dir == GLP_MAX)
dir = -1.0;
else
xassert(npp != npp);
#if 0 /* 11/VII-2013; due to call from ios_main */
xassert(npp->m == prob->m);
#else
if (npp->sol != GLP_MIP)
xassert(npp->m == prob->m);
#endif
xassert(npp->n == prob->n);
#if 0 /* 11/VII-2013; due to call from ios_main */
xassert(npp->nnz == prob->nnz);
#else
if (npp->sol != GLP_MIP)
xassert(npp->nnz == prob->nnz);
#endif
/* copy solution status */
if (npp->sol == GLP_SOL)
{ npp->p_stat = prob->pbs_stat;
npp->d_stat = prob->dbs_stat;
}
else if (npp->sol == GLP_IPT)
npp->t_stat = prob->ipt_stat;
else if (npp->sol == GLP_MIP)
npp->i_stat = prob->mip_stat;
else
xassert(npp != npp);
/* allocate solution arrays */
if (npp->sol == GLP_SOL)
{ if (npp->r_stat == NULL)
npp->r_stat = xcalloc(1+npp->nrows, sizeof(char));
for (i = 1; i <= npp->nrows; i++)
npp->r_stat[i] = 0;
if (npp->c_stat == NULL)
npp->c_stat = xcalloc(1+npp->ncols, sizeof(char));
for (j = 1; j <= npp->ncols; j++)
npp->c_stat[j] = 0;
}
#if 0
if (npp->r_prim == NULL)
npp->r_prim = xcalloc(1+npp->nrows, sizeof(double));
for (i = 1; i <= npp->nrows; i++)
npp->r_prim[i] = DBL_MAX;
#endif
if (npp->c_value == NULL)
npp->c_value = xcalloc(1+npp->ncols, sizeof(double));
for (j = 1; j <= npp->ncols; j++)
npp->c_value[j] = DBL_MAX;
if (npp->sol != GLP_MIP)
{ if (npp->r_pi == NULL)
npp->r_pi = xcalloc(1+npp->nrows, sizeof(double));
for (i = 1; i <= npp->nrows; i++)
npp->r_pi[i] = DBL_MAX;
#if 0
if (npp->c_dual == NULL)
npp->c_dual = xcalloc(1+npp->ncols, sizeof(double));
for (j = 1; j <= npp->ncols; j++)
npp->c_dual[j] = DBL_MAX;
#endif
}
/* copy solution components from the resultant problem */
if (npp->sol == GLP_SOL)
{ for (i = 1; i <= npp->m; i++)
{ row = prob->row[i];
k = npp->row_ref[i];
npp->r_stat[k] = (char)row->stat;
/*npp->r_prim[k] = row->prim;*/
npp->r_pi[k] = dir * row->dual;
}
for (j = 1; j <= npp->n; j++)
{ col = prob->col[j];
k = npp->col_ref[j];
npp->c_stat[k] = (char)col->stat;
npp->c_value[k] = col->prim;
/*npp->c_dual[k] = dir * col->dual;*/
}
}
else if (npp->sol == GLP_IPT)
{ for (i = 1; i <= npp->m; i++)
{ row = prob->row[i];
k = npp->row_ref[i];
/*npp->r_prim[k] = row->pval;*/
npp->r_pi[k] = dir * row->dval;
}
for (j = 1; j <= npp->n; j++)
{ col = prob->col[j];
k = npp->col_ref[j];
npp->c_value[k] = col->pval;
/*npp->c_dual[k] = dir * col->dval;*/
}
}
else if (npp->sol == GLP_MIP)
{
#if 0
for (i = 1; i <= npp->m; i++)
{ row = prob->row[i];
k = npp->row_ref[i];
/*npp->r_prim[k] = row->mipx;*/
}
#endif
for (j = 1; j <= npp->n; j++)
{ col = prob->col[j];
k = npp->col_ref[j];
npp->c_value[k] = col->mipx;
}
}
else
xassert(npp != npp);
/* perform postprocessing to construct solution to the original
problem */
for (tse = npp->top; tse != NULL; tse = tse->link)
{ xassert(tse->func != NULL);
xassert(tse->func(npp, tse->info) == 0);
}
return;
}
void npp_unload_sol(NPP *npp, glp_prob *orig)
{ /* store solution to the original problem */
GLPROW *row;
GLPCOL *col;
int i, j;
double dir;
xassert(npp->orig_dir == orig->dir);
if (npp->orig_dir == GLP_MIN)
dir = +1.0;
else if (npp->orig_dir == GLP_MAX)
dir = -1.0;
else
xassert(npp != npp);
xassert(npp->orig_m == orig->m);
xassert(npp->orig_n == orig->n);
xassert(npp->orig_nnz == orig->nnz);
if (npp->sol == GLP_SOL)
{ /* store basic solution */
orig->valid = 0;
orig->pbs_stat = npp->p_stat;
orig->dbs_stat = npp->d_stat;
orig->obj_val = orig->c0;
orig->some = 0;
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
row->stat = npp->r_stat[i];
if (!npp->scaling)
{ /*row->prim = npp->r_prim[i];*/
row->dual = dir * npp->r_pi[i];
}
else
{ /*row->prim = npp->r_prim[i] / row->rii;*/
row->dual = dir * npp->r_pi[i] * row->rii;
}
if (row->stat == GLP_BS)
row->dual = 0.0;
else if (row->stat == GLP_NL)
{ xassert(row->type == GLP_LO || row->type == GLP_DB);
row->prim = row->lb;
}
else if (row->stat == GLP_NU)
{ xassert(row->type == GLP_UP || row->type == GLP_DB);
row->prim = row->ub;
}
else if (row->stat == GLP_NF)
{ xassert(row->type == GLP_FR);
row->prim = 0.0;
}
else if (row->stat == GLP_NS)
{ xassert(row->type == GLP_FX);
row->prim = row->lb;
}
else
xassert(row != row);
}
for (j = 1; j <= orig->n; j++)
{ col = orig->col[j];
col->stat = npp->c_stat[j];
if (!npp->scaling)
{ col->prim = npp->c_value[j];
/*col->dual = dir * npp->c_dual[j];*/
}
else
{ col->prim = npp->c_value[j] * col->sjj;
/*col->dual = dir * npp->c_dual[j] / col->sjj;*/
}
if (col->stat == GLP_BS)
col->dual = 0.0;
#if 1
else if (col->stat == GLP_NL)
{ xassert(col->type == GLP_LO || col->type == GLP_DB);
col->prim = col->lb;
}
else if (col->stat == GLP_NU)
{ xassert(col->type == GLP_UP || col->type == GLP_DB);
col->prim = col->ub;
}
else if (col->stat == GLP_NF)
{ xassert(col->type == GLP_FR);
col->prim = 0.0;
}
else if (col->stat == GLP_NS)
{ xassert(col->type == GLP_FX);
col->prim = col->lb;
}
else
xassert(col != col);
#endif
orig->obj_val += col->coef * col->prim;
}
#if 1
/* compute primal values of inactive rows */
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
if (row->stat == GLP_BS)
{ GLPAIJ *aij;
double temp;
temp = 0.0;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
temp += aij->val * aij->col->prim;
row->prim = temp;
}
}
/* compute reduced costs of active columns */
for (j = 1; j <= orig->n; j++)
{ col = orig->col[j];
if (col->stat != GLP_BS)
{ GLPAIJ *aij;
double temp;
temp = col->coef;
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
temp -= aij->val * aij->row->dual;
col->dual = temp;
}
}
#endif
}
else if (npp->sol == GLP_IPT)
{ /* store interior-point solution */
orig->ipt_stat = npp->t_stat;
orig->ipt_obj = orig->c0;
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
if (!npp->scaling)
{ /*row->pval = npp->r_prim[i];*/
row->dval = dir * npp->r_pi[i];
}
else
{ /*row->pval = npp->r_prim[i] / row->rii;*/
row->dval = dir * npp->r_pi[i] * row->rii;
}
}
for (j = 1; j <= orig->n; j++)
{ col = orig->col[j];
if (!npp->scaling)
{ col->pval = npp->c_value[j];
/*col->dval = dir * npp->c_dual[j];*/
}
else
{ col->pval = npp->c_value[j] * col->sjj;
/*col->dval = dir * npp->c_dual[j] / col->sjj;*/
}
orig->ipt_obj += col->coef * col->pval;
}
#if 1
/* compute row primal values */
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
{ GLPAIJ *aij;
double temp;
temp = 0.0;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
temp += aij->val * aij->col->pval;
row->pval = temp;
}
}
/* compute column dual values */
for (j = 1; j <= orig->n; j++)
{ col = orig->col[j];
{ GLPAIJ *aij;
double temp;
temp = col->coef;
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
temp -= aij->val * aij->row->dval;
col->dval = temp;
}
}
#endif
}
else if (npp->sol == GLP_MIP)
{ /* store MIP solution */
xassert(!npp->scaling);
orig->mip_stat = npp->i_stat;
orig->mip_obj = orig->c0;
#if 0
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
/*row->mipx = npp->r_prim[i];*/
}
#endif
for (j = 1; j <= orig->n; j++)
{ col = orig->col[j];
col->mipx = npp->c_value[j];
if (col->kind == GLP_IV)
xassert(col->mipx == floor(col->mipx));
orig->mip_obj += col->coef * col->mipx;
}
#if 1
/* compute row primal values */
for (i = 1; i <= orig->m; i++)
{ row = orig->row[i];
{ GLPAIJ *aij;
double temp;
temp = 0.0;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
temp += aij->val * aij->col->mipx;
row->mipx = temp;
}
}
#endif
}
else
xassert(npp != npp);
return;
}
void npp_delete_wksp(NPP *npp)
{ /* delete LP/MIP preprocessor workspace */
if (npp->pool != NULL)
dmp_delete_pool(npp->pool);
if (npp->stack != NULL)
dmp_delete_pool(npp->stack);
if (npp->row_ref != NULL)
xfree(npp->row_ref);
if (npp->col_ref != NULL)
xfree(npp->col_ref);
if (npp->r_stat != NULL)
xfree(npp->r_stat);
#if 0
if (npp->r_prim != NULL)
xfree(npp->r_prim);
#endif
if (npp->r_pi != NULL)
xfree(npp->r_pi);
if (npp->c_stat != NULL)
xfree(npp->c_stat);
if (npp->c_value != NULL)
xfree(npp->c_value);
#if 0
if (npp->c_dual != NULL)
xfree(npp->c_dual);
#endif
xfree(npp);
return;
}
/* eof */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+807
View File
@@ -0,0 +1,807 @@
/* npp5.c */
/***********************************************************************
* This code is part of GLPK (GNU Linear Programming Kit).
* Copyright (C) 2009-2017 Free Software Foundation, Inc.
* Written by Andrew Makhorin <mao@gnu.org>.
*
* GLPK is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPK 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 General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "env.h"
#include "npp.h"
/***********************************************************************
* NAME
*
* npp_clean_prob - perform initial LP/MIP processing
*
* SYNOPSIS
*
* #include "glpnpp.h"
* void npp_clean_prob(NPP *npp);
*
* DESCRIPTION
*
* The routine npp_clean_prob performs initial LP/MIP processing that
* currently includes:
*
* 1) removing free rows;
*
* 2) replacing double-sided constraint rows with almost identical
* bounds, by equality constraint rows;
*
* 3) removing fixed columns;
*
* 4) replacing double-bounded columns with almost identical bounds by
* fixed columns and removing those columns;
*
* 5) initial processing constraint coefficients (not implemented);
*
* 6) initial processing objective coefficients (not implemented). */
void npp_clean_prob(NPP *npp)
{ /* perform initial LP/MIP processing */
NPPROW *row, *next_row;
NPPCOL *col, *next_col;
int ret;
xassert(npp == npp);
/* process rows which originally are free */
for (row = npp->r_head; row != NULL; row = next_row)
{ next_row = row->next;
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
{ /* process free row */
#ifdef GLP_DEBUG
xprintf("1");
#endif
npp_free_row(npp, row);
/* row was deleted */
}
}
/* process rows which originally are double-sided inequalities */
for (row = npp->r_head; row != NULL; row = next_row)
{ next_row = row->next;
if (row->lb != -DBL_MAX && row->ub != +DBL_MAX &&
row->lb < row->ub)
{ ret = npp_make_equality(npp, row);
if (ret == 0)
;
else if (ret == 1)
{ /* row was replaced by equality constraint */
#ifdef GLP_DEBUG
xprintf("2");
#endif
}
else
xassert(ret != ret);
}
}
/* process columns which are originally fixed */
for (col = npp->c_head; col != NULL; col = next_col)
{ next_col = col->next;
if (col->lb == col->ub)
{ /* process fixed column */
#ifdef GLP_DEBUG
xprintf("3");
#endif
npp_fixed_col(npp, col);
/* column was deleted */
}
}
/* process columns which are originally double-bounded */
for (col = npp->c_head; col != NULL; col = next_col)
{ next_col = col->next;
if (col->lb != -DBL_MAX && col->ub != +DBL_MAX &&
col->lb < col->ub)
{ ret = npp_make_fixed(npp, col);
if (ret == 0)
;
else if (ret == 1)
{ /* column was replaced by fixed column; process it */
#ifdef GLP_DEBUG
xprintf("4");
#endif
npp_fixed_col(npp, col);
/* column was deleted */
}
}
}
return;
}
/***********************************************************************
* NAME
*
* npp_process_row - perform basic row processing
*
* SYNOPSIS
*
* #include "glpnpp.h"
* int npp_process_row(NPP *npp, NPPROW *row, int hard);
*
* DESCRIPTION
*
* The routine npp_process_row performs basic row processing that
* currently includes:
*
* 1) removing empty row;
*
* 2) removing equality constraint row singleton and corresponding
* column;
*
* 3) removing inequality constraint row singleton and corresponding
* column if it was fixed;
*
* 4) performing general row analysis;
*
* 5) removing redundant row bounds;
*
* 6) removing forcing row and corresponding columns;
*
* 7) removing row which becomes free due to redundant bounds;
*
* 8) computing implied bounds for all columns in the row and using
* them to strengthen current column bounds (MIP only, optional,
* performed if the flag hard is on).
*
* Additionally the routine may activate affected rows and/or columns
* for further processing.
*
* RETURNS
*
* 0 success;
*
* GLP_ENOPFS primal/integer infeasibility detected;
*
* GLP_ENODFS dual infeasibility detected. */
int npp_process_row(NPP *npp, NPPROW *row, int hard)
{ /* perform basic row processing */
NPPCOL *col;
NPPAIJ *aij, *next_aij, *aaa;
int ret;
/* row must not be free */
xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX));
/* start processing row */
if (row->ptr == NULL)
{ /* empty row */
ret = npp_empty_row(npp, row);
if (ret == 0)
{ /* row was deleted */
#ifdef GLP_DEBUG
xprintf("A");
#endif
return 0;
}
else if (ret == 1)
{ /* primal infeasibility */
return GLP_ENOPFS;
}
else
xassert(ret != ret);
}
if (row->ptr->r_next == NULL)
{ /* row singleton */
col = row->ptr->col;
if (row->lb == row->ub)
{ /* equality constraint */
ret = npp_eq_singlet(npp, row);
if (ret == 0)
{ /* column was fixed, row was deleted */
#ifdef GLP_DEBUG
xprintf("B");
#endif
/* activate rows affected by column */
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
npp_activate_row(npp, aij->row);
/* process fixed column */
npp_fixed_col(npp, col);
/* column was deleted */
return 0;
}
else if (ret == 1 || ret == 2)
{ /* primal/integer infeasibility */
return GLP_ENOPFS;
}
else
xassert(ret != ret);
}
else
{ /* inequality constraint */
ret = npp_ineq_singlet(npp, row);
if (0 <= ret && ret <= 3)
{ /* row was deleted */
#ifdef GLP_DEBUG
xprintf("C");
#endif
/* activate column, since its length was changed due to
row deletion */
npp_activate_col(npp, col);
if (ret >= 2)
{ /* column bounds changed significantly or column was
fixed */
/* activate rows affected by column */
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
npp_activate_row(npp, aij->row);
}
if (ret == 3)
{ /* column was fixed; process it */
#ifdef GLP_DEBUG
xprintf("D");
#endif
npp_fixed_col(npp, col);
/* column was deleted */
}
return 0;
}
else if (ret == 4)
{ /* primal infeasibility */
return GLP_ENOPFS;
}
else
xassert(ret != ret);
}
}
#if 0
/* sometimes this causes too large round-off errors; probably
pivot coefficient should be chosen more carefully */
if (row->ptr->r_next->r_next == NULL)
{ /* row doubleton */
if (row->lb == row->ub)
{ /* equality constraint */
if (!(row->ptr->col->is_int ||
row->ptr->r_next->col->is_int))
{ /* both columns are continuous */
NPPCOL *q;
q = npp_eq_doublet(npp, row);
if (q != NULL)
{ /* column q was eliminated */
#ifdef GLP_DEBUG
xprintf("E");
#endif
/* now column q is singleton of type "implied slack
variable"; we process it here to make sure that on
recovering basic solution the row is always active
equality constraint (as required by the routine
rcv_eq_doublet) */
xassert(npp_process_col(npp, q) == 0);
/* column q was deleted; note that row p also may be
deleted */
return 0;
}
}
}
}
#endif
/* general row analysis */
ret = npp_analyze_row(npp, row);
xassert(0x00 <= ret && ret <= 0xFF);
if (ret == 0x33)
{ /* row bounds are inconsistent with column bounds */
return GLP_ENOPFS;
}
if ((ret & 0x0F) == 0x00)
{ /* row lower bound does not exist or redundant */
if (row->lb != -DBL_MAX)
{ /* remove redundant row lower bound */
#ifdef GLP_DEBUG
xprintf("F");
#endif
npp_inactive_bound(npp, row, 0);
}
}
else if ((ret & 0x0F) == 0x01)
{ /* row lower bound can be active */
/* see below */
}
else if ((ret & 0x0F) == 0x02)
{ /* row lower bound is a forcing bound */
#ifdef GLP_DEBUG
xprintf("G");
#endif
/* process forcing row */
if (npp_forcing_row(npp, row, 0) == 0)
fixup: { /* columns were fixed, row was made free */
for (aij = row->ptr; aij != NULL; aij = next_aij)
{ /* process column fixed by forcing row */
#ifdef GLP_DEBUG
xprintf("H");
#endif
col = aij->col;
next_aij = aij->r_next;
/* activate rows affected by column */
for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next)
npp_activate_row(npp, aaa->row);
/* process fixed column */
npp_fixed_col(npp, col);
/* column was deleted */
}
/* process free row (which now is empty due to deletion of
all its columns) */
npp_free_row(npp, row);
/* row was deleted */
return 0;
}
}
else
xassert(ret != ret);
if ((ret & 0xF0) == 0x00)
{ /* row upper bound does not exist or redundant */
if (row->ub != +DBL_MAX)
{ /* remove redundant row upper bound */
#ifdef GLP_DEBUG
xprintf("I");
#endif
npp_inactive_bound(npp, row, 1);
}
}
else if ((ret & 0xF0) == 0x10)
{ /* row upper bound can be active */
/* see below */
}
else if ((ret & 0xF0) == 0x20)
{ /* row upper bound is a forcing bound */
#ifdef GLP_DEBUG
xprintf("J");
#endif
/* process forcing row */
if (npp_forcing_row(npp, row, 1) == 0) goto fixup;
}
else
xassert(ret != ret);
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
{ /* row became free due to redundant bounds removal */
#ifdef GLP_DEBUG
xprintf("K");
#endif
/* activate its columns, since their length will change due
to row deletion */
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
npp_activate_col(npp, aij->col);
/* process free row */
npp_free_row(npp, row);
/* row was deleted */
return 0;
}
#if 1 /* 23/XII-2009 */
/* row lower and/or upper bounds can be active */
if (npp->sol == GLP_MIP && hard)
{ /* improve current column bounds (optional) */
if (npp_improve_bounds(npp, row, 1) < 0)
return GLP_ENOPFS;
}
#endif
return 0;
}
/***********************************************************************
* NAME
*
* npp_improve_bounds - improve current column bounds
*
* SYNOPSIS
*
* #include "glpnpp.h"
* int npp_improve_bounds(NPP *npp, NPPROW *row, int flag);
*
* DESCRIPTION
*
* The routine npp_improve_bounds analyzes specified row (inequality
* or equality constraint) to determine implied column bounds and then
* uses these bounds to improve (strengthen) current column bounds.
*
* If the flag is on and current column bounds changed significantly
* or the column was fixed, the routine activate rows affected by the
* column for further processing. (This feature is intended to be used
* in the main loop of the routine npp_process_row.)
*
* NOTE: This operation can be used for MIP problem only.
*
* RETURNS
*
* The routine npp_improve_bounds returns the number of significantly
* changed bounds plus the number of column having been fixed due to
* bound improvements. However, if the routine detects primal/integer
* infeasibility, it returns a negative value. */
int npp_improve_bounds(NPP *npp, NPPROW *row, int flag)
{ /* improve current column bounds */
NPPCOL *col;
NPPAIJ *aij, *next_aij, *aaa;
int kase, ret, count = 0;
double lb, ub;
xassert(npp->sol == GLP_MIP);
/* row must not be free */
xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX));
/* determine implied column bounds */
npp_implied_bounds(npp, row);
/* and use these bounds to strengthen current column bounds */
for (aij = row->ptr; aij != NULL; aij = next_aij)
{ col = aij->col;
next_aij = aij->r_next;
for (kase = 0; kase <= 1; kase++)
{ /* save current column bounds */
lb = col->lb, ub = col->ub;
if (kase == 0)
{ /* process implied column lower bound */
if (col->ll.ll == -DBL_MAX) continue;
ret = npp_implied_lower(npp, col, col->ll.ll);
}
else
{ /* process implied column upper bound */
if (col->uu.uu == +DBL_MAX) continue;
ret = npp_implied_upper(npp, col, col->uu.uu);
}
if (ret == 0 || ret == 1)
{ /* current column bounds did not change or changed, but
not significantly; restore current column bounds */
col->lb = lb, col->ub = ub;
}
else if (ret == 2 || ret == 3)
{ /* current column bounds changed significantly or column
was fixed */
#ifdef GLP_DEBUG
xprintf("L");
#endif
count++;
/* activate other rows affected by column, if required */
if (flag)
{ for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next)
{ if (aaa->row != row)
npp_activate_row(npp, aaa->row);
}
}
if (ret == 3)
{ /* process fixed column */
#ifdef GLP_DEBUG
xprintf("M");
#endif
npp_fixed_col(npp, col);
/* column was deleted */
break; /* for kase */
}
}
else if (ret == 4)
{ /* primal/integer infeasibility */
return -1;
}
else
xassert(ret != ret);
}
}
return count;
}
/***********************************************************************
* NAME
*
* npp_process_col - perform basic column processing
*
* SYNOPSIS
*
* #include "glpnpp.h"
* int npp_process_col(NPP *npp, NPPCOL *col);
*
* DESCRIPTION
*
* The routine npp_process_col performs basic column processing that
* currently includes:
*
* 1) fixing and removing empty column;
*
* 2) removing column singleton, which is implied slack variable, and
* corresponding row if it becomes free;
*
* 3) removing bounds of column, which is implied free variable, and
* replacing corresponding row by equality constraint.
*
* Additionally the routine may activate affected rows and/or columns
* for further processing.
*
* RETURNS
*
* 0 success;
*
* GLP_ENOPFS primal/integer infeasibility detected;
*
* GLP_ENODFS dual infeasibility detected. */
int npp_process_col(NPP *npp, NPPCOL *col)
{ /* perform basic column processing */
NPPROW *row;
NPPAIJ *aij;
int ret;
/* column must not be fixed */
xassert(col->lb < col->ub);
/* start processing column */
if (col->ptr == NULL)
{ /* empty column */
ret = npp_empty_col(npp, col);
if (ret == 0)
{ /* column was fixed and deleted */
#ifdef GLP_DEBUG
xprintf("N");
#endif
return 0;
}
else if (ret == 1)
{ /* dual infeasibility */
return GLP_ENODFS;
}
else
xassert(ret != ret);
}
if (col->ptr->c_next == NULL)
{ /* column singleton */
row = col->ptr->row;
if (row->lb == row->ub)
{ /* equality constraint */
if (!col->is_int)
slack: { /* implied slack variable */
#ifdef GLP_DEBUG
xprintf("O");
#endif
npp_implied_slack(npp, col);
/* column was deleted */
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
{ /* row became free due to implied slack variable */
#ifdef GLP_DEBUG
xprintf("P");
#endif
/* activate columns affected by row */
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
npp_activate_col(npp, aij->col);
/* process free row */
npp_free_row(npp, row);
/* row was deleted */
}
else
{ /* row became inequality constraint; activate it
since its length changed due to column deletion */
npp_activate_row(npp, row);
}
return 0;
}
}
else
{ /* inequality constraint */
if (!col->is_int)
{ ret = npp_implied_free(npp, col);
if (ret == 0)
{ /* implied free variable */
#ifdef GLP_DEBUG
xprintf("Q");
#endif
/* column bounds were removed, row was replaced by
equality constraint */
goto slack;
}
else if (ret == 1)
{ /* column is not implied free variable, because its
lower and/or upper bounds can be active */
}
else if (ret == 2)
{ /* dual infeasibility */
return GLP_ENODFS;
}
}
}
}
/* column still exists */
return 0;
}
/***********************************************************************
* NAME
*
* npp_process_prob - perform basic LP/MIP processing
*
* SYNOPSIS
*
* #include "glpnpp.h"
* int npp_process_prob(NPP *npp, int hard);
*
* DESCRIPTION
*
* The routine npp_process_prob performs basic LP/MIP processing that
* currently includes:
*
* 1) initial LP/MIP processing (see the routine npp_clean_prob),
*
* 2) basic row processing (see the routine npp_process_row), and
*
* 3) basic column processing (see the routine npp_process_col).
*
* If the flag hard is on, the routine attempts to improve current
* column bounds multiple times within the main processing loop, in
* which case this feature may take a time. Otherwise, if the flag hard
* is off, improving column bounds is performed only once at the end of
* the main loop. (Note that this feature is used for MIP only.)
*
* The routine uses two sets: the set of active rows and the set of
* active columns. Rows/columns are marked by a flag (the field temp in
* NPPROW/NPPCOL). If the flag is non-zero, the row/column is active,
* in which case it is placed in the beginning of the row/column list;
* otherwise, if the flag is zero, the row/column is inactive, in which
* case it is placed in the end of the row/column list. If a row/column
* being currently processed may affect other rows/columns, the latters
* are activated for further processing.
*
* RETURNS
*
* 0 success;
*
* GLP_ENOPFS primal/integer infeasibility detected;
*
* GLP_ENODFS dual infeasibility detected. */
int npp_process_prob(NPP *npp, int hard)
{ /* perform basic LP/MIP processing */
NPPROW *row;
NPPCOL *col;
int processing, ret;
/* perform initial LP/MIP processing */
npp_clean_prob(npp);
/* activate all remaining rows and columns */
for (row = npp->r_head; row != NULL; row = row->next)
row->temp = 1;
for (col = npp->c_head; col != NULL; col = col->next)
col->temp = 1;
/* main processing loop */
processing = 1;
while (processing)
{ processing = 0;
/* process all active rows */
for (;;)
{ row = npp->r_head;
if (row == NULL || !row->temp) break;
npp_deactivate_row(npp, row);
ret = npp_process_row(npp, row, hard);
if (ret != 0) goto done;
processing = 1;
}
/* process all active columns */
for (;;)
{ col = npp->c_head;
if (col == NULL || !col->temp) break;
npp_deactivate_col(npp, col);
ret = npp_process_col(npp, col);
if (ret != 0) goto done;
processing = 1;
}
}
#if 1 /* 23/XII-2009 */
if (npp->sol == GLP_MIP && !hard)
{ /* improve current column bounds (optional) */
for (row = npp->r_head; row != NULL; row = row->next)
{ if (npp_improve_bounds(npp, row, 0) < 0)
{ ret = GLP_ENOPFS;
goto done;
}
}
}
#endif
/* all seems ok */
ret = 0;
done: xassert(ret == 0 || ret == GLP_ENOPFS || ret == GLP_ENODFS);
#ifdef GLP_DEBUG
xprintf("\n");
#endif
return ret;
}
/**********************************************************************/
int npp_simplex(NPP *npp, const glp_smcp *parm)
{ /* process LP prior to applying primal/dual simplex method */
int ret;
xassert(npp->sol == GLP_SOL);
xassert(parm == parm);
ret = npp_process_prob(npp, 0);
return ret;
}
/**********************************************************************/
int npp_integer(NPP *npp, const glp_iocp *parm)
{ /* process MIP prior to applying branch-and-bound method */
NPPROW *row, *prev_row;
NPPCOL *col;
NPPAIJ *aij;
int count, ret;
xassert(npp->sol == GLP_MIP);
xassert(parm == parm);
/*==============================================================*/
/* perform basic MIP processing */
ret = npp_process_prob(npp, 1);
if (ret != 0) goto done;
/*==============================================================*/
/* binarize problem, if required */
if (parm->binarize)
npp_binarize_prob(npp);
/*==============================================================*/
/* identify hidden packing inequalities */
count = 0;
/* new rows will be added to the end of the row list, so we go
from the end to beginning of the row list */
for (row = npp->r_tail; row != NULL; row = prev_row)
{ prev_row = row->prev;
/* skip free row */
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue;
/* skip equality constraint */
if (row->lb == row->ub) continue;
/* skip row having less than two variables */
if (row->ptr == NULL || row->ptr->r_next == NULL) continue;
/* skip row having non-binary variables */
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
{ col = aij->col;
if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0))
break;
}
if (aij != NULL) continue;
count += npp_hidden_packing(npp, row);
}
if (count > 0)
xprintf("%d hidden packing inequaliti(es) were detected\n",
count);
/*==============================================================*/
/* identify hidden covering inequalities */
count = 0;
/* new rows will be added to the end of the row list, so we go
from the end to beginning of the row list */
for (row = npp->r_tail; row != NULL; row = prev_row)
{ prev_row = row->prev;
/* skip free row */
if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue;
/* skip equality constraint */
if (row->lb == row->ub) continue;
/* skip row having less than three variables */
if (row->ptr == NULL || row->ptr->r_next == NULL ||
row->ptr->r_next->r_next == NULL) continue;
/* skip row having non-binary variables */
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
{ col = aij->col;
if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0))
break;
}
if (aij != NULL) continue;
count += npp_hidden_covering(npp, row);
}
if (count > 0)
xprintf("%d hidden covering inequaliti(es) were detected\n",
count);
/*==============================================================*/
/* reduce inequality constraint coefficients */
count = 0;
/* new rows will be added to the end of the row list, so we go
from the end to beginning of the row list */
for (row = npp->r_tail; row != NULL; row = prev_row)
{ prev_row = row->prev;
/* skip equality constraint */
if (row->lb == row->ub) continue;
count += npp_reduce_ineq_coef(npp, row);
}
if (count > 0)
xprintf("%d constraint coefficient(s) were reduced\n", count);
/*==============================================================*/
#ifdef GLP_DEBUG
routine(npp);
#endif
/*==============================================================*/
/* all seems ok */
ret = 0;
done: return ret;
}
/* eof */
File diff suppressed because it is too large Load Diff