Add graph references
This commit is contained in:
+643
@@ -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
@@ -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 */
|
||||
+1431
File diff suppressed because it is too large
Load Diff
+2859
File diff suppressed because it is too large
Load Diff
+1412
File diff suppressed because it is too large
Load Diff
+807
@@ -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 */
|
||||
+1498
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user