alpar@1: /* glpnpp01.c */ alpar@1: alpar@1: /*********************************************************************** alpar@1: * This code is part of GLPK (GNU Linear Programming Kit). alpar@1: * alpar@1: * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, alpar@1: * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, alpar@1: * Moscow Aviation Institute, Moscow, Russia. All rights reserved. alpar@1: * E-mail: . alpar@1: * alpar@1: * GLPK is free software: you can redistribute it and/or modify it alpar@1: * under the terms of the GNU General Public License as published by alpar@1: * the Free Software Foundation, either version 3 of the License, or alpar@1: * (at your option) any later version. alpar@1: * alpar@1: * GLPK is distributed in the hope that it will be useful, but WITHOUT alpar@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY alpar@1: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public alpar@1: * License for more details. alpar@1: * alpar@1: * You should have received a copy of the GNU General Public License alpar@1: * along with GLPK. If not, see . alpar@1: ***********************************************************************/ alpar@1: alpar@1: #include "glpnpp.h" alpar@1: alpar@1: NPP *npp_create_wksp(void) alpar@1: { /* create LP/MIP preprocessor workspace */ alpar@1: NPP *npp; alpar@1: npp = xmalloc(sizeof(NPP)); alpar@1: npp->orig_dir = 0; alpar@1: npp->orig_m = npp->orig_n = npp->orig_nnz = 0; alpar@1: npp->pool = dmp_create_pool(); alpar@1: npp->name = npp->obj = NULL; alpar@1: npp->c0 = 0.0; alpar@1: npp->nrows = npp->ncols = 0; alpar@1: npp->r_head = npp->r_tail = NULL; alpar@1: npp->c_head = npp->c_tail = NULL; alpar@1: npp->stack = dmp_create_pool(); alpar@1: npp->top = NULL; alpar@1: #if 0 /* 16/XII-2009 */ alpar@1: memset(&npp->count, 0, sizeof(npp->count)); alpar@1: #endif alpar@1: npp->m = npp->n = npp->nnz = 0; alpar@1: npp->row_ref = npp->col_ref = NULL; alpar@1: npp->sol = npp->scaling = 0; alpar@1: npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0; alpar@1: npp->r_stat = NULL; alpar@1: /*npp->r_prim =*/ npp->r_pi = NULL; alpar@1: npp->c_stat = NULL; alpar@1: npp->c_value = /*npp->c_dual =*/ NULL; alpar@1: return npp; alpar@1: } alpar@1: alpar@1: void npp_insert_row(NPP *npp, NPPROW *row, int where) alpar@1: { /* insert row to the row list */ alpar@1: if (where == 0) alpar@1: { /* insert row to the beginning of the row list */ alpar@1: row->prev = NULL; alpar@1: row->next = npp->r_head; alpar@1: if (row->next == NULL) alpar@1: npp->r_tail = row; alpar@1: else alpar@1: row->next->prev = row; alpar@1: npp->r_head = row; alpar@1: } alpar@1: else alpar@1: { /* insert row to the end of the row list */ alpar@1: row->prev = npp->r_tail; alpar@1: row->next = NULL; alpar@1: if (row->prev == NULL) alpar@1: npp->r_head = row; alpar@1: else alpar@1: row->prev->next = row; alpar@1: npp->r_tail = row; alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_remove_row(NPP *npp, NPPROW *row) alpar@1: { /* remove row from the row list */ alpar@1: if (row->prev == NULL) alpar@1: npp->r_head = row->next; alpar@1: else alpar@1: row->prev->next = row->next; alpar@1: if (row->next == NULL) alpar@1: npp->r_tail = row->prev; alpar@1: else alpar@1: row->next->prev = row->prev; alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_activate_row(NPP *npp, NPPROW *row) alpar@1: { /* make row active */ alpar@1: if (!row->temp) alpar@1: { row->temp = 1; alpar@1: /* move the row to the beginning of the row list */ alpar@1: npp_remove_row(npp, row); alpar@1: npp_insert_row(npp, row, 0); alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_deactivate_row(NPP *npp, NPPROW *row) alpar@1: { /* make row inactive */ alpar@1: if (row->temp) alpar@1: { row->temp = 0; alpar@1: /* move the row to the end of the row list */ alpar@1: npp_remove_row(npp, row); alpar@1: npp_insert_row(npp, row, 1); alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_insert_col(NPP *npp, NPPCOL *col, int where) alpar@1: { /* insert column to the column list */ alpar@1: if (where == 0) alpar@1: { /* insert column to the beginning of the column list */ alpar@1: col->prev = NULL; alpar@1: col->next = npp->c_head; alpar@1: if (col->next == NULL) alpar@1: npp->c_tail = col; alpar@1: else alpar@1: col->next->prev = col; alpar@1: npp->c_head = col; alpar@1: } alpar@1: else alpar@1: { /* insert column to the end of the column list */ alpar@1: col->prev = npp->c_tail; alpar@1: col->next = NULL; alpar@1: if (col->prev == NULL) alpar@1: npp->c_head = col; alpar@1: else alpar@1: col->prev->next = col; alpar@1: npp->c_tail = col; alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_remove_col(NPP *npp, NPPCOL *col) alpar@1: { /* remove column from the column list */ alpar@1: if (col->prev == NULL) alpar@1: npp->c_head = col->next; alpar@1: else alpar@1: col->prev->next = col->next; alpar@1: if (col->next == NULL) alpar@1: npp->c_tail = col->prev; alpar@1: else alpar@1: col->next->prev = col->prev; alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_activate_col(NPP *npp, NPPCOL *col) alpar@1: { /* make column active */ alpar@1: if (!col->temp) alpar@1: { col->temp = 1; alpar@1: /* move the column to the beginning of the column list */ alpar@1: npp_remove_col(npp, col); alpar@1: npp_insert_col(npp, col, 0); alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_deactivate_col(NPP *npp, NPPCOL *col) alpar@1: { /* make column inactive */ alpar@1: if (col->temp) alpar@1: { col->temp = 0; alpar@1: /* move the column to the end of the column list */ alpar@1: npp_remove_col(npp, col); alpar@1: npp_insert_col(npp, col, 1); alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: NPPROW *npp_add_row(NPP *npp) alpar@1: { /* add new row to the current problem */ alpar@1: NPPROW *row; alpar@1: row = dmp_get_atom(npp->pool, sizeof(NPPROW)); alpar@1: row->i = ++(npp->nrows); alpar@1: row->name = NULL; alpar@1: row->lb = -DBL_MAX, row->ub = +DBL_MAX; alpar@1: row->ptr = NULL; alpar@1: row->temp = 0; alpar@1: npp_insert_row(npp, row, 1); alpar@1: return row; alpar@1: } alpar@1: alpar@1: NPPCOL *npp_add_col(NPP *npp) alpar@1: { /* add new column to the current problem */ alpar@1: NPPCOL *col; alpar@1: col = dmp_get_atom(npp->pool, sizeof(NPPCOL)); alpar@1: col->j = ++(npp->ncols); alpar@1: col->name = NULL; alpar@1: #if 0 alpar@1: col->kind = GLP_CV; alpar@1: #else alpar@1: col->is_int = 0; alpar@1: #endif alpar@1: col->lb = col->ub = col->coef = 0.0; alpar@1: col->ptr = NULL; alpar@1: col->temp = 0; alpar@1: npp_insert_col(npp, col, 1); alpar@1: return col; alpar@1: } alpar@1: alpar@1: NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val) alpar@1: { /* add new element to the constraint matrix */ alpar@1: NPPAIJ *aij; alpar@1: aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ)); alpar@1: aij->row = row; alpar@1: aij->col = col; alpar@1: aij->val = val; alpar@1: aij->r_prev = NULL; alpar@1: aij->r_next = row->ptr; alpar@1: aij->c_prev = NULL; alpar@1: aij->c_next = col->ptr; alpar@1: if (aij->r_next != NULL) alpar@1: aij->r_next->r_prev = aij; alpar@1: if (aij->c_next != NULL) alpar@1: aij->c_next->c_prev = aij; alpar@1: row->ptr = col->ptr = aij; alpar@1: return aij; alpar@1: } alpar@1: alpar@1: int npp_row_nnz(NPP *npp, NPPROW *row) alpar@1: { /* count number of non-zero coefficients in row */ alpar@1: NPPAIJ *aij; alpar@1: int nnz; alpar@1: xassert(npp == npp); alpar@1: nnz = 0; alpar@1: for (aij = row->ptr; aij != NULL; aij = aij->r_next) alpar@1: nnz++; alpar@1: return nnz; alpar@1: } alpar@1: alpar@1: int npp_col_nnz(NPP *npp, NPPCOL *col) alpar@1: { /* count number of non-zero coefficients in column */ alpar@1: NPPAIJ *aij; alpar@1: int nnz; alpar@1: xassert(npp == npp); alpar@1: nnz = 0; alpar@1: for (aij = col->ptr; aij != NULL; aij = aij->c_next) alpar@1: nnz++; alpar@1: return nnz; alpar@1: } alpar@1: alpar@1: void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), alpar@1: int size) alpar@1: { /* push new entry to the transformation stack */ alpar@1: NPPTSE *tse; alpar@1: tse = dmp_get_atom(npp->stack, sizeof(NPPTSE)); alpar@1: tse->func = func; alpar@1: tse->info = dmp_get_atom(npp->stack, size); alpar@1: tse->link = npp->top; alpar@1: npp->top = tse; alpar@1: return tse->info; alpar@1: } alpar@1: alpar@1: #if 1 /* 23/XII-2009 */ alpar@1: void npp_erase_row(NPP *npp, NPPROW *row) alpar@1: { /* erase row content to make it empty */ alpar@1: NPPAIJ *aij; alpar@1: while (row->ptr != NULL) alpar@1: { aij = row->ptr; alpar@1: row->ptr = aij->r_next; alpar@1: if (aij->c_prev == NULL) alpar@1: aij->col->ptr = aij->c_next; alpar@1: else alpar@1: aij->c_prev->c_next = aij->c_next; alpar@1: if (aij->c_next == NULL) alpar@1: ; alpar@1: else alpar@1: aij->c_next->c_prev = aij->c_prev; alpar@1: dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); alpar@1: } alpar@1: return; alpar@1: } alpar@1: #endif alpar@1: alpar@1: void npp_del_row(NPP *npp, NPPROW *row) alpar@1: { /* remove row from the current problem */ alpar@1: #if 0 /* 23/XII-2009 */ alpar@1: NPPAIJ *aij; alpar@1: #endif alpar@1: if (row->name != NULL) alpar@1: dmp_free_atom(npp->pool, row->name, strlen(row->name)+1); alpar@1: #if 0 /* 23/XII-2009 */ alpar@1: while (row->ptr != NULL) alpar@1: { aij = row->ptr; alpar@1: row->ptr = aij->r_next; alpar@1: if (aij->c_prev == NULL) alpar@1: aij->col->ptr = aij->c_next; alpar@1: else alpar@1: aij->c_prev->c_next = aij->c_next; alpar@1: if (aij->c_next == NULL) alpar@1: ; alpar@1: else alpar@1: aij->c_next->c_prev = aij->c_prev; alpar@1: dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); alpar@1: } alpar@1: #else alpar@1: npp_erase_row(npp, row); alpar@1: #endif alpar@1: npp_remove_row(npp, row); alpar@1: dmp_free_atom(npp->pool, row, sizeof(NPPROW)); alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_del_col(NPP *npp, NPPCOL *col) alpar@1: { /* remove column from the current problem */ alpar@1: NPPAIJ *aij; alpar@1: if (col->name != NULL) alpar@1: dmp_free_atom(npp->pool, col->name, strlen(col->name)+1); alpar@1: while (col->ptr != NULL) alpar@1: { aij = col->ptr; alpar@1: col->ptr = aij->c_next; alpar@1: if (aij->r_prev == NULL) alpar@1: aij->row->ptr = aij->r_next; alpar@1: else alpar@1: aij->r_prev->r_next = aij->r_next; alpar@1: if (aij->r_next == NULL) alpar@1: ; alpar@1: else alpar@1: aij->r_next->r_prev = aij->r_prev; alpar@1: dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); alpar@1: } alpar@1: npp_remove_col(npp, col); alpar@1: dmp_free_atom(npp->pool, col, sizeof(NPPCOL)); alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_del_aij(NPP *npp, NPPAIJ *aij) alpar@1: { /* remove element from the constraint matrix */ alpar@1: if (aij->r_prev == NULL) alpar@1: aij->row->ptr = aij->r_next; alpar@1: else alpar@1: aij->r_prev->r_next = aij->r_next; alpar@1: if (aij->r_next == NULL) alpar@1: ; alpar@1: else alpar@1: aij->r_next->r_prev = aij->r_prev; alpar@1: if (aij->c_prev == NULL) alpar@1: aij->col->ptr = aij->c_next; alpar@1: else alpar@1: aij->c_prev->c_next = aij->c_next; alpar@1: if (aij->c_next == NULL) alpar@1: ; alpar@1: else alpar@1: aij->c_next->c_prev = aij->c_prev; alpar@1: dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, alpar@1: int scaling) alpar@1: { /* load original problem into the preprocessor workspace */ alpar@1: int m = orig->m; alpar@1: int n = orig->n; alpar@1: NPPROW **link; alpar@1: int i, j; alpar@1: double dir; alpar@1: xassert(names == GLP_OFF || names == GLP_ON); alpar@1: xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP); alpar@1: xassert(scaling == GLP_OFF || scaling == GLP_ON); alpar@1: if (sol == GLP_MIP) xassert(!scaling); alpar@1: npp->orig_dir = orig->dir; alpar@1: if (npp->orig_dir == GLP_MIN) alpar@1: dir = +1.0; alpar@1: else if (npp->orig_dir == GLP_MAX) alpar@1: dir = -1.0; alpar@1: else alpar@1: xassert(npp != npp); alpar@1: npp->orig_m = m; alpar@1: npp->orig_n = n; alpar@1: npp->orig_nnz = orig->nnz; alpar@1: if (names && orig->name != NULL) alpar@1: { npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1); alpar@1: strcpy(npp->name, orig->name); alpar@1: } alpar@1: if (names && orig->obj != NULL) alpar@1: { npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1); alpar@1: strcpy(npp->obj, orig->obj); alpar@1: } alpar@1: npp->c0 = dir * orig->c0; alpar@1: /* load rows */ alpar@1: link = xcalloc(1+m, sizeof(NPPROW *)); alpar@1: for (i = 1; i <= m; i++) alpar@1: { GLPROW *rrr = orig->row[i]; alpar@1: NPPROW *row; alpar@1: link[i] = row = npp_add_row(npp); alpar@1: xassert(row->i == i); alpar@1: if (names && rrr->name != NULL) alpar@1: { row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1); alpar@1: strcpy(row->name, rrr->name); alpar@1: } alpar@1: if (!scaling) alpar@1: { if (rrr->type == GLP_FR) alpar@1: row->lb = -DBL_MAX, row->ub = +DBL_MAX; alpar@1: else if (rrr->type == GLP_LO) alpar@1: row->lb = rrr->lb, row->ub = +DBL_MAX; alpar@1: else if (rrr->type == GLP_UP) alpar@1: row->lb = -DBL_MAX, row->ub = rrr->ub; alpar@1: else if (rrr->type == GLP_DB) alpar@1: row->lb = rrr->lb, row->ub = rrr->ub; alpar@1: else if (rrr->type == GLP_FX) alpar@1: row->lb = row->ub = rrr->lb; alpar@1: else alpar@1: xassert(rrr != rrr); alpar@1: } alpar@1: else alpar@1: { double rii = rrr->rii; alpar@1: if (rrr->type == GLP_FR) alpar@1: row->lb = -DBL_MAX, row->ub = +DBL_MAX; alpar@1: else if (rrr->type == GLP_LO) alpar@1: row->lb = rrr->lb * rii, row->ub = +DBL_MAX; alpar@1: else if (rrr->type == GLP_UP) alpar@1: row->lb = -DBL_MAX, row->ub = rrr->ub * rii; alpar@1: else if (rrr->type == GLP_DB) alpar@1: row->lb = rrr->lb * rii, row->ub = rrr->ub * rii; alpar@1: else if (rrr->type == GLP_FX) alpar@1: row->lb = row->ub = rrr->lb * rii; alpar@1: else alpar@1: xassert(rrr != rrr); alpar@1: } alpar@1: } alpar@1: /* load columns and constraint coefficients */ alpar@1: for (j = 1; j <= n; j++) alpar@1: { GLPCOL *ccc = orig->col[j]; alpar@1: GLPAIJ *aaa; alpar@1: NPPCOL *col; alpar@1: col = npp_add_col(npp); alpar@1: xassert(col->j == j); alpar@1: if (names && ccc->name != NULL) alpar@1: { col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1); alpar@1: strcpy(col->name, ccc->name); alpar@1: } alpar@1: if (sol == GLP_MIP) alpar@1: #if 0 alpar@1: col->kind = ccc->kind; alpar@1: #else alpar@1: col->is_int = (char)(ccc->kind == GLP_IV); alpar@1: #endif alpar@1: if (!scaling) alpar@1: { if (ccc->type == GLP_FR) alpar@1: col->lb = -DBL_MAX, col->ub = +DBL_MAX; alpar@1: else if (ccc->type == GLP_LO) alpar@1: col->lb = ccc->lb, col->ub = +DBL_MAX; alpar@1: else if (ccc->type == GLP_UP) alpar@1: col->lb = -DBL_MAX, col->ub = ccc->ub; alpar@1: else if (ccc->type == GLP_DB) alpar@1: col->lb = ccc->lb, col->ub = ccc->ub; alpar@1: else if (ccc->type == GLP_FX) alpar@1: col->lb = col->ub = ccc->lb; alpar@1: else alpar@1: xassert(ccc != ccc); alpar@1: col->coef = dir * ccc->coef; alpar@1: for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) alpar@1: npp_add_aij(npp, link[aaa->row->i], col, aaa->val); alpar@1: } alpar@1: else alpar@1: { double sjj = ccc->sjj; alpar@1: if (ccc->type == GLP_FR) alpar@1: col->lb = -DBL_MAX, col->ub = +DBL_MAX; alpar@1: else if (ccc->type == GLP_LO) alpar@1: col->lb = ccc->lb / sjj, col->ub = +DBL_MAX; alpar@1: else if (ccc->type == GLP_UP) alpar@1: col->lb = -DBL_MAX, col->ub = ccc->ub / sjj; alpar@1: else if (ccc->type == GLP_DB) alpar@1: col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj; alpar@1: else if (ccc->type == GLP_FX) alpar@1: col->lb = col->ub = ccc->lb / sjj; alpar@1: else alpar@1: xassert(ccc != ccc); alpar@1: col->coef = dir * ccc->coef * sjj; alpar@1: for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) alpar@1: npp_add_aij(npp, link[aaa->row->i], col, alpar@1: aaa->row->rii * aaa->val * sjj); alpar@1: } alpar@1: } alpar@1: xfree(link); alpar@1: /* keep solution indicator and scaling option */ alpar@1: npp->sol = sol; alpar@1: npp->scaling = scaling; alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_build_prob(NPP *npp, glp_prob *prob) alpar@1: { /* build resultant (preprocessed) problem */ alpar@1: NPPROW *row; alpar@1: NPPCOL *col; alpar@1: NPPAIJ *aij; alpar@1: int i, j, type, len, *ind; alpar@1: double dir, *val; alpar@1: glp_erase_prob(prob); alpar@1: glp_set_prob_name(prob, npp->name); alpar@1: glp_set_obj_name(prob, npp->obj); alpar@1: glp_set_obj_dir(prob, npp->orig_dir); alpar@1: if (npp->orig_dir == GLP_MIN) alpar@1: dir = +1.0; alpar@1: else if (npp->orig_dir == GLP_MAX) alpar@1: dir = -1.0; alpar@1: else alpar@1: xassert(npp != npp); alpar@1: glp_set_obj_coef(prob, 0, dir * npp->c0); alpar@1: /* build rows */ alpar@1: for (row = npp->r_head; row != NULL; row = row->next) alpar@1: { row->temp = i = glp_add_rows(prob, 1); alpar@1: glp_set_row_name(prob, i, row->name); alpar@1: if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) alpar@1: type = GLP_FR; alpar@1: else if (row->ub == +DBL_MAX) alpar@1: type = GLP_LO; alpar@1: else if (row->lb == -DBL_MAX) alpar@1: type = GLP_UP; alpar@1: else if (row->lb != row->ub) alpar@1: type = GLP_DB; alpar@1: else alpar@1: type = GLP_FX; alpar@1: glp_set_row_bnds(prob, i, type, row->lb, row->ub); alpar@1: } alpar@1: /* build columns and the constraint matrix */ alpar@1: ind = xcalloc(1+prob->m, sizeof(int)); alpar@1: val = xcalloc(1+prob->m, sizeof(double)); alpar@1: for (col = npp->c_head; col != NULL; col = col->next) alpar@1: { j = glp_add_cols(prob, 1); alpar@1: glp_set_col_name(prob, j, col->name); alpar@1: #if 0 alpar@1: glp_set_col_kind(prob, j, col->kind); alpar@1: #else alpar@1: glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV); alpar@1: #endif alpar@1: if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) alpar@1: type = GLP_FR; alpar@1: else if (col->ub == +DBL_MAX) alpar@1: type = GLP_LO; alpar@1: else if (col->lb == -DBL_MAX) alpar@1: type = GLP_UP; alpar@1: else if (col->lb != col->ub) alpar@1: type = GLP_DB; alpar@1: else alpar@1: type = GLP_FX; alpar@1: glp_set_col_bnds(prob, j, type, col->lb, col->ub); alpar@1: glp_set_obj_coef(prob, j, dir * col->coef); alpar@1: len = 0; alpar@1: for (aij = col->ptr; aij != NULL; aij = aij->c_next) alpar@1: { len++; alpar@1: ind[len] = aij->row->temp; alpar@1: val[len] = aij->val; alpar@1: } alpar@1: glp_set_mat_col(prob, j, len, ind, val); alpar@1: } alpar@1: xfree(ind); alpar@1: xfree(val); alpar@1: /* resultant problem has been built */ alpar@1: npp->m = prob->m; alpar@1: npp->n = prob->n; alpar@1: npp->nnz = prob->nnz; alpar@1: npp->row_ref = xcalloc(1+npp->m, sizeof(int)); alpar@1: npp->col_ref = xcalloc(1+npp->n, sizeof(int)); alpar@1: for (row = npp->r_head, i = 0; row != NULL; row = row->next) alpar@1: npp->row_ref[++i] = row->i; alpar@1: for (col = npp->c_head, j = 0; col != NULL; col = col->next) alpar@1: npp->col_ref[++j] = col->j; alpar@1: /* transformed problem segment is no longer needed */ alpar@1: dmp_delete_pool(npp->pool), npp->pool = NULL; alpar@1: npp->name = npp->obj = NULL; alpar@1: npp->c0 = 0.0; alpar@1: npp->r_head = npp->r_tail = NULL; alpar@1: npp->c_head = npp->c_tail = NULL; alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_postprocess(NPP *npp, glp_prob *prob) alpar@1: { /* postprocess solution from the resultant problem */ alpar@1: GLPROW *row; alpar@1: GLPCOL *col; alpar@1: NPPTSE *tse; alpar@1: int i, j, k; alpar@1: double dir; alpar@1: xassert(npp->orig_dir == prob->dir); alpar@1: if (npp->orig_dir == GLP_MIN) alpar@1: dir = +1.0; alpar@1: else if (npp->orig_dir == GLP_MAX) alpar@1: dir = -1.0; alpar@1: else alpar@1: xassert(npp != npp); alpar@1: xassert(npp->m == prob->m); alpar@1: xassert(npp->n == prob->n); alpar@1: xassert(npp->nnz == prob->nnz); alpar@1: /* copy solution status */ alpar@1: if (npp->sol == GLP_SOL) alpar@1: { npp->p_stat = prob->pbs_stat; alpar@1: npp->d_stat = prob->dbs_stat; alpar@1: } alpar@1: else if (npp->sol == GLP_IPT) alpar@1: npp->t_stat = prob->ipt_stat; alpar@1: else if (npp->sol == GLP_MIP) alpar@1: npp->i_stat = prob->mip_stat; alpar@1: else alpar@1: xassert(npp != npp); alpar@1: /* allocate solution arrays */ alpar@1: if (npp->sol == GLP_SOL) alpar@1: { if (npp->r_stat == NULL) alpar@1: npp->r_stat = xcalloc(1+npp->nrows, sizeof(char)); alpar@1: for (i = 1; i <= npp->nrows; i++) alpar@1: npp->r_stat[i] = 0; alpar@1: if (npp->c_stat == NULL) alpar@1: npp->c_stat = xcalloc(1+npp->ncols, sizeof(char)); alpar@1: for (j = 1; j <= npp->ncols; j++) alpar@1: npp->c_stat[j] = 0; alpar@1: } alpar@1: #if 0 alpar@1: if (npp->r_prim == NULL) alpar@1: npp->r_prim = xcalloc(1+npp->nrows, sizeof(double)); alpar@1: for (i = 1; i <= npp->nrows; i++) alpar@1: npp->r_prim[i] = DBL_MAX; alpar@1: #endif alpar@1: if (npp->c_value == NULL) alpar@1: npp->c_value = xcalloc(1+npp->ncols, sizeof(double)); alpar@1: for (j = 1; j <= npp->ncols; j++) alpar@1: npp->c_value[j] = DBL_MAX; alpar@1: if (npp->sol != GLP_MIP) alpar@1: { if (npp->r_pi == NULL) alpar@1: npp->r_pi = xcalloc(1+npp->nrows, sizeof(double)); alpar@1: for (i = 1; i <= npp->nrows; i++) alpar@1: npp->r_pi[i] = DBL_MAX; alpar@1: #if 0 alpar@1: if (npp->c_dual == NULL) alpar@1: npp->c_dual = xcalloc(1+npp->ncols, sizeof(double)); alpar@1: for (j = 1; j <= npp->ncols; j++) alpar@1: npp->c_dual[j] = DBL_MAX; alpar@1: #endif alpar@1: } alpar@1: /* copy solution components from the resultant problem */ alpar@1: if (npp->sol == GLP_SOL) alpar@1: { for (i = 1; i <= npp->m; i++) alpar@1: { row = prob->row[i]; alpar@1: k = npp->row_ref[i]; alpar@1: npp->r_stat[k] = (char)row->stat; alpar@1: /*npp->r_prim[k] = row->prim;*/ alpar@1: npp->r_pi[k] = dir * row->dual; alpar@1: } alpar@1: for (j = 1; j <= npp->n; j++) alpar@1: { col = prob->col[j]; alpar@1: k = npp->col_ref[j]; alpar@1: npp->c_stat[k] = (char)col->stat; alpar@1: npp->c_value[k] = col->prim; alpar@1: /*npp->c_dual[k] = dir * col->dual;*/ alpar@1: } alpar@1: } alpar@1: else if (npp->sol == GLP_IPT) alpar@1: { for (i = 1; i <= npp->m; i++) alpar@1: { row = prob->row[i]; alpar@1: k = npp->row_ref[i]; alpar@1: /*npp->r_prim[k] = row->pval;*/ alpar@1: npp->r_pi[k] = dir * row->dval; alpar@1: } alpar@1: for (j = 1; j <= npp->n; j++) alpar@1: { col = prob->col[j]; alpar@1: k = npp->col_ref[j]; alpar@1: npp->c_value[k] = col->pval; alpar@1: /*npp->c_dual[k] = dir * col->dval;*/ alpar@1: } alpar@1: } alpar@1: else if (npp->sol == GLP_MIP) alpar@1: { alpar@1: #if 0 alpar@1: for (i = 1; i <= npp->m; i++) alpar@1: { row = prob->row[i]; alpar@1: k = npp->row_ref[i]; alpar@1: /*npp->r_prim[k] = row->mipx;*/ alpar@1: } alpar@1: #endif alpar@1: for (j = 1; j <= npp->n; j++) alpar@1: { col = prob->col[j]; alpar@1: k = npp->col_ref[j]; alpar@1: npp->c_value[k] = col->mipx; alpar@1: } alpar@1: } alpar@1: else alpar@1: xassert(npp != npp); alpar@1: /* perform postprocessing to construct solution to the original alpar@1: problem */ alpar@1: for (tse = npp->top; tse != NULL; tse = tse->link) alpar@1: { xassert(tse->func != NULL); alpar@1: xassert(tse->func(npp, tse->info) == 0); alpar@1: } alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_unload_sol(NPP *npp, glp_prob *orig) alpar@1: { /* store solution to the original problem */ alpar@1: GLPROW *row; alpar@1: GLPCOL *col; alpar@1: int i, j; alpar@1: double dir; alpar@1: xassert(npp->orig_dir == orig->dir); alpar@1: if (npp->orig_dir == GLP_MIN) alpar@1: dir = +1.0; alpar@1: else if (npp->orig_dir == GLP_MAX) alpar@1: dir = -1.0; alpar@1: else alpar@1: xassert(npp != npp); alpar@1: xassert(npp->orig_m == orig->m); alpar@1: xassert(npp->orig_n == orig->n); alpar@1: xassert(npp->orig_nnz == orig->nnz); alpar@1: if (npp->sol == GLP_SOL) alpar@1: { /* store basic solution */ alpar@1: orig->valid = 0; alpar@1: orig->pbs_stat = npp->p_stat; alpar@1: orig->dbs_stat = npp->d_stat; alpar@1: orig->obj_val = orig->c0; alpar@1: orig->some = 0; alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: row->stat = npp->r_stat[i]; alpar@1: if (!npp->scaling) alpar@1: { /*row->prim = npp->r_prim[i];*/ alpar@1: row->dual = dir * npp->r_pi[i]; alpar@1: } alpar@1: else alpar@1: { /*row->prim = npp->r_prim[i] / row->rii;*/ alpar@1: row->dual = dir * npp->r_pi[i] * row->rii; alpar@1: } alpar@1: if (row->stat == GLP_BS) alpar@1: row->dual = 0.0; alpar@1: else if (row->stat == GLP_NL) alpar@1: { xassert(row->type == GLP_LO || row->type == GLP_DB); alpar@1: row->prim = row->lb; alpar@1: } alpar@1: else if (row->stat == GLP_NU) alpar@1: { xassert(row->type == GLP_UP || row->type == GLP_DB); alpar@1: row->prim = row->ub; alpar@1: } alpar@1: else if (row->stat == GLP_NF) alpar@1: { xassert(row->type == GLP_FR); alpar@1: row->prim = 0.0; alpar@1: } alpar@1: else if (row->stat == GLP_NS) alpar@1: { xassert(row->type == GLP_FX); alpar@1: row->prim = row->lb; alpar@1: } alpar@1: else alpar@1: xassert(row != row); alpar@1: } alpar@1: for (j = 1; j <= orig->n; j++) alpar@1: { col = orig->col[j]; alpar@1: col->stat = npp->c_stat[j]; alpar@1: if (!npp->scaling) alpar@1: { col->prim = npp->c_value[j]; alpar@1: /*col->dual = dir * npp->c_dual[j];*/ alpar@1: } alpar@1: else alpar@1: { col->prim = npp->c_value[j] * col->sjj; alpar@1: /*col->dual = dir * npp->c_dual[j] / col->sjj;*/ alpar@1: } alpar@1: if (col->stat == GLP_BS) alpar@1: col->dual = 0.0; alpar@1: #if 1 alpar@1: else if (col->stat == GLP_NL) alpar@1: { xassert(col->type == GLP_LO || col->type == GLP_DB); alpar@1: col->prim = col->lb; alpar@1: } alpar@1: else if (col->stat == GLP_NU) alpar@1: { xassert(col->type == GLP_UP || col->type == GLP_DB); alpar@1: col->prim = col->ub; alpar@1: } alpar@1: else if (col->stat == GLP_NF) alpar@1: { xassert(col->type == GLP_FR); alpar@1: col->prim = 0.0; alpar@1: } alpar@1: else if (col->stat == GLP_NS) alpar@1: { xassert(col->type == GLP_FX); alpar@1: col->prim = col->lb; alpar@1: } alpar@1: else alpar@1: xassert(col != col); alpar@1: #endif alpar@1: orig->obj_val += col->coef * col->prim; alpar@1: } alpar@1: #if 1 alpar@1: /* compute primal values of inactive rows */ alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: if (row->stat == GLP_BS) alpar@1: { GLPAIJ *aij; alpar@1: double temp; alpar@1: temp = 0.0; alpar@1: for (aij = row->ptr; aij != NULL; aij = aij->r_next) alpar@1: temp += aij->val * aij->col->prim; alpar@1: row->prim = temp; alpar@1: } alpar@1: } alpar@1: /* compute reduced costs of active columns */ alpar@1: for (j = 1; j <= orig->n; j++) alpar@1: { col = orig->col[j]; alpar@1: if (col->stat != GLP_BS) alpar@1: { GLPAIJ *aij; alpar@1: double temp; alpar@1: temp = col->coef; alpar@1: for (aij = col->ptr; aij != NULL; aij = aij->c_next) alpar@1: temp -= aij->val * aij->row->dual; alpar@1: col->dual = temp; alpar@1: } alpar@1: } alpar@1: #endif alpar@1: } alpar@1: else if (npp->sol == GLP_IPT) alpar@1: { /* store interior-point solution */ alpar@1: orig->ipt_stat = npp->t_stat; alpar@1: orig->ipt_obj = orig->c0; alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: if (!npp->scaling) alpar@1: { /*row->pval = npp->r_prim[i];*/ alpar@1: row->dval = dir * npp->r_pi[i]; alpar@1: } alpar@1: else alpar@1: { /*row->pval = npp->r_prim[i] / row->rii;*/ alpar@1: row->dval = dir * npp->r_pi[i] * row->rii; alpar@1: } alpar@1: } alpar@1: for (j = 1; j <= orig->n; j++) alpar@1: { col = orig->col[j]; alpar@1: if (!npp->scaling) alpar@1: { col->pval = npp->c_value[j]; alpar@1: /*col->dval = dir * npp->c_dual[j];*/ alpar@1: } alpar@1: else alpar@1: { col->pval = npp->c_value[j] * col->sjj; alpar@1: /*col->dval = dir * npp->c_dual[j] / col->sjj;*/ alpar@1: } alpar@1: orig->ipt_obj += col->coef * col->pval; alpar@1: } alpar@1: #if 1 alpar@1: /* compute row primal values */ alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: { GLPAIJ *aij; alpar@1: double temp; alpar@1: temp = 0.0; alpar@1: for (aij = row->ptr; aij != NULL; aij = aij->r_next) alpar@1: temp += aij->val * aij->col->pval; alpar@1: row->pval = temp; alpar@1: } alpar@1: } alpar@1: /* compute column dual values */ alpar@1: for (j = 1; j <= orig->n; j++) alpar@1: { col = orig->col[j]; alpar@1: { GLPAIJ *aij; alpar@1: double temp; alpar@1: temp = col->coef; alpar@1: for (aij = col->ptr; aij != NULL; aij = aij->c_next) alpar@1: temp -= aij->val * aij->row->dval; alpar@1: col->dval = temp; alpar@1: } alpar@1: } alpar@1: #endif alpar@1: } alpar@1: else if (npp->sol == GLP_MIP) alpar@1: { /* store MIP solution */ alpar@1: xassert(!npp->scaling); alpar@1: orig->mip_stat = npp->i_stat; alpar@1: orig->mip_obj = orig->c0; alpar@1: #if 0 alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: /*row->mipx = npp->r_prim[i];*/ alpar@1: } alpar@1: #endif alpar@1: for (j = 1; j <= orig->n; j++) alpar@1: { col = orig->col[j]; alpar@1: col->mipx = npp->c_value[j]; alpar@1: if (col->kind == GLP_IV) alpar@1: xassert(col->mipx == floor(col->mipx)); alpar@1: orig->mip_obj += col->coef * col->mipx; alpar@1: } alpar@1: #if 1 alpar@1: /* compute row primal values */ alpar@1: for (i = 1; i <= orig->m; i++) alpar@1: { row = orig->row[i]; alpar@1: { GLPAIJ *aij; alpar@1: double temp; alpar@1: temp = 0.0; alpar@1: for (aij = row->ptr; aij != NULL; aij = aij->r_next) alpar@1: temp += aij->val * aij->col->mipx; alpar@1: row->mipx = temp; alpar@1: } alpar@1: } alpar@1: #endif alpar@1: } alpar@1: else alpar@1: xassert(npp != npp); alpar@1: return; alpar@1: } alpar@1: alpar@1: void npp_delete_wksp(NPP *npp) alpar@1: { /* delete LP/MIP preprocessor workspace */ alpar@1: if (npp->pool != NULL) alpar@1: dmp_delete_pool(npp->pool); alpar@1: if (npp->stack != NULL) alpar@1: dmp_delete_pool(npp->stack); alpar@1: if (npp->row_ref != NULL) alpar@1: xfree(npp->row_ref); alpar@1: if (npp->col_ref != NULL) alpar@1: xfree(npp->col_ref); alpar@1: if (npp->r_stat != NULL) alpar@1: xfree(npp->r_stat); alpar@1: #if 0 alpar@1: if (npp->r_prim != NULL) alpar@1: xfree(npp->r_prim); alpar@1: #endif alpar@1: if (npp->r_pi != NULL) alpar@1: xfree(npp->r_pi); alpar@1: if (npp->c_stat != NULL) alpar@1: xfree(npp->c_stat); alpar@1: if (npp->c_value != NULL) alpar@1: xfree(npp->c_value); alpar@1: #if 0 alpar@1: if (npp->c_dual != NULL) alpar@1: xfree(npp->c_dual); alpar@1: #endif alpar@1: xfree(npp); alpar@1: return; alpar@1: } alpar@1: alpar@1: /* eof */