src/glpnpp01.c
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:608f853e250f
       
     1 /* glpnpp01.c */
       
     2 
       
     3 /***********************************************************************
       
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
       
     5 *
       
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
       
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
       
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
       
     9 *  E-mail: <mao@gnu.org>.
       
    10 *
       
    11 *  GLPK is free software: you can redistribute it and/or modify it
       
    12 *  under the terms of the GNU General Public License as published by
       
    13 *  the Free Software Foundation, either version 3 of the License, or
       
    14 *  (at your option) any later version.
       
    15 *
       
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
       
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
       
    19 *  License for more details.
       
    20 *
       
    21 *  You should have received a copy of the GNU General Public License
       
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
       
    23 ***********************************************************************/
       
    24 
       
    25 #include "glpnpp.h"
       
    26 
       
    27 NPP *npp_create_wksp(void)
       
    28 {     /* create LP/MIP preprocessor workspace */
       
    29       NPP *npp;
       
    30       npp = xmalloc(sizeof(NPP));
       
    31       npp->orig_dir = 0;
       
    32       npp->orig_m = npp->orig_n = npp->orig_nnz = 0;
       
    33       npp->pool = dmp_create_pool();
       
    34       npp->name = npp->obj = NULL;
       
    35       npp->c0 = 0.0;
       
    36       npp->nrows = npp->ncols = 0;
       
    37       npp->r_head = npp->r_tail = NULL;
       
    38       npp->c_head = npp->c_tail = NULL;
       
    39       npp->stack = dmp_create_pool();
       
    40       npp->top = NULL;
       
    41 #if 0 /* 16/XII-2009 */
       
    42       memset(&npp->count, 0, sizeof(npp->count));
       
    43 #endif
       
    44       npp->m = npp->n = npp->nnz = 0;
       
    45       npp->row_ref = npp->col_ref = NULL;
       
    46       npp->sol = npp->scaling = 0;
       
    47       npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0;
       
    48       npp->r_stat = NULL;
       
    49       /*npp->r_prim =*/ npp->r_pi = NULL;
       
    50       npp->c_stat = NULL;
       
    51       npp->c_value = /*npp->c_dual =*/ NULL;
       
    52       return npp;
       
    53 }
       
    54 
       
    55 void npp_insert_row(NPP *npp, NPPROW *row, int where)
       
    56 {     /* insert row to the row list */
       
    57       if (where == 0)
       
    58       {  /* insert row to the beginning of the row list */
       
    59          row->prev = NULL;
       
    60          row->next = npp->r_head;
       
    61          if (row->next == NULL)
       
    62             npp->r_tail = row;
       
    63          else
       
    64             row->next->prev = row;
       
    65          npp->r_head = row;
       
    66       }
       
    67       else
       
    68       {  /* insert row to the end of the row list */
       
    69          row->prev = npp->r_tail;
       
    70          row->next = NULL;
       
    71          if (row->prev == NULL)
       
    72             npp->r_head = row;
       
    73          else
       
    74             row->prev->next = row;
       
    75          npp->r_tail = row;
       
    76       }
       
    77       return;
       
    78 }
       
    79 
       
    80 void npp_remove_row(NPP *npp, NPPROW *row)
       
    81 {     /* remove row from the row list */
       
    82       if (row->prev == NULL)
       
    83          npp->r_head = row->next;
       
    84       else
       
    85          row->prev->next = row->next;
       
    86       if (row->next == NULL)
       
    87          npp->r_tail = row->prev;
       
    88       else
       
    89          row->next->prev = row->prev;
       
    90       return;
       
    91 }
       
    92 
       
    93 void npp_activate_row(NPP *npp, NPPROW *row)
       
    94 {     /* make row active */
       
    95       if (!row->temp)
       
    96       {  row->temp = 1;
       
    97          /* move the row to the beginning of the row list */
       
    98          npp_remove_row(npp, row);
       
    99          npp_insert_row(npp, row, 0);
       
   100       }
       
   101       return;
       
   102 }
       
   103 
       
   104 void npp_deactivate_row(NPP *npp, NPPROW *row)
       
   105 {     /* make row inactive */
       
   106       if (row->temp)
       
   107       {  row->temp = 0;
       
   108          /* move the row to the end of the row list */
       
   109          npp_remove_row(npp, row);
       
   110          npp_insert_row(npp, row, 1);
       
   111       }
       
   112       return;
       
   113 }
       
   114 
       
   115 void npp_insert_col(NPP *npp, NPPCOL *col, int where)
       
   116 {     /* insert column to the column list */
       
   117       if (where == 0)
       
   118       {  /* insert column to the beginning of the column list */
       
   119          col->prev = NULL;
       
   120          col->next = npp->c_head;
       
   121          if (col->next == NULL)
       
   122             npp->c_tail = col;
       
   123          else
       
   124             col->next->prev = col;
       
   125          npp->c_head = col;
       
   126       }
       
   127       else
       
   128       {  /* insert column to the end of the column list */
       
   129          col->prev = npp->c_tail;
       
   130          col->next = NULL;
       
   131          if (col->prev == NULL)
       
   132             npp->c_head = col;
       
   133          else
       
   134             col->prev->next = col;
       
   135          npp->c_tail = col;
       
   136       }
       
   137       return;
       
   138 }
       
   139 
       
   140 void npp_remove_col(NPP *npp, NPPCOL *col)
       
   141 {     /* remove column from the column list */
       
   142       if (col->prev == NULL)
       
   143          npp->c_head = col->next;
       
   144       else
       
   145          col->prev->next = col->next;
       
   146       if (col->next == NULL)
       
   147          npp->c_tail = col->prev;
       
   148       else
       
   149          col->next->prev = col->prev;
       
   150       return;
       
   151 }
       
   152 
       
   153 void npp_activate_col(NPP *npp, NPPCOL *col)
       
   154 {     /* make column active */
       
   155       if (!col->temp)
       
   156       {  col->temp = 1;
       
   157          /* move the column to the beginning of the column list */
       
   158          npp_remove_col(npp, col);
       
   159          npp_insert_col(npp, col, 0);
       
   160       }
       
   161       return;
       
   162 }
       
   163 
       
   164 void npp_deactivate_col(NPP *npp, NPPCOL *col)
       
   165 {     /* make column inactive */
       
   166       if (col->temp)
       
   167       {  col->temp = 0;
       
   168          /* move the column to the end of the column list */
       
   169          npp_remove_col(npp, col);
       
   170          npp_insert_col(npp, col, 1);
       
   171       }
       
   172       return;
       
   173 }
       
   174 
       
   175 NPPROW *npp_add_row(NPP *npp)
       
   176 {     /* add new row to the current problem */
       
   177       NPPROW *row;
       
   178       row = dmp_get_atom(npp->pool, sizeof(NPPROW));
       
   179       row->i = ++(npp->nrows);
       
   180       row->name = NULL;
       
   181       row->lb = -DBL_MAX, row->ub = +DBL_MAX;
       
   182       row->ptr = NULL;
       
   183       row->temp = 0;
       
   184       npp_insert_row(npp, row, 1);
       
   185       return row;
       
   186 }
       
   187 
       
   188 NPPCOL *npp_add_col(NPP *npp)
       
   189 {     /* add new column to the current problem */
       
   190       NPPCOL *col;
       
   191       col = dmp_get_atom(npp->pool, sizeof(NPPCOL));
       
   192       col->j = ++(npp->ncols);
       
   193       col->name = NULL;
       
   194 #if 0
       
   195       col->kind = GLP_CV;
       
   196 #else
       
   197       col->is_int = 0;
       
   198 #endif
       
   199       col->lb = col->ub = col->coef = 0.0;
       
   200       col->ptr = NULL;
       
   201       col->temp = 0;
       
   202       npp_insert_col(npp, col, 1);
       
   203       return col;
       
   204 }
       
   205 
       
   206 NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val)
       
   207 {     /* add new element to the constraint matrix */
       
   208       NPPAIJ *aij;
       
   209       aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ));
       
   210       aij->row = row;
       
   211       aij->col = col;
       
   212       aij->val = val;
       
   213       aij->r_prev = NULL;
       
   214       aij->r_next = row->ptr;
       
   215       aij->c_prev = NULL;
       
   216       aij->c_next = col->ptr;
       
   217       if (aij->r_next != NULL)
       
   218          aij->r_next->r_prev = aij;
       
   219       if (aij->c_next != NULL)
       
   220          aij->c_next->c_prev = aij;
       
   221       row->ptr = col->ptr = aij;
       
   222       return aij;
       
   223 }
       
   224 
       
   225 int npp_row_nnz(NPP *npp, NPPROW *row)
       
   226 {     /* count number of non-zero coefficients in row */
       
   227       NPPAIJ *aij;
       
   228       int nnz;
       
   229       xassert(npp == npp);
       
   230       nnz = 0;
       
   231       for (aij = row->ptr; aij != NULL; aij = aij->r_next)
       
   232          nnz++;
       
   233       return nnz;
       
   234 }
       
   235 
       
   236 int npp_col_nnz(NPP *npp, NPPCOL *col)
       
   237 {     /* count number of non-zero coefficients in column */
       
   238       NPPAIJ *aij;
       
   239       int nnz;
       
   240       xassert(npp == npp);
       
   241       nnz = 0;
       
   242       for (aij = col->ptr; aij != NULL; aij = aij->c_next)
       
   243          nnz++;
       
   244       return nnz;
       
   245 }
       
   246 
       
   247 void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info),
       
   248       int size)
       
   249 {     /* push new entry to the transformation stack */
       
   250       NPPTSE *tse;
       
   251       tse = dmp_get_atom(npp->stack, sizeof(NPPTSE));
       
   252       tse->func = func;
       
   253       tse->info = dmp_get_atom(npp->stack, size);
       
   254       tse->link = npp->top;
       
   255       npp->top = tse;
       
   256       return tse->info;
       
   257 }
       
   258 
       
   259 #if 1 /* 23/XII-2009 */
       
   260 void npp_erase_row(NPP *npp, NPPROW *row)
       
   261 {     /* erase row content to make it empty */
       
   262       NPPAIJ *aij;
       
   263       while (row->ptr != NULL)
       
   264       {  aij = row->ptr;
       
   265          row->ptr = aij->r_next;
       
   266          if (aij->c_prev == NULL)
       
   267             aij->col->ptr = aij->c_next;
       
   268          else
       
   269             aij->c_prev->c_next = aij->c_next;
       
   270          if (aij->c_next == NULL)
       
   271             ;
       
   272          else
       
   273             aij->c_next->c_prev = aij->c_prev;
       
   274          dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
       
   275       }
       
   276       return;
       
   277 }
       
   278 #endif
       
   279 
       
   280 void npp_del_row(NPP *npp, NPPROW *row)
       
   281 {     /* remove row from the current problem */
       
   282 #if 0 /* 23/XII-2009 */
       
   283       NPPAIJ *aij;
       
   284 #endif
       
   285       if (row->name != NULL)
       
   286          dmp_free_atom(npp->pool, row->name, strlen(row->name)+1);
       
   287 #if 0 /* 23/XII-2009 */
       
   288       while (row->ptr != NULL)
       
   289       {  aij = row->ptr;
       
   290          row->ptr = aij->r_next;
       
   291          if (aij->c_prev == NULL)
       
   292             aij->col->ptr = aij->c_next;
       
   293          else
       
   294             aij->c_prev->c_next = aij->c_next;
       
   295          if (aij->c_next == NULL)
       
   296             ;
       
   297          else
       
   298             aij->c_next->c_prev = aij->c_prev;
       
   299          dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
       
   300       }
       
   301 #else
       
   302       npp_erase_row(npp, row);
       
   303 #endif
       
   304       npp_remove_row(npp, row);
       
   305       dmp_free_atom(npp->pool, row, sizeof(NPPROW));
       
   306       return;
       
   307 }
       
   308 
       
   309 void npp_del_col(NPP *npp, NPPCOL *col)
       
   310 {     /* remove column from the current problem */
       
   311       NPPAIJ *aij;
       
   312       if (col->name != NULL)
       
   313          dmp_free_atom(npp->pool, col->name, strlen(col->name)+1);
       
   314       while (col->ptr != NULL)
       
   315       {  aij = col->ptr;
       
   316          col->ptr = aij->c_next;
       
   317          if (aij->r_prev == NULL)
       
   318             aij->row->ptr = aij->r_next;
       
   319          else
       
   320             aij->r_prev->r_next = aij->r_next;
       
   321          if (aij->r_next == NULL)
       
   322             ;
       
   323          else
       
   324             aij->r_next->r_prev = aij->r_prev;
       
   325          dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
       
   326       }
       
   327       npp_remove_col(npp, col);
       
   328       dmp_free_atom(npp->pool, col, sizeof(NPPCOL));
       
   329       return;
       
   330 }
       
   331 
       
   332 void npp_del_aij(NPP *npp, NPPAIJ *aij)
       
   333 {     /* remove element from the constraint matrix */
       
   334       if (aij->r_prev == NULL)
       
   335          aij->row->ptr = aij->r_next;
       
   336       else
       
   337          aij->r_prev->r_next = aij->r_next;
       
   338       if (aij->r_next == NULL)
       
   339          ;
       
   340       else
       
   341          aij->r_next->r_prev = aij->r_prev;
       
   342       if (aij->c_prev == NULL)
       
   343          aij->col->ptr = aij->c_next;
       
   344       else
       
   345          aij->c_prev->c_next = aij->c_next;
       
   346       if (aij->c_next == NULL)
       
   347          ;
       
   348       else
       
   349          aij->c_next->c_prev = aij->c_prev;
       
   350       dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
       
   351       return;
       
   352 }
       
   353 
       
   354 void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol,
       
   355       int scaling)
       
   356 {     /* load original problem into the preprocessor workspace */
       
   357       int m = orig->m;
       
   358       int n = orig->n;
       
   359       NPPROW **link;
       
   360       int i, j;
       
   361       double dir;
       
   362       xassert(names == GLP_OFF || names == GLP_ON);
       
   363       xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP);
       
   364       xassert(scaling == GLP_OFF || scaling == GLP_ON);
       
   365       if (sol == GLP_MIP) xassert(!scaling);
       
   366       npp->orig_dir = orig->dir;
       
   367       if (npp->orig_dir == GLP_MIN)
       
   368          dir = +1.0;
       
   369       else if (npp->orig_dir == GLP_MAX)
       
   370          dir = -1.0;
       
   371       else
       
   372          xassert(npp != npp);
       
   373       npp->orig_m = m;
       
   374       npp->orig_n = n;
       
   375       npp->orig_nnz = orig->nnz;
       
   376       if (names && orig->name != NULL)
       
   377       {  npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1);
       
   378          strcpy(npp->name, orig->name);
       
   379       }
       
   380       if (names && orig->obj != NULL)
       
   381       {  npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1);
       
   382          strcpy(npp->obj, orig->obj);
       
   383       }
       
   384       npp->c0 = dir * orig->c0;
       
   385       /* load rows */
       
   386       link = xcalloc(1+m, sizeof(NPPROW *));
       
   387       for (i = 1; i <= m; i++)
       
   388       {  GLPROW *rrr = orig->row[i];
       
   389          NPPROW *row;
       
   390          link[i] = row = npp_add_row(npp);
       
   391          xassert(row->i == i);
       
   392          if (names && rrr->name != NULL)
       
   393          {  row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1);
       
   394             strcpy(row->name, rrr->name);
       
   395          }
       
   396          if (!scaling)
       
   397          {  if (rrr->type == GLP_FR)
       
   398                row->lb = -DBL_MAX, row->ub = +DBL_MAX;
       
   399             else if (rrr->type == GLP_LO)
       
   400                row->lb = rrr->lb, row->ub = +DBL_MAX;
       
   401             else if (rrr->type == GLP_UP)
       
   402                row->lb = -DBL_MAX, row->ub = rrr->ub;
       
   403             else if (rrr->type == GLP_DB)
       
   404                row->lb = rrr->lb, row->ub = rrr->ub;
       
   405             else if (rrr->type == GLP_FX)
       
   406                row->lb = row->ub = rrr->lb;
       
   407             else
       
   408                xassert(rrr != rrr);
       
   409          }
       
   410          else
       
   411          {  double rii = rrr->rii;
       
   412             if (rrr->type == GLP_FR)
       
   413                row->lb = -DBL_MAX, row->ub = +DBL_MAX;
       
   414             else if (rrr->type == GLP_LO)
       
   415                row->lb = rrr->lb * rii, row->ub = +DBL_MAX;
       
   416             else if (rrr->type == GLP_UP)
       
   417                row->lb = -DBL_MAX, row->ub = rrr->ub * rii;
       
   418             else if (rrr->type == GLP_DB)
       
   419                row->lb = rrr->lb * rii, row->ub = rrr->ub * rii;
       
   420             else if (rrr->type == GLP_FX)
       
   421                row->lb = row->ub = rrr->lb * rii;
       
   422             else
       
   423                xassert(rrr != rrr);
       
   424          }
       
   425       }
       
   426       /* load columns and constraint coefficients */
       
   427       for (j = 1; j <= n; j++)
       
   428       {  GLPCOL *ccc = orig->col[j];
       
   429          GLPAIJ *aaa;
       
   430          NPPCOL *col;
       
   431          col = npp_add_col(npp);
       
   432          xassert(col->j == j);
       
   433          if (names && ccc->name != NULL)
       
   434          {  col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1);
       
   435             strcpy(col->name, ccc->name);
       
   436          }
       
   437          if (sol == GLP_MIP)
       
   438 #if 0
       
   439             col->kind = ccc->kind;
       
   440 #else
       
   441             col->is_int = (char)(ccc->kind == GLP_IV);
       
   442 #endif
       
   443          if (!scaling)
       
   444          {  if (ccc->type == GLP_FR)
       
   445                col->lb = -DBL_MAX, col->ub = +DBL_MAX;
       
   446             else if (ccc->type == GLP_LO)
       
   447                col->lb = ccc->lb, col->ub = +DBL_MAX;
       
   448             else if (ccc->type == GLP_UP)
       
   449                col->lb = -DBL_MAX, col->ub = ccc->ub;
       
   450             else if (ccc->type == GLP_DB)
       
   451                col->lb = ccc->lb, col->ub = ccc->ub;
       
   452             else if (ccc->type == GLP_FX)
       
   453                col->lb = col->ub = ccc->lb;
       
   454             else
       
   455                xassert(ccc != ccc);
       
   456             col->coef = dir * ccc->coef;
       
   457             for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
       
   458                npp_add_aij(npp, link[aaa->row->i], col, aaa->val);
       
   459          }
       
   460          else
       
   461          {  double sjj = ccc->sjj;
       
   462             if (ccc->type == GLP_FR)
       
   463                col->lb = -DBL_MAX, col->ub = +DBL_MAX;
       
   464             else if (ccc->type == GLP_LO)
       
   465                col->lb = ccc->lb / sjj, col->ub = +DBL_MAX;
       
   466             else if (ccc->type == GLP_UP)
       
   467                col->lb = -DBL_MAX, col->ub = ccc->ub / sjj;
       
   468             else if (ccc->type == GLP_DB)
       
   469                col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj;
       
   470             else if (ccc->type == GLP_FX)
       
   471                col->lb = col->ub = ccc->lb / sjj;
       
   472             else
       
   473                xassert(ccc != ccc);
       
   474             col->coef = dir * ccc->coef * sjj;
       
   475             for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
       
   476                npp_add_aij(npp, link[aaa->row->i], col,
       
   477                   aaa->row->rii * aaa->val * sjj);
       
   478          }
       
   479       }
       
   480       xfree(link);
       
   481       /* keep solution indicator and scaling option */
       
   482       npp->sol = sol;
       
   483       npp->scaling = scaling;
       
   484       return;
       
   485 }
       
   486 
       
   487 void npp_build_prob(NPP *npp, glp_prob *prob)
       
   488 {     /* build resultant (preprocessed) problem */
       
   489       NPPROW *row;
       
   490       NPPCOL *col;
       
   491       NPPAIJ *aij;
       
   492       int i, j, type, len, *ind;
       
   493       double dir, *val;
       
   494       glp_erase_prob(prob);
       
   495       glp_set_prob_name(prob, npp->name);
       
   496       glp_set_obj_name(prob, npp->obj);
       
   497       glp_set_obj_dir(prob, npp->orig_dir);
       
   498       if (npp->orig_dir == GLP_MIN)
       
   499          dir = +1.0;
       
   500       else if (npp->orig_dir == GLP_MAX)
       
   501          dir = -1.0;
       
   502       else
       
   503          xassert(npp != npp);
       
   504       glp_set_obj_coef(prob, 0, dir * npp->c0);
       
   505       /* build rows */
       
   506       for (row = npp->r_head; row != NULL; row = row->next)
       
   507       {  row->temp = i = glp_add_rows(prob, 1);
       
   508          glp_set_row_name(prob, i, row->name);
       
   509          if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
       
   510             type = GLP_FR;
       
   511          else if (row->ub == +DBL_MAX)
       
   512             type = GLP_LO;
       
   513          else if (row->lb == -DBL_MAX)
       
   514             type = GLP_UP;
       
   515          else if (row->lb != row->ub)
       
   516             type = GLP_DB;
       
   517          else
       
   518             type = GLP_FX;
       
   519          glp_set_row_bnds(prob, i, type, row->lb, row->ub);
       
   520       }
       
   521       /* build columns and the constraint matrix */
       
   522       ind = xcalloc(1+prob->m, sizeof(int));
       
   523       val = xcalloc(1+prob->m, sizeof(double));
       
   524       for (col = npp->c_head; col != NULL; col = col->next)
       
   525       {  j = glp_add_cols(prob, 1);
       
   526          glp_set_col_name(prob, j, col->name);
       
   527 #if 0
       
   528          glp_set_col_kind(prob, j, col->kind);
       
   529 #else
       
   530          glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV);
       
   531 #endif
       
   532          if (col->lb == -DBL_MAX && col->ub == +DBL_MAX)
       
   533             type = GLP_FR;
       
   534          else if (col->ub == +DBL_MAX)
       
   535             type = GLP_LO;
       
   536          else if (col->lb == -DBL_MAX)
       
   537             type = GLP_UP;
       
   538          else if (col->lb != col->ub)
       
   539             type = GLP_DB;
       
   540          else
       
   541             type = GLP_FX;
       
   542          glp_set_col_bnds(prob, j, type, col->lb, col->ub);
       
   543          glp_set_obj_coef(prob, j, dir * col->coef);
       
   544          len = 0;
       
   545          for (aij = col->ptr; aij != NULL; aij = aij->c_next)
       
   546          {  len++;
       
   547             ind[len] = aij->row->temp;
       
   548             val[len] = aij->val;
       
   549          }
       
   550          glp_set_mat_col(prob, j, len, ind, val);
       
   551       }
       
   552       xfree(ind);
       
   553       xfree(val);
       
   554       /* resultant problem has been built */
       
   555       npp->m = prob->m;
       
   556       npp->n = prob->n;
       
   557       npp->nnz = prob->nnz;
       
   558       npp->row_ref = xcalloc(1+npp->m, sizeof(int));
       
   559       npp->col_ref = xcalloc(1+npp->n, sizeof(int));
       
   560       for (row = npp->r_head, i = 0; row != NULL; row = row->next)
       
   561          npp->row_ref[++i] = row->i;
       
   562       for (col = npp->c_head, j = 0; col != NULL; col = col->next)
       
   563          npp->col_ref[++j] = col->j;
       
   564       /* transformed problem segment is no longer needed */
       
   565       dmp_delete_pool(npp->pool), npp->pool = NULL;
       
   566       npp->name = npp->obj = NULL;
       
   567       npp->c0 = 0.0;
       
   568       npp->r_head = npp->r_tail = NULL;
       
   569       npp->c_head = npp->c_tail = NULL;
       
   570       return;
       
   571 }
       
   572 
       
   573 void npp_postprocess(NPP *npp, glp_prob *prob)
       
   574 {     /* postprocess solution from the resultant problem */
       
   575       GLPROW *row;
       
   576       GLPCOL *col;
       
   577       NPPTSE *tse;
       
   578       int i, j, k;
       
   579       double dir;
       
   580       xassert(npp->orig_dir == prob->dir);
       
   581       if (npp->orig_dir == GLP_MIN)
       
   582          dir = +1.0;
       
   583       else if (npp->orig_dir == GLP_MAX)
       
   584          dir = -1.0;
       
   585       else
       
   586          xassert(npp != npp);
       
   587       xassert(npp->m == prob->m);
       
   588       xassert(npp->n == prob->n);
       
   589       xassert(npp->nnz == prob->nnz);
       
   590       /* copy solution status */
       
   591       if (npp->sol == GLP_SOL)
       
   592       {  npp->p_stat = prob->pbs_stat;
       
   593          npp->d_stat = prob->dbs_stat;
       
   594       }
       
   595       else if (npp->sol == GLP_IPT)
       
   596          npp->t_stat = prob->ipt_stat;
       
   597       else if (npp->sol == GLP_MIP)
       
   598          npp->i_stat = prob->mip_stat;
       
   599       else
       
   600          xassert(npp != npp);
       
   601       /* allocate solution arrays */
       
   602       if (npp->sol == GLP_SOL)
       
   603       {  if (npp->r_stat == NULL)
       
   604             npp->r_stat = xcalloc(1+npp->nrows, sizeof(char));
       
   605          for (i = 1; i <= npp->nrows; i++)
       
   606             npp->r_stat[i] = 0;
       
   607          if (npp->c_stat == NULL)
       
   608             npp->c_stat = xcalloc(1+npp->ncols, sizeof(char));
       
   609          for (j = 1; j <= npp->ncols; j++)
       
   610             npp->c_stat[j] = 0;
       
   611       }
       
   612 #if 0
       
   613       if (npp->r_prim == NULL)
       
   614          npp->r_prim = xcalloc(1+npp->nrows, sizeof(double));
       
   615       for (i = 1; i <= npp->nrows; i++)
       
   616          npp->r_prim[i] = DBL_MAX;
       
   617 #endif
       
   618       if (npp->c_value == NULL)
       
   619          npp->c_value = xcalloc(1+npp->ncols, sizeof(double));
       
   620       for (j = 1; j <= npp->ncols; j++)
       
   621          npp->c_value[j] = DBL_MAX;
       
   622       if (npp->sol != GLP_MIP)
       
   623       {  if (npp->r_pi == NULL)
       
   624             npp->r_pi = xcalloc(1+npp->nrows, sizeof(double));
       
   625          for (i = 1; i <= npp->nrows; i++)
       
   626             npp->r_pi[i] = DBL_MAX;
       
   627 #if 0
       
   628          if (npp->c_dual == NULL)
       
   629             npp->c_dual = xcalloc(1+npp->ncols, sizeof(double));
       
   630          for (j = 1; j <= npp->ncols; j++)
       
   631             npp->c_dual[j] = DBL_MAX;
       
   632 #endif
       
   633       }
       
   634       /* copy solution components from the resultant problem */
       
   635       if (npp->sol == GLP_SOL)
       
   636       {  for (i = 1; i <= npp->m; i++)
       
   637          {  row = prob->row[i];
       
   638             k = npp->row_ref[i];
       
   639             npp->r_stat[k] = (char)row->stat;
       
   640             /*npp->r_prim[k] = row->prim;*/
       
   641             npp->r_pi[k] = dir * row->dual;
       
   642          }
       
   643          for (j = 1; j <= npp->n; j++)
       
   644          {  col = prob->col[j];
       
   645             k = npp->col_ref[j];
       
   646             npp->c_stat[k] = (char)col->stat;
       
   647             npp->c_value[k] = col->prim;
       
   648             /*npp->c_dual[k] = dir * col->dual;*/
       
   649          }
       
   650       }
       
   651       else if (npp->sol == GLP_IPT)
       
   652       {  for (i = 1; i <= npp->m; i++)
       
   653          {  row = prob->row[i];
       
   654             k = npp->row_ref[i];
       
   655             /*npp->r_prim[k] = row->pval;*/
       
   656             npp->r_pi[k] = dir * row->dval;
       
   657          }
       
   658          for (j = 1; j <= npp->n; j++)
       
   659          {  col = prob->col[j];
       
   660             k = npp->col_ref[j];
       
   661             npp->c_value[k] = col->pval;
       
   662             /*npp->c_dual[k] = dir * col->dval;*/
       
   663          }
       
   664       }
       
   665       else if (npp->sol == GLP_MIP)
       
   666       {
       
   667 #if 0
       
   668          for (i = 1; i <= npp->m; i++)
       
   669          {  row = prob->row[i];
       
   670             k = npp->row_ref[i];
       
   671             /*npp->r_prim[k] = row->mipx;*/
       
   672          }
       
   673 #endif
       
   674          for (j = 1; j <= npp->n; j++)
       
   675          {  col = prob->col[j];
       
   676             k = npp->col_ref[j];
       
   677             npp->c_value[k] = col->mipx;
       
   678          }
       
   679       }
       
   680       else
       
   681          xassert(npp != npp);
       
   682       /* perform postprocessing to construct solution to the original
       
   683          problem */
       
   684       for (tse = npp->top; tse != NULL; tse = tse->link)
       
   685       {  xassert(tse->func != NULL);
       
   686          xassert(tse->func(npp, tse->info) == 0);
       
   687       }
       
   688       return;
       
   689 }
       
   690 
       
   691 void npp_unload_sol(NPP *npp, glp_prob *orig)
       
   692 {     /* store solution to the original problem */
       
   693       GLPROW *row;
       
   694       GLPCOL *col;
       
   695       int i, j;
       
   696       double dir;
       
   697       xassert(npp->orig_dir == orig->dir);
       
   698       if (npp->orig_dir == GLP_MIN)
       
   699          dir = +1.0;
       
   700       else if (npp->orig_dir == GLP_MAX)
       
   701          dir = -1.0;
       
   702       else
       
   703          xassert(npp != npp);
       
   704       xassert(npp->orig_m == orig->m);
       
   705       xassert(npp->orig_n == orig->n);
       
   706       xassert(npp->orig_nnz == orig->nnz);
       
   707       if (npp->sol == GLP_SOL)
       
   708       {  /* store basic solution */
       
   709          orig->valid = 0;
       
   710          orig->pbs_stat = npp->p_stat;
       
   711          orig->dbs_stat = npp->d_stat;
       
   712          orig->obj_val = orig->c0;
       
   713          orig->some = 0;
       
   714          for (i = 1; i <= orig->m; i++)
       
   715          {  row = orig->row[i];
       
   716             row->stat = npp->r_stat[i];
       
   717             if (!npp->scaling)
       
   718             {  /*row->prim = npp->r_prim[i];*/
       
   719                row->dual = dir * npp->r_pi[i];
       
   720             }
       
   721             else
       
   722             {  /*row->prim = npp->r_prim[i] / row->rii;*/
       
   723                row->dual = dir * npp->r_pi[i] * row->rii;
       
   724             }
       
   725             if (row->stat == GLP_BS)
       
   726                row->dual = 0.0;
       
   727             else if (row->stat == GLP_NL)
       
   728             {  xassert(row->type == GLP_LO || row->type == GLP_DB);
       
   729                row->prim = row->lb;
       
   730             }
       
   731             else if (row->stat == GLP_NU)
       
   732             {  xassert(row->type == GLP_UP || row->type == GLP_DB);
       
   733                row->prim = row->ub;
       
   734             }
       
   735             else if (row->stat == GLP_NF)
       
   736             {  xassert(row->type == GLP_FR);
       
   737                row->prim = 0.0;
       
   738             }
       
   739             else if (row->stat == GLP_NS)
       
   740             {  xassert(row->type == GLP_FX);
       
   741                row->prim = row->lb;
       
   742             }
       
   743             else
       
   744                xassert(row != row);
       
   745          }
       
   746          for (j = 1; j <= orig->n; j++)
       
   747          {  col = orig->col[j];
       
   748             col->stat = npp->c_stat[j];
       
   749             if (!npp->scaling)
       
   750             {  col->prim = npp->c_value[j];
       
   751                /*col->dual = dir * npp->c_dual[j];*/
       
   752             }
       
   753             else
       
   754             {  col->prim = npp->c_value[j] * col->sjj;
       
   755                /*col->dual = dir * npp->c_dual[j] / col->sjj;*/
       
   756             }
       
   757             if (col->stat == GLP_BS)
       
   758                col->dual = 0.0;
       
   759 #if 1
       
   760             else if (col->stat == GLP_NL)
       
   761             {  xassert(col->type == GLP_LO || col->type == GLP_DB);
       
   762                col->prim = col->lb;
       
   763             }
       
   764             else if (col->stat == GLP_NU)
       
   765             {  xassert(col->type == GLP_UP || col->type == GLP_DB);
       
   766                col->prim = col->ub;
       
   767             }
       
   768             else if (col->stat == GLP_NF)
       
   769             {  xassert(col->type == GLP_FR);
       
   770                col->prim = 0.0;
       
   771             }
       
   772             else if (col->stat == GLP_NS)
       
   773             {  xassert(col->type == GLP_FX);
       
   774                col->prim = col->lb;
       
   775             }
       
   776             else
       
   777                xassert(col != col);
       
   778 #endif
       
   779             orig->obj_val += col->coef * col->prim;
       
   780          }
       
   781 #if 1
       
   782          /* compute primal values of inactive rows */
       
   783          for (i = 1; i <= orig->m; i++)
       
   784          {  row = orig->row[i];
       
   785             if (row->stat == GLP_BS)
       
   786             {  GLPAIJ *aij;
       
   787                double temp;
       
   788                temp = 0.0;
       
   789                for (aij = row->ptr; aij != NULL; aij = aij->r_next)
       
   790                   temp += aij->val * aij->col->prim;
       
   791                row->prim = temp;
       
   792             }
       
   793          }
       
   794          /* compute reduced costs of active columns */
       
   795          for (j = 1; j <= orig->n; j++)
       
   796          {  col = orig->col[j];
       
   797             if (col->stat != GLP_BS)
       
   798             {  GLPAIJ *aij;
       
   799                double temp;
       
   800                temp = col->coef;
       
   801                for (aij = col->ptr; aij != NULL; aij = aij->c_next)
       
   802                   temp -= aij->val * aij->row->dual;
       
   803                col->dual = temp;
       
   804             }
       
   805          }
       
   806 #endif
       
   807       }
       
   808       else if (npp->sol == GLP_IPT)
       
   809       {  /* store interior-point solution */
       
   810          orig->ipt_stat = npp->t_stat;
       
   811          orig->ipt_obj = orig->c0;
       
   812          for (i = 1; i <= orig->m; i++)
       
   813          {  row = orig->row[i];
       
   814             if (!npp->scaling)
       
   815             {  /*row->pval = npp->r_prim[i];*/
       
   816                row->dval = dir * npp->r_pi[i];
       
   817             }
       
   818             else
       
   819             {  /*row->pval = npp->r_prim[i] / row->rii;*/
       
   820                row->dval = dir * npp->r_pi[i] * row->rii;
       
   821             }
       
   822          }
       
   823          for (j = 1; j <= orig->n; j++)
       
   824          {  col = orig->col[j];
       
   825             if (!npp->scaling)
       
   826             {  col->pval = npp->c_value[j];
       
   827                /*col->dval = dir * npp->c_dual[j];*/
       
   828             }
       
   829             else
       
   830             {  col->pval = npp->c_value[j] * col->sjj;
       
   831                /*col->dval = dir * npp->c_dual[j] / col->sjj;*/
       
   832             }
       
   833             orig->ipt_obj += col->coef * col->pval;
       
   834          }
       
   835 #if 1
       
   836          /* compute row primal values */
       
   837          for (i = 1; i <= orig->m; i++)
       
   838          {  row = orig->row[i];
       
   839             {  GLPAIJ *aij;
       
   840                double temp;
       
   841                temp = 0.0;
       
   842                for (aij = row->ptr; aij != NULL; aij = aij->r_next)
       
   843                   temp += aij->val * aij->col->pval;
       
   844                row->pval = temp;
       
   845             }
       
   846          }
       
   847          /* compute column dual values */
       
   848          for (j = 1; j <= orig->n; j++)
       
   849          {  col = orig->col[j];
       
   850             {  GLPAIJ *aij;
       
   851                double temp;
       
   852                temp = col->coef;
       
   853                for (aij = col->ptr; aij != NULL; aij = aij->c_next)
       
   854                   temp -= aij->val * aij->row->dval;
       
   855                col->dval = temp;
       
   856             }
       
   857          }
       
   858 #endif
       
   859       }
       
   860       else if (npp->sol == GLP_MIP)
       
   861       {  /* store MIP solution */
       
   862          xassert(!npp->scaling);
       
   863          orig->mip_stat = npp->i_stat;
       
   864          orig->mip_obj = orig->c0;
       
   865 #if 0
       
   866          for (i = 1; i <= orig->m; i++)
       
   867          {  row = orig->row[i];
       
   868             /*row->mipx = npp->r_prim[i];*/
       
   869          }
       
   870 #endif
       
   871          for (j = 1; j <= orig->n; j++)
       
   872          {  col = orig->col[j];
       
   873             col->mipx = npp->c_value[j];
       
   874             if (col->kind == GLP_IV)
       
   875                xassert(col->mipx == floor(col->mipx));
       
   876             orig->mip_obj += col->coef * col->mipx;
       
   877          }
       
   878 #if 1
       
   879          /* compute row primal values */
       
   880          for (i = 1; i <= orig->m; i++)
       
   881          {  row = orig->row[i];
       
   882             {  GLPAIJ *aij;
       
   883                double temp;
       
   884                temp = 0.0;
       
   885                for (aij = row->ptr; aij != NULL; aij = aij->r_next)
       
   886                   temp += aij->val * aij->col->mipx;
       
   887                row->mipx = temp;
       
   888             }
       
   889          }
       
   890 #endif
       
   891       }
       
   892       else
       
   893          xassert(npp != npp);
       
   894       return;
       
   895 }
       
   896 
       
   897 void npp_delete_wksp(NPP *npp)
       
   898 {     /* delete LP/MIP preprocessor workspace */
       
   899       if (npp->pool != NULL)
       
   900          dmp_delete_pool(npp->pool);
       
   901       if (npp->stack != NULL)
       
   902          dmp_delete_pool(npp->stack);
       
   903       if (npp->row_ref != NULL)
       
   904          xfree(npp->row_ref);
       
   905       if (npp->col_ref != NULL)
       
   906          xfree(npp->col_ref);
       
   907       if (npp->r_stat != NULL)
       
   908          xfree(npp->r_stat);
       
   909 #if 0
       
   910       if (npp->r_prim != NULL)
       
   911          xfree(npp->r_prim);
       
   912 #endif
       
   913       if (npp->r_pi != NULL)
       
   914          xfree(npp->r_pi);
       
   915       if (npp->c_stat != NULL)
       
   916          xfree(npp->c_stat);
       
   917       if (npp->c_value != NULL)
       
   918          xfree(npp->c_value);
       
   919 #if 0
       
   920       if (npp->c_dual != NULL)
       
   921          xfree(npp->c_dual);
       
   922 #endif
       
   923       xfree(npp);
       
   924       return;
       
   925 }
       
   926 
       
   927 /* eof */