lemon-project-template-glpk

annotate deps/glpk/src/glpapi01.c @ 9:33de93886c88

Import GLPK 4.47
author Alpar Juttner <alpar@cs.elte.hu>
date Sun, 06 Nov 2011 20:59:10 +0100
parents
children
rev   line source
alpar@9 1 /* glpapi01.c (problem creating and modifying routines) */
alpar@9 2
alpar@9 3 /***********************************************************************
alpar@9 4 * This code is part of GLPK (GNU Linear Programming Kit).
alpar@9 5 *
alpar@9 6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@9 7 * 2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics,
alpar@9 8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@9 9 * E-mail: <mao@gnu.org>.
alpar@9 10 *
alpar@9 11 * GLPK is free software: you can redistribute it and/or modify it
alpar@9 12 * under the terms of the GNU General Public License as published by
alpar@9 13 * the Free Software Foundation, either version 3 of the License, or
alpar@9 14 * (at your option) any later version.
alpar@9 15 *
alpar@9 16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@9 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@9 18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@9 19 * License for more details.
alpar@9 20 *
alpar@9 21 * You should have received a copy of the GNU General Public License
alpar@9 22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@9 23 ***********************************************************************/
alpar@9 24
alpar@9 25 #include "glpios.h"
alpar@9 26
alpar@9 27 /* CAUTION: DO NOT CHANGE THE LIMITS BELOW */
alpar@9 28
alpar@9 29 #define M_MAX 100000000 /* = 100*10^6 */
alpar@9 30 /* maximal number of rows in the problem object */
alpar@9 31
alpar@9 32 #define N_MAX 100000000 /* = 100*10^6 */
alpar@9 33 /* maximal number of columns in the problem object */
alpar@9 34
alpar@9 35 #define NNZ_MAX 500000000 /* = 500*10^6 */
alpar@9 36 /* maximal number of constraint coefficients in the problem object */
alpar@9 37
alpar@9 38 /***********************************************************************
alpar@9 39 * NAME
alpar@9 40 *
alpar@9 41 * glp_create_prob - create problem object
alpar@9 42 *
alpar@9 43 * SYNOPSIS
alpar@9 44 *
alpar@9 45 * glp_prob *glp_create_prob(void);
alpar@9 46 *
alpar@9 47 * DESCRIPTION
alpar@9 48 *
alpar@9 49 * The routine glp_create_prob creates a new problem object, which is
alpar@9 50 * initially "empty", i.e. has no rows and columns.
alpar@9 51 *
alpar@9 52 * RETURNS
alpar@9 53 *
alpar@9 54 * The routine returns a pointer to the object created, which should be
alpar@9 55 * used in any subsequent operations on this object. */
alpar@9 56
alpar@9 57 static void create_prob(glp_prob *lp)
alpar@9 58 { lp->magic = GLP_PROB_MAGIC;
alpar@9 59 lp->pool = dmp_create_pool();
alpar@9 60 #if 0 /* 17/XI-2009 */
alpar@9 61 lp->cps = xmalloc(sizeof(struct LPXCPS));
alpar@9 62 lpx_reset_parms(lp);
alpar@9 63 #else
alpar@9 64 lp->parms = NULL;
alpar@9 65 #endif
alpar@9 66 lp->tree = NULL;
alpar@9 67 #if 0
alpar@9 68 lp->lwa = 0;
alpar@9 69 lp->cwa = NULL;
alpar@9 70 #endif
alpar@9 71 /* LP/MIP data */
alpar@9 72 lp->name = NULL;
alpar@9 73 lp->obj = NULL;
alpar@9 74 lp->dir = GLP_MIN;
alpar@9 75 lp->c0 = 0.0;
alpar@9 76 lp->m_max = 100;
alpar@9 77 lp->n_max = 200;
alpar@9 78 lp->m = lp->n = 0;
alpar@9 79 lp->nnz = 0;
alpar@9 80 lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
alpar@9 81 lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
alpar@9 82 lp->r_tree = lp->c_tree = NULL;
alpar@9 83 /* basis factorization */
alpar@9 84 lp->valid = 0;
alpar@9 85 lp->head = xcalloc(1+lp->m_max, sizeof(int));
alpar@9 86 lp->bfcp = NULL;
alpar@9 87 lp->bfd = NULL;
alpar@9 88 /* basic solution (LP) */
alpar@9 89 lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
alpar@9 90 lp->obj_val = 0.0;
alpar@9 91 lp->it_cnt = 0;
alpar@9 92 lp->some = 0;
alpar@9 93 /* interior-point solution (LP) */
alpar@9 94 lp->ipt_stat = GLP_UNDEF;
alpar@9 95 lp->ipt_obj = 0.0;
alpar@9 96 /* integer solution (MIP) */
alpar@9 97 lp->mip_stat = GLP_UNDEF;
alpar@9 98 lp->mip_obj = 0.0;
alpar@9 99 return;
alpar@9 100 }
alpar@9 101
alpar@9 102 glp_prob *glp_create_prob(void)
alpar@9 103 { glp_prob *lp;
alpar@9 104 lp = xmalloc(sizeof(glp_prob));
alpar@9 105 create_prob(lp);
alpar@9 106 return lp;
alpar@9 107 }
alpar@9 108
alpar@9 109 /***********************************************************************
alpar@9 110 * NAME
alpar@9 111 *
alpar@9 112 * glp_set_prob_name - assign (change) problem name
alpar@9 113 *
alpar@9 114 * SYNOPSIS
alpar@9 115 *
alpar@9 116 * void glp_set_prob_name(glp_prob *lp, const char *name);
alpar@9 117 *
alpar@9 118 * DESCRIPTION
alpar@9 119 *
alpar@9 120 * The routine glp_set_prob_name assigns a given symbolic name (1 up to
alpar@9 121 * 255 characters) to the specified problem object.
alpar@9 122 *
alpar@9 123 * If the parameter name is NULL or empty string, the routine erases an
alpar@9 124 * existing symbolic name of the problem object. */
alpar@9 125
alpar@9 126 void glp_set_prob_name(glp_prob *lp, const char *name)
alpar@9 127 { glp_tree *tree = lp->tree;
alpar@9 128 if (tree != NULL && tree->reason != 0)
alpar@9 129 xerror("glp_set_prob_name: operation not allowed\n");
alpar@9 130 if (lp->name != NULL)
alpar@9 131 { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1);
alpar@9 132 lp->name = NULL;
alpar@9 133 }
alpar@9 134 if (!(name == NULL || name[0] == '\0'))
alpar@9 135 { int k;
alpar@9 136 for (k = 0; name[k] != '\0'; k++)
alpar@9 137 { if (k == 256)
alpar@9 138 xerror("glp_set_prob_name: problem name too long\n");
alpar@9 139 if (iscntrl((unsigned char)name[k]))
alpar@9 140 xerror("glp_set_prob_name: problem name contains invalid"
alpar@9 141 " character(s)\n");
alpar@9 142 }
alpar@9 143 lp->name = dmp_get_atom(lp->pool, strlen(name)+1);
alpar@9 144 strcpy(lp->name, name);
alpar@9 145 }
alpar@9 146 return;
alpar@9 147 }
alpar@9 148
alpar@9 149 /***********************************************************************
alpar@9 150 * NAME
alpar@9 151 *
alpar@9 152 * glp_set_obj_name - assign (change) objective function name
alpar@9 153 *
alpar@9 154 * SYNOPSIS
alpar@9 155 *
alpar@9 156 * void glp_set_obj_name(glp_prob *lp, const char *name);
alpar@9 157 *
alpar@9 158 * DESCRIPTION
alpar@9 159 *
alpar@9 160 * The routine glp_set_obj_name assigns a given symbolic name (1 up to
alpar@9 161 * 255 characters) to the objective function of the specified problem
alpar@9 162 * object.
alpar@9 163 *
alpar@9 164 * If the parameter name is NULL or empty string, the routine erases an
alpar@9 165 * existing name of the objective function. */
alpar@9 166
alpar@9 167 void glp_set_obj_name(glp_prob *lp, const char *name)
alpar@9 168 { glp_tree *tree = lp->tree;
alpar@9 169 if (tree != NULL && tree->reason != 0)
alpar@9 170 xerror("glp_set_obj_name: operation not allowed\n");
alpar@9 171 if (lp->obj != NULL)
alpar@9 172 { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1);
alpar@9 173 lp->obj = NULL;
alpar@9 174 }
alpar@9 175 if (!(name == NULL || name[0] == '\0'))
alpar@9 176 { int k;
alpar@9 177 for (k = 0; name[k] != '\0'; k++)
alpar@9 178 { if (k == 256)
alpar@9 179 xerror("glp_set_obj_name: objective name too long\n");
alpar@9 180 if (iscntrl((unsigned char)name[k]))
alpar@9 181 xerror("glp_set_obj_name: objective name contains invali"
alpar@9 182 "d character(s)\n");
alpar@9 183 }
alpar@9 184 lp->obj = dmp_get_atom(lp->pool, strlen(name)+1);
alpar@9 185 strcpy(lp->obj, name);
alpar@9 186 }
alpar@9 187 return;
alpar@9 188 }
alpar@9 189
alpar@9 190 /***********************************************************************
alpar@9 191 * NAME
alpar@9 192 *
alpar@9 193 * glp_set_obj_dir - set (change) optimization direction flag
alpar@9 194 *
alpar@9 195 * SYNOPSIS
alpar@9 196 *
alpar@9 197 * void glp_set_obj_dir(glp_prob *lp, int dir);
alpar@9 198 *
alpar@9 199 * DESCRIPTION
alpar@9 200 *
alpar@9 201 * The routine glp_set_obj_dir sets (changes) optimization direction
alpar@9 202 * flag (i.e. "sense" of the objective function) as specified by the
alpar@9 203 * parameter dir:
alpar@9 204 *
alpar@9 205 * GLP_MIN - minimization;
alpar@9 206 * GLP_MAX - maximization. */
alpar@9 207
alpar@9 208 void glp_set_obj_dir(glp_prob *lp, int dir)
alpar@9 209 { glp_tree *tree = lp->tree;
alpar@9 210 if (tree != NULL && tree->reason != 0)
alpar@9 211 xerror("glp_set_obj_dir: operation not allowed\n");
alpar@9 212 if (!(dir == GLP_MIN || dir == GLP_MAX))
alpar@9 213 xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n",
alpar@9 214 dir);
alpar@9 215 lp->dir = dir;
alpar@9 216 return;
alpar@9 217 }
alpar@9 218
alpar@9 219 /***********************************************************************
alpar@9 220 * NAME
alpar@9 221 *
alpar@9 222 * glp_add_rows - add new rows to problem object
alpar@9 223 *
alpar@9 224 * SYNOPSIS
alpar@9 225 *
alpar@9 226 * int glp_add_rows(glp_prob *lp, int nrs);
alpar@9 227 *
alpar@9 228 * DESCRIPTION
alpar@9 229 *
alpar@9 230 * The routine glp_add_rows adds nrs rows (constraints) to the specified
alpar@9 231 * problem object. New rows are always added to the end of the row list,
alpar@9 232 * so the ordinal numbers of existing rows remain unchanged.
alpar@9 233 *
alpar@9 234 * Being added each new row is initially free (unbounded) and has empty
alpar@9 235 * list of the constraint coefficients.
alpar@9 236 *
alpar@9 237 * RETURNS
alpar@9 238 *
alpar@9 239 * The routine glp_add_rows returns the ordinal number of the first new
alpar@9 240 * row added to the problem object. */
alpar@9 241
alpar@9 242 int glp_add_rows(glp_prob *lp, int nrs)
alpar@9 243 { glp_tree *tree = lp->tree;
alpar@9 244 GLPROW *row;
alpar@9 245 int m_new, i;
alpar@9 246 /* determine new number of rows */
alpar@9 247 if (nrs < 1)
alpar@9 248 xerror("glp_add_rows: nrs = %d; invalid number of rows\n",
alpar@9 249 nrs);
alpar@9 250 if (nrs > M_MAX - lp->m)
alpar@9 251 xerror("glp_add_rows: nrs = %d; too many rows\n", nrs);
alpar@9 252 m_new = lp->m + nrs;
alpar@9 253 /* increase the room, if necessary */
alpar@9 254 if (lp->m_max < m_new)
alpar@9 255 { GLPROW **save = lp->row;
alpar@9 256 while (lp->m_max < m_new)
alpar@9 257 { lp->m_max += lp->m_max;
alpar@9 258 xassert(lp->m_max > 0);
alpar@9 259 }
alpar@9 260 lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
alpar@9 261 memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *));
alpar@9 262 xfree(save);
alpar@9 263 /* do not forget about the basis header */
alpar@9 264 xfree(lp->head);
alpar@9 265 lp->head = xcalloc(1+lp->m_max, sizeof(int));
alpar@9 266 }
alpar@9 267 /* add new rows to the end of the row list */
alpar@9 268 for (i = lp->m+1; i <= m_new; i++)
alpar@9 269 { /* create row descriptor */
alpar@9 270 lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW));
alpar@9 271 row->i = i;
alpar@9 272 row->name = NULL;
alpar@9 273 row->node = NULL;
alpar@9 274 #if 1 /* 20/IX-2008 */
alpar@9 275 row->level = 0;
alpar@9 276 row->origin = 0;
alpar@9 277 row->klass = 0;
alpar@9 278 if (tree != NULL)
alpar@9 279 { switch (tree->reason)
alpar@9 280 { case 0:
alpar@9 281 break;
alpar@9 282 case GLP_IROWGEN:
alpar@9 283 xassert(tree->curr != NULL);
alpar@9 284 row->level = tree->curr->level;
alpar@9 285 row->origin = GLP_RF_LAZY;
alpar@9 286 break;
alpar@9 287 case GLP_ICUTGEN:
alpar@9 288 xassert(tree->curr != NULL);
alpar@9 289 row->level = tree->curr->level;
alpar@9 290 row->origin = GLP_RF_CUT;
alpar@9 291 break;
alpar@9 292 default:
alpar@9 293 xassert(tree != tree);
alpar@9 294 }
alpar@9 295 }
alpar@9 296 #endif
alpar@9 297 row->type = GLP_FR;
alpar@9 298 row->lb = row->ub = 0.0;
alpar@9 299 row->ptr = NULL;
alpar@9 300 row->rii = 1.0;
alpar@9 301 row->stat = GLP_BS;
alpar@9 302 #if 0
alpar@9 303 row->bind = -1;
alpar@9 304 #else
alpar@9 305 row->bind = 0;
alpar@9 306 #endif
alpar@9 307 row->prim = row->dual = 0.0;
alpar@9 308 row->pval = row->dval = 0.0;
alpar@9 309 row->mipx = 0.0;
alpar@9 310 }
alpar@9 311 /* set new number of rows */
alpar@9 312 lp->m = m_new;
alpar@9 313 /* invalidate the basis factorization */
alpar@9 314 lp->valid = 0;
alpar@9 315 #if 1
alpar@9 316 if (tree != NULL && tree->reason != 0) tree->reopt = 1;
alpar@9 317 #endif
alpar@9 318 /* return the ordinal number of the first row added */
alpar@9 319 return m_new - nrs + 1;
alpar@9 320 }
alpar@9 321
alpar@9 322 /***********************************************************************
alpar@9 323 * NAME
alpar@9 324 *
alpar@9 325 * glp_add_cols - add new columns to problem object
alpar@9 326 *
alpar@9 327 * SYNOPSIS
alpar@9 328 *
alpar@9 329 * int glp_add_cols(glp_prob *lp, int ncs);
alpar@9 330 *
alpar@9 331 * DESCRIPTION
alpar@9 332 *
alpar@9 333 * The routine glp_add_cols adds ncs columns (structural variables) to
alpar@9 334 * the specified problem object. New columns are always added to the end
alpar@9 335 * of the column list, so the ordinal numbers of existing columns remain
alpar@9 336 * unchanged.
alpar@9 337 *
alpar@9 338 * Being added each new column is initially fixed at zero and has empty
alpar@9 339 * list of the constraint coefficients.
alpar@9 340 *
alpar@9 341 * RETURNS
alpar@9 342 *
alpar@9 343 * The routine glp_add_cols returns the ordinal number of the first new
alpar@9 344 * column added to the problem object. */
alpar@9 345
alpar@9 346 int glp_add_cols(glp_prob *lp, int ncs)
alpar@9 347 { glp_tree *tree = lp->tree;
alpar@9 348 GLPCOL *col;
alpar@9 349 int n_new, j;
alpar@9 350 if (tree != NULL && tree->reason != 0)
alpar@9 351 xerror("glp_add_cols: operation not allowed\n");
alpar@9 352 /* determine new number of columns */
alpar@9 353 if (ncs < 1)
alpar@9 354 xerror("glp_add_cols: ncs = %d; invalid number of columns\n",
alpar@9 355 ncs);
alpar@9 356 if (ncs > N_MAX - lp->n)
alpar@9 357 xerror("glp_add_cols: ncs = %d; too many columns\n", ncs);
alpar@9 358 n_new = lp->n + ncs;
alpar@9 359 /* increase the room, if necessary */
alpar@9 360 if (lp->n_max < n_new)
alpar@9 361 { GLPCOL **save = lp->col;
alpar@9 362 while (lp->n_max < n_new)
alpar@9 363 { lp->n_max += lp->n_max;
alpar@9 364 xassert(lp->n_max > 0);
alpar@9 365 }
alpar@9 366 lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
alpar@9 367 memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *));
alpar@9 368 xfree(save);
alpar@9 369 }
alpar@9 370 /* add new columns to the end of the column list */
alpar@9 371 for (j = lp->n+1; j <= n_new; j++)
alpar@9 372 { /* create column descriptor */
alpar@9 373 lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL));
alpar@9 374 col->j = j;
alpar@9 375 col->name = NULL;
alpar@9 376 col->node = NULL;
alpar@9 377 col->kind = GLP_CV;
alpar@9 378 col->type = GLP_FX;
alpar@9 379 col->lb = col->ub = 0.0;
alpar@9 380 col->coef = 0.0;
alpar@9 381 col->ptr = NULL;
alpar@9 382 col->sjj = 1.0;
alpar@9 383 col->stat = GLP_NS;
alpar@9 384 #if 0
alpar@9 385 col->bind = -1;
alpar@9 386 #else
alpar@9 387 col->bind = 0; /* the basis may remain valid */
alpar@9 388 #endif
alpar@9 389 col->prim = col->dual = 0.0;
alpar@9 390 col->pval = col->dval = 0.0;
alpar@9 391 col->mipx = 0.0;
alpar@9 392 }
alpar@9 393 /* set new number of columns */
alpar@9 394 lp->n = n_new;
alpar@9 395 /* return the ordinal number of the first column added */
alpar@9 396 return n_new - ncs + 1;
alpar@9 397 }
alpar@9 398
alpar@9 399 /***********************************************************************
alpar@9 400 * NAME
alpar@9 401 *
alpar@9 402 * glp_set_row_name - assign (change) row name
alpar@9 403 *
alpar@9 404 * SYNOPSIS
alpar@9 405 *
alpar@9 406 * void glp_set_row_name(glp_prob *lp, int i, const char *name);
alpar@9 407 *
alpar@9 408 * DESCRIPTION
alpar@9 409 *
alpar@9 410 * The routine glp_set_row_name assigns a given symbolic name (1 up to
alpar@9 411 * 255 characters) to i-th row (auxiliary variable) of the specified
alpar@9 412 * problem object.
alpar@9 413 *
alpar@9 414 * If the parameter name is NULL or empty string, the routine erases an
alpar@9 415 * existing name of i-th row. */
alpar@9 416
alpar@9 417 void glp_set_row_name(glp_prob *lp, int i, const char *name)
alpar@9 418 { glp_tree *tree = lp->tree;
alpar@9 419 GLPROW *row;
alpar@9 420 if (!(1 <= i && i <= lp->m))
alpar@9 421 xerror("glp_set_row_name: i = %d; row number out of range\n",
alpar@9 422 i);
alpar@9 423 row = lp->row[i];
alpar@9 424 if (tree != NULL && tree->reason != 0)
alpar@9 425 { xassert(tree->curr != NULL);
alpar@9 426 xassert(row->level == tree->curr->level);
alpar@9 427 }
alpar@9 428 if (row->name != NULL)
alpar@9 429 { if (row->node != NULL)
alpar@9 430 { xassert(lp->r_tree != NULL);
alpar@9 431 avl_delete_node(lp->r_tree, row->node);
alpar@9 432 row->node = NULL;
alpar@9 433 }
alpar@9 434 dmp_free_atom(lp->pool, row->name, strlen(row->name)+1);
alpar@9 435 row->name = NULL;
alpar@9 436 }
alpar@9 437 if (!(name == NULL || name[0] == '\0'))
alpar@9 438 { int k;
alpar@9 439 for (k = 0; name[k] != '\0'; k++)
alpar@9 440 { if (k == 256)
alpar@9 441 xerror("glp_set_row_name: i = %d; row name too long\n",
alpar@9 442 i);
alpar@9 443 if (iscntrl((unsigned char)name[k]))
alpar@9 444 xerror("glp_set_row_name: i = %d: row name contains inva"
alpar@9 445 "lid character(s)\n", i);
alpar@9 446 }
alpar@9 447 row->name = dmp_get_atom(lp->pool, strlen(name)+1);
alpar@9 448 strcpy(row->name, name);
alpar@9 449 if (lp->r_tree != NULL)
alpar@9 450 { xassert(row->node == NULL);
alpar@9 451 row->node = avl_insert_node(lp->r_tree, row->name);
alpar@9 452 avl_set_node_link(row->node, row);
alpar@9 453 }
alpar@9 454 }
alpar@9 455 return;
alpar@9 456 }
alpar@9 457
alpar@9 458 /***********************************************************************
alpar@9 459 * NAME
alpar@9 460 *
alpar@9 461 * glp_set_col_name - assign (change) column name
alpar@9 462 *
alpar@9 463 * SYNOPSIS
alpar@9 464 *
alpar@9 465 * void glp_set_col_name(glp_prob *lp, int j, const char *name);
alpar@9 466 *
alpar@9 467 * DESCRIPTION
alpar@9 468 *
alpar@9 469 * The routine glp_set_col_name assigns a given symbolic name (1 up to
alpar@9 470 * 255 characters) to j-th column (structural variable) of the specified
alpar@9 471 * problem object.
alpar@9 472 *
alpar@9 473 * If the parameter name is NULL or empty string, the routine erases an
alpar@9 474 * existing name of j-th column. */
alpar@9 475
alpar@9 476 void glp_set_col_name(glp_prob *lp, int j, const char *name)
alpar@9 477 { glp_tree *tree = lp->tree;
alpar@9 478 GLPCOL *col;
alpar@9 479 if (tree != NULL && tree->reason != 0)
alpar@9 480 xerror("glp_set_col_name: operation not allowed\n");
alpar@9 481 if (!(1 <= j && j <= lp->n))
alpar@9 482 xerror("glp_set_col_name: j = %d; column number out of range\n"
alpar@9 483 , j);
alpar@9 484 col = lp->col[j];
alpar@9 485 if (col->name != NULL)
alpar@9 486 { if (col->node != NULL)
alpar@9 487 { xassert(lp->c_tree != NULL);
alpar@9 488 avl_delete_node(lp->c_tree, col->node);
alpar@9 489 col->node = NULL;
alpar@9 490 }
alpar@9 491 dmp_free_atom(lp->pool, col->name, strlen(col->name)+1);
alpar@9 492 col->name = NULL;
alpar@9 493 }
alpar@9 494 if (!(name == NULL || name[0] == '\0'))
alpar@9 495 { int k;
alpar@9 496 for (k = 0; name[k] != '\0'; k++)
alpar@9 497 { if (k == 256)
alpar@9 498 xerror("glp_set_col_name: j = %d; column name too long\n"
alpar@9 499 , j);
alpar@9 500 if (iscntrl((unsigned char)name[k]))
alpar@9 501 xerror("glp_set_col_name: j = %d: column name contains i"
alpar@9 502 "nvalid character(s)\n", j);
alpar@9 503 }
alpar@9 504 col->name = dmp_get_atom(lp->pool, strlen(name)+1);
alpar@9 505 strcpy(col->name, name);
alpar@9 506 if (lp->c_tree != NULL && col->name != NULL)
alpar@9 507 { xassert(col->node == NULL);
alpar@9 508 col->node = avl_insert_node(lp->c_tree, col->name);
alpar@9 509 avl_set_node_link(col->node, col);
alpar@9 510 }
alpar@9 511 }
alpar@9 512 return;
alpar@9 513 }
alpar@9 514
alpar@9 515 /***********************************************************************
alpar@9 516 * NAME
alpar@9 517 *
alpar@9 518 * glp_set_row_bnds - set (change) row bounds
alpar@9 519 *
alpar@9 520 * SYNOPSIS
alpar@9 521 *
alpar@9 522 * void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
alpar@9 523 * double ub);
alpar@9 524 *
alpar@9 525 * DESCRIPTION
alpar@9 526 *
alpar@9 527 * The routine glp_set_row_bnds sets (changes) the type and bounds of
alpar@9 528 * i-th row (auxiliary variable) of the specified problem object.
alpar@9 529 *
alpar@9 530 * Parameters type, lb, and ub specify the type, lower bound, and upper
alpar@9 531 * bound, respectively, as follows:
alpar@9 532 *
alpar@9 533 * Type Bounds Comments
alpar@9 534 * ------------------------------------------------------
alpar@9 535 * GLP_FR -inf < x < +inf Free variable
alpar@9 536 * GLP_LO lb <= x < +inf Variable with lower bound
alpar@9 537 * GLP_UP -inf < x <= ub Variable with upper bound
alpar@9 538 * GLP_DB lb <= x <= ub Double-bounded variable
alpar@9 539 * GLP_FX x = lb Fixed variable
alpar@9 540 *
alpar@9 541 * where x is the auxiliary variable associated with i-th row.
alpar@9 542 *
alpar@9 543 * If the row has no lower bound, the parameter lb is ignored. If the
alpar@9 544 * row has no upper bound, the parameter ub is ignored. If the row is
alpar@9 545 * an equality constraint (i.e. the corresponding auxiliary variable is
alpar@9 546 * of fixed type), only the parameter lb is used while the parameter ub
alpar@9 547 * is ignored. */
alpar@9 548
alpar@9 549 void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
alpar@9 550 double ub)
alpar@9 551 { GLPROW *row;
alpar@9 552 if (!(1 <= i && i <= lp->m))
alpar@9 553 xerror("glp_set_row_bnds: i = %d; row number out of range\n",
alpar@9 554 i);
alpar@9 555 row = lp->row[i];
alpar@9 556 row->type = type;
alpar@9 557 switch (type)
alpar@9 558 { case GLP_FR:
alpar@9 559 row->lb = row->ub = 0.0;
alpar@9 560 if (row->stat != GLP_BS) row->stat = GLP_NF;
alpar@9 561 break;
alpar@9 562 case GLP_LO:
alpar@9 563 row->lb = lb, row->ub = 0.0;
alpar@9 564 if (row->stat != GLP_BS) row->stat = GLP_NL;
alpar@9 565 break;
alpar@9 566 case GLP_UP:
alpar@9 567 row->lb = 0.0, row->ub = ub;
alpar@9 568 if (row->stat != GLP_BS) row->stat = GLP_NU;
alpar@9 569 break;
alpar@9 570 case GLP_DB:
alpar@9 571 row->lb = lb, row->ub = ub;
alpar@9 572 if (!(row->stat == GLP_BS ||
alpar@9 573 row->stat == GLP_NL || row->stat == GLP_NU))
alpar@9 574 row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
alpar@9 575 break;
alpar@9 576 case GLP_FX:
alpar@9 577 row->lb = row->ub = lb;
alpar@9 578 if (row->stat != GLP_BS) row->stat = GLP_NS;
alpar@9 579 break;
alpar@9 580 default:
alpar@9 581 xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty"
alpar@9 582 "pe\n", i, type);
alpar@9 583 }
alpar@9 584 return;
alpar@9 585 }
alpar@9 586
alpar@9 587 /***********************************************************************
alpar@9 588 * NAME
alpar@9 589 *
alpar@9 590 * glp_set_col_bnds - set (change) column bounds
alpar@9 591 *
alpar@9 592 * SYNOPSIS
alpar@9 593 *
alpar@9 594 * void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
alpar@9 595 * double ub);
alpar@9 596 *
alpar@9 597 * DESCRIPTION
alpar@9 598 *
alpar@9 599 * The routine glp_set_col_bnds sets (changes) the type and bounds of
alpar@9 600 * j-th column (structural variable) of the specified problem object.
alpar@9 601 *
alpar@9 602 * Parameters type, lb, and ub specify the type, lower bound, and upper
alpar@9 603 * bound, respectively, as follows:
alpar@9 604 *
alpar@9 605 * Type Bounds Comments
alpar@9 606 * ------------------------------------------------------
alpar@9 607 * GLP_FR -inf < x < +inf Free variable
alpar@9 608 * GLP_LO lb <= x < +inf Variable with lower bound
alpar@9 609 * GLP_UP -inf < x <= ub Variable with upper bound
alpar@9 610 * GLP_DB lb <= x <= ub Double-bounded variable
alpar@9 611 * GLP_FX x = lb Fixed variable
alpar@9 612 *
alpar@9 613 * where x is the structural variable associated with j-th column.
alpar@9 614 *
alpar@9 615 * If the column has no lower bound, the parameter lb is ignored. If the
alpar@9 616 * column has no upper bound, the parameter ub is ignored. If the column
alpar@9 617 * is of fixed type, only the parameter lb is used while the parameter
alpar@9 618 * ub is ignored. */
alpar@9 619
alpar@9 620 void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
alpar@9 621 double ub)
alpar@9 622 { GLPCOL *col;
alpar@9 623 if (!(1 <= j && j <= lp->n))
alpar@9 624 xerror("glp_set_col_bnds: j = %d; column number out of range\n"
alpar@9 625 , j);
alpar@9 626 col = lp->col[j];
alpar@9 627 col->type = type;
alpar@9 628 switch (type)
alpar@9 629 { case GLP_FR:
alpar@9 630 col->lb = col->ub = 0.0;
alpar@9 631 if (col->stat != GLP_BS) col->stat = GLP_NF;
alpar@9 632 break;
alpar@9 633 case GLP_LO:
alpar@9 634 col->lb = lb, col->ub = 0.0;
alpar@9 635 if (col->stat != GLP_BS) col->stat = GLP_NL;
alpar@9 636 break;
alpar@9 637 case GLP_UP:
alpar@9 638 col->lb = 0.0, col->ub = ub;
alpar@9 639 if (col->stat != GLP_BS) col->stat = GLP_NU;
alpar@9 640 break;
alpar@9 641 case GLP_DB:
alpar@9 642 col->lb = lb, col->ub = ub;
alpar@9 643 if (!(col->stat == GLP_BS ||
alpar@9 644 col->stat == GLP_NL || col->stat == GLP_NU))
alpar@9 645 col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
alpar@9 646 break;
alpar@9 647 case GLP_FX:
alpar@9 648 col->lb = col->ub = lb;
alpar@9 649 if (col->stat != GLP_BS) col->stat = GLP_NS;
alpar@9 650 break;
alpar@9 651 default:
alpar@9 652 xerror("glp_set_col_bnds: j = %d; type = %d; invalid column"
alpar@9 653 " type\n", j, type);
alpar@9 654 }
alpar@9 655 return;
alpar@9 656 }
alpar@9 657
alpar@9 658 /***********************************************************************
alpar@9 659 * NAME
alpar@9 660 *
alpar@9 661 * glp_set_obj_coef - set (change) obj. coefficient or constant term
alpar@9 662 *
alpar@9 663 * SYNOPSIS
alpar@9 664 *
alpar@9 665 * void glp_set_obj_coef(glp_prob *lp, int j, double coef);
alpar@9 666 *
alpar@9 667 * DESCRIPTION
alpar@9 668 *
alpar@9 669 * The routine glp_set_obj_coef sets (changes) objective coefficient at
alpar@9 670 * j-th column (structural variable) of the specified problem object.
alpar@9 671 *
alpar@9 672 * If the parameter j is 0, the routine sets (changes) the constant term
alpar@9 673 * ("shift") of the objective function. */
alpar@9 674
alpar@9 675 void glp_set_obj_coef(glp_prob *lp, int j, double coef)
alpar@9 676 { glp_tree *tree = lp->tree;
alpar@9 677 if (tree != NULL && tree->reason != 0)
alpar@9 678 xerror("glp_set_obj_coef: operation not allowed\n");
alpar@9 679 if (!(0 <= j && j <= lp->n))
alpar@9 680 xerror("glp_set_obj_coef: j = %d; column number out of range\n"
alpar@9 681 , j);
alpar@9 682 if (j == 0)
alpar@9 683 lp->c0 = coef;
alpar@9 684 else
alpar@9 685 lp->col[j]->coef = coef;
alpar@9 686 return;
alpar@9 687 }
alpar@9 688
alpar@9 689 /***********************************************************************
alpar@9 690 * NAME
alpar@9 691 *
alpar@9 692 * glp_set_mat_row - set (replace) row of the constraint matrix
alpar@9 693 *
alpar@9 694 * SYNOPSIS
alpar@9 695 *
alpar@9 696 * void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
alpar@9 697 * const double val[]);
alpar@9 698 *
alpar@9 699 * DESCRIPTION
alpar@9 700 *
alpar@9 701 * The routine glp_set_mat_row stores (replaces) the contents of i-th
alpar@9 702 * row of the constraint matrix of the specified problem object.
alpar@9 703 *
alpar@9 704 * Column indices and numeric values of new row elements must be placed
alpar@9 705 * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
alpar@9 706 * 0 <= len <= n is the new length of i-th row, n is the current number
alpar@9 707 * of columns in the problem object. Elements with identical column
alpar@9 708 * indices are not allowed. Zero elements are allowed, but they are not
alpar@9 709 * stored in the constraint matrix.
alpar@9 710 *
alpar@9 711 * If the parameter len is zero, the parameters ind and/or val can be
alpar@9 712 * specified as NULL. */
alpar@9 713
alpar@9 714 void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
alpar@9 715 const double val[])
alpar@9 716 { glp_tree *tree = lp->tree;
alpar@9 717 GLPROW *row;
alpar@9 718 GLPCOL *col;
alpar@9 719 GLPAIJ *aij, *next;
alpar@9 720 int j, k;
alpar@9 721 /* obtain pointer to i-th row */
alpar@9 722 if (!(1 <= i && i <= lp->m))
alpar@9 723 xerror("glp_set_mat_row: i = %d; row number out of range\n",
alpar@9 724 i);
alpar@9 725 row = lp->row[i];
alpar@9 726 if (tree != NULL && tree->reason != 0)
alpar@9 727 { xassert(tree->curr != NULL);
alpar@9 728 xassert(row->level == tree->curr->level);
alpar@9 729 }
alpar@9 730 /* remove all existing elements from i-th row */
alpar@9 731 while (row->ptr != NULL)
alpar@9 732 { /* take next element in the row */
alpar@9 733 aij = row->ptr;
alpar@9 734 /* remove the element from the row list */
alpar@9 735 row->ptr = aij->r_next;
alpar@9 736 /* obtain pointer to corresponding column */
alpar@9 737 col = aij->col;
alpar@9 738 /* remove the element from the column list */
alpar@9 739 if (aij->c_prev == NULL)
alpar@9 740 col->ptr = aij->c_next;
alpar@9 741 else
alpar@9 742 aij->c_prev->c_next = aij->c_next;
alpar@9 743 if (aij->c_next == NULL)
alpar@9 744 ;
alpar@9 745 else
alpar@9 746 aij->c_next->c_prev = aij->c_prev;
alpar@9 747 /* return the element to the memory pool */
alpar@9 748 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 749 /* if the corresponding column is basic, invalidate the basis
alpar@9 750 factorization */
alpar@9 751 if (col->stat == GLP_BS) lp->valid = 0;
alpar@9 752 }
alpar@9 753 /* store new contents of i-th row */
alpar@9 754 if (!(0 <= len && len <= lp->n))
alpar@9 755 xerror("glp_set_mat_row: i = %d; len = %d; invalid row length "
alpar@9 756 "\n", i, len);
alpar@9 757 if (len > NNZ_MAX - lp->nnz)
alpar@9 758 xerror("glp_set_mat_row: i = %d; len = %d; too many constraint"
alpar@9 759 " coefficients\n", i, len);
alpar@9 760 for (k = 1; k <= len; k++)
alpar@9 761 { /* take number j of corresponding column */
alpar@9 762 j = ind[k];
alpar@9 763 /* obtain pointer to j-th column */
alpar@9 764 if (!(1 <= j && j <= lp->n))
alpar@9 765 xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index"
alpar@9 766 " out of range\n", i, k, j);
alpar@9 767 col = lp->col[j];
alpar@9 768 /* if there is element with the same column index, it can only
alpar@9 769 be found in the beginning of j-th column list */
alpar@9 770 if (col->ptr != NULL && col->ptr->row->i == i)
alpar@9 771 xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co"
alpar@9 772 "lumn indices not allowed\n", i, k, j);
alpar@9 773 /* create new element */
alpar@9 774 aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
alpar@9 775 aij->row = row;
alpar@9 776 aij->col = col;
alpar@9 777 aij->val = val[k];
alpar@9 778 /* add the new element to the beginning of i-th row and j-th
alpar@9 779 column lists */
alpar@9 780 aij->r_prev = NULL;
alpar@9 781 aij->r_next = row->ptr;
alpar@9 782 aij->c_prev = NULL;
alpar@9 783 aij->c_next = col->ptr;
alpar@9 784 if (aij->r_next != NULL) aij->r_next->r_prev = aij;
alpar@9 785 if (aij->c_next != NULL) aij->c_next->c_prev = aij;
alpar@9 786 row->ptr = col->ptr = aij;
alpar@9 787 /* if the corresponding column is basic, invalidate the basis
alpar@9 788 factorization */
alpar@9 789 if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0;
alpar@9 790 }
alpar@9 791 /* remove zero elements from i-th row */
alpar@9 792 for (aij = row->ptr; aij != NULL; aij = next)
alpar@9 793 { next = aij->r_next;
alpar@9 794 if (aij->val == 0.0)
alpar@9 795 { /* remove the element from the row list */
alpar@9 796 if (aij->r_prev == NULL)
alpar@9 797 row->ptr = next;
alpar@9 798 else
alpar@9 799 aij->r_prev->r_next = next;
alpar@9 800 if (next == NULL)
alpar@9 801 ;
alpar@9 802 else
alpar@9 803 next->r_prev = aij->r_prev;
alpar@9 804 /* remove the element from the column list */
alpar@9 805 xassert(aij->c_prev == NULL);
alpar@9 806 aij->col->ptr = aij->c_next;
alpar@9 807 if (aij->c_next != NULL) aij->c_next->c_prev = NULL;
alpar@9 808 /* return the element to the memory pool */
alpar@9 809 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 810 }
alpar@9 811 }
alpar@9 812 return;
alpar@9 813 }
alpar@9 814
alpar@9 815 /***********************************************************************
alpar@9 816 * NAME
alpar@9 817 *
alpar@9 818 * glp_set_mat_col - set (replace) column of the constraint matrix
alpar@9 819 *
alpar@9 820 * SYNOPSIS
alpar@9 821 *
alpar@9 822 * void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
alpar@9 823 * const double val[]);
alpar@9 824 *
alpar@9 825 * DESCRIPTION
alpar@9 826 *
alpar@9 827 * The routine glp_set_mat_col stores (replaces) the contents of j-th
alpar@9 828 * column of the constraint matrix of the specified problem object.
alpar@9 829 *
alpar@9 830 * Row indices and numeric values of new column elements must be placed
alpar@9 831 * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
alpar@9 832 * 0 <= len <= m is the new length of j-th column, m is the current
alpar@9 833 * number of rows in the problem object. Elements with identical column
alpar@9 834 * indices are not allowed. Zero elements are allowed, but they are not
alpar@9 835 * stored in the constraint matrix.
alpar@9 836 *
alpar@9 837 * If the parameter len is zero, the parameters ind and/or val can be
alpar@9 838 * specified as NULL. */
alpar@9 839
alpar@9 840 void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
alpar@9 841 const double val[])
alpar@9 842 { glp_tree *tree = lp->tree;
alpar@9 843 GLPROW *row;
alpar@9 844 GLPCOL *col;
alpar@9 845 GLPAIJ *aij, *next;
alpar@9 846 int i, k;
alpar@9 847 if (tree != NULL && tree->reason != 0)
alpar@9 848 xerror("glp_set_mat_col: operation not allowed\n");
alpar@9 849 /* obtain pointer to j-th column */
alpar@9 850 if (!(1 <= j && j <= lp->n))
alpar@9 851 xerror("glp_set_mat_col: j = %d; column number out of range\n",
alpar@9 852 j);
alpar@9 853 col = lp->col[j];
alpar@9 854 /* remove all existing elements from j-th column */
alpar@9 855 while (col->ptr != NULL)
alpar@9 856 { /* take next element in the column */
alpar@9 857 aij = col->ptr;
alpar@9 858 /* remove the element from the column list */
alpar@9 859 col->ptr = aij->c_next;
alpar@9 860 /* obtain pointer to corresponding row */
alpar@9 861 row = aij->row;
alpar@9 862 /* remove the element from the row list */
alpar@9 863 if (aij->r_prev == NULL)
alpar@9 864 row->ptr = aij->r_next;
alpar@9 865 else
alpar@9 866 aij->r_prev->r_next = aij->r_next;
alpar@9 867 if (aij->r_next == NULL)
alpar@9 868 ;
alpar@9 869 else
alpar@9 870 aij->r_next->r_prev = aij->r_prev;
alpar@9 871 /* return the element to the memory pool */
alpar@9 872 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 873 }
alpar@9 874 /* store new contents of j-th column */
alpar@9 875 if (!(0 <= len && len <= lp->m))
alpar@9 876 xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng"
alpar@9 877 "th\n", j, len);
alpar@9 878 if (len > NNZ_MAX - lp->nnz)
alpar@9 879 xerror("glp_set_mat_col: j = %d; len = %d; too many constraint"
alpar@9 880 " coefficients\n", j, len);
alpar@9 881 for (k = 1; k <= len; k++)
alpar@9 882 { /* take number i of corresponding row */
alpar@9 883 i = ind[k];
alpar@9 884 /* obtain pointer to i-th row */
alpar@9 885 if (!(1 <= i && i <= lp->m))
alpar@9 886 xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou"
alpar@9 887 "t of range\n", j, k, i);
alpar@9 888 row = lp->row[i];
alpar@9 889 /* if there is element with the same row index, it can only be
alpar@9 890 found in the beginning of i-th row list */
alpar@9 891 if (row->ptr != NULL && row->ptr->col->j == j)
alpar@9 892 xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro"
alpar@9 893 "w indices not allowed\n", j, k, i);
alpar@9 894 /* create new element */
alpar@9 895 aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
alpar@9 896 aij->row = row;
alpar@9 897 aij->col = col;
alpar@9 898 aij->val = val[k];
alpar@9 899 /* add the new element to the beginning of i-th row and j-th
alpar@9 900 column lists */
alpar@9 901 aij->r_prev = NULL;
alpar@9 902 aij->r_next = row->ptr;
alpar@9 903 aij->c_prev = NULL;
alpar@9 904 aij->c_next = col->ptr;
alpar@9 905 if (aij->r_next != NULL) aij->r_next->r_prev = aij;
alpar@9 906 if (aij->c_next != NULL) aij->c_next->c_prev = aij;
alpar@9 907 row->ptr = col->ptr = aij;
alpar@9 908 }
alpar@9 909 /* remove zero elements from j-th column */
alpar@9 910 for (aij = col->ptr; aij != NULL; aij = next)
alpar@9 911 { next = aij->c_next;
alpar@9 912 if (aij->val == 0.0)
alpar@9 913 { /* remove the element from the row list */
alpar@9 914 xassert(aij->r_prev == NULL);
alpar@9 915 aij->row->ptr = aij->r_next;
alpar@9 916 if (aij->r_next != NULL) aij->r_next->r_prev = NULL;
alpar@9 917 /* remove the element from the column list */
alpar@9 918 if (aij->c_prev == NULL)
alpar@9 919 col->ptr = next;
alpar@9 920 else
alpar@9 921 aij->c_prev->c_next = next;
alpar@9 922 if (next == NULL)
alpar@9 923 ;
alpar@9 924 else
alpar@9 925 next->c_prev = aij->c_prev;
alpar@9 926 /* return the element to the memory pool */
alpar@9 927 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 928 }
alpar@9 929 }
alpar@9 930 /* if j-th column is basic, invalidate the basis factorization */
alpar@9 931 if (col->stat == GLP_BS) lp->valid = 0;
alpar@9 932 return;
alpar@9 933 }
alpar@9 934
alpar@9 935 /***********************************************************************
alpar@9 936 * NAME
alpar@9 937 *
alpar@9 938 * glp_load_matrix - load (replace) the whole constraint matrix
alpar@9 939 *
alpar@9 940 * SYNOPSIS
alpar@9 941 *
alpar@9 942 * void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
alpar@9 943 * const int ja[], const double ar[]);
alpar@9 944 *
alpar@9 945 * DESCRIPTION
alpar@9 946 *
alpar@9 947 * The routine glp_load_matrix loads the constraint matrix passed in
alpar@9 948 * the arrays ia, ja, and ar into the specified problem object. Before
alpar@9 949 * loading the current contents of the constraint matrix is destroyed.
alpar@9 950 *
alpar@9 951 * Constraint coefficients (elements of the constraint matrix) must be
alpar@9 952 * specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne,
alpar@9 953 * where ia[k] is the row index, ja[k] is the column index, ar[k] is a
alpar@9 954 * numeric value of corresponding constraint coefficient. The parameter
alpar@9 955 * ne specifies the total number of (non-zero) elements in the matrix
alpar@9 956 * to be loaded. Coefficients with identical indices are not allowed.
alpar@9 957 * Zero coefficients are allowed, however, they are not stored in the
alpar@9 958 * constraint matrix.
alpar@9 959 *
alpar@9 960 * If the parameter ne is zero, the parameters ia, ja, and ar can be
alpar@9 961 * specified as NULL. */
alpar@9 962
alpar@9 963 void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
alpar@9 964 const int ja[], const double ar[])
alpar@9 965 { glp_tree *tree = lp->tree;
alpar@9 966 GLPROW *row;
alpar@9 967 GLPCOL *col;
alpar@9 968 GLPAIJ *aij, *next;
alpar@9 969 int i, j, k;
alpar@9 970 if (tree != NULL && tree->reason != 0)
alpar@9 971 xerror("glp_load_matrix: operation not allowed\n");
alpar@9 972 /* clear the constraint matrix */
alpar@9 973 for (i = 1; i <= lp->m; i++)
alpar@9 974 { row = lp->row[i];
alpar@9 975 while (row->ptr != NULL)
alpar@9 976 { aij = row->ptr;
alpar@9 977 row->ptr = aij->r_next;
alpar@9 978 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 979 }
alpar@9 980 }
alpar@9 981 xassert(lp->nnz == 0);
alpar@9 982 for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL;
alpar@9 983 /* load the new contents of the constraint matrix and build its
alpar@9 984 row lists */
alpar@9 985 if (ne < 0)
alpar@9 986 xerror("glp_load_matrix: ne = %d; invalid number of constraint"
alpar@9 987 " coefficients\n", ne);
alpar@9 988 if (ne > NNZ_MAX)
alpar@9 989 xerror("glp_load_matrix: ne = %d; too many constraint coeffici"
alpar@9 990 "ents\n", ne);
alpar@9 991 for (k = 1; k <= ne; k++)
alpar@9 992 { /* take indices of new element */
alpar@9 993 i = ia[k], j = ja[k];
alpar@9 994 /* obtain pointer to i-th row */
alpar@9 995 if (!(1 <= i && i <= lp->m))
alpar@9 996 xerror("glp_load_matrix: ia[%d] = %d; row index out of rang"
alpar@9 997 "e\n", k, i);
alpar@9 998 row = lp->row[i];
alpar@9 999 /* obtain pointer to j-th column */
alpar@9 1000 if (!(1 <= j && j <= lp->n))
alpar@9 1001 xerror("glp_load_matrix: ja[%d] = %d; column index out of r"
alpar@9 1002 "ange\n", k, j);
alpar@9 1003 col = lp->col[j];
alpar@9 1004 /* create new element */
alpar@9 1005 aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
alpar@9 1006 aij->row = row;
alpar@9 1007 aij->col = col;
alpar@9 1008 aij->val = ar[k];
alpar@9 1009 /* add the new element to the beginning of i-th row list */
alpar@9 1010 aij->r_prev = NULL;
alpar@9 1011 aij->r_next = row->ptr;
alpar@9 1012 if (aij->r_next != NULL) aij->r_next->r_prev = aij;
alpar@9 1013 row->ptr = aij;
alpar@9 1014 }
alpar@9 1015 xassert(lp->nnz == ne);
alpar@9 1016 /* build column lists of the constraint matrix and check elements
alpar@9 1017 with identical indices */
alpar@9 1018 for (i = 1; i <= lp->m; i++)
alpar@9 1019 { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next)
alpar@9 1020 { /* obtain pointer to corresponding column */
alpar@9 1021 col = aij->col;
alpar@9 1022 /* if there is element with identical indices, it can only
alpar@9 1023 be found in the beginning of j-th column list */
alpar@9 1024 if (col->ptr != NULL && col->ptr->row->i == i)
alpar@9 1025 { for (k = 1; k <= ne; k++)
alpar@9 1026 if (ia[k] == i && ja[k] == col->j) break;
alpar@9 1027 xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat"
alpar@9 1028 "e indices not allowed\n", k, i, k, col->j);
alpar@9 1029 }
alpar@9 1030 /* add the element to the beginning of j-th column list */
alpar@9 1031 aij->c_prev = NULL;
alpar@9 1032 aij->c_next = col->ptr;
alpar@9 1033 if (aij->c_next != NULL) aij->c_next->c_prev = aij;
alpar@9 1034 col->ptr = aij;
alpar@9 1035 }
alpar@9 1036 }
alpar@9 1037 /* remove zero elements from the constraint matrix */
alpar@9 1038 for (i = 1; i <= lp->m; i++)
alpar@9 1039 { row = lp->row[i];
alpar@9 1040 for (aij = row->ptr; aij != NULL; aij = next)
alpar@9 1041 { next = aij->r_next;
alpar@9 1042 if (aij->val == 0.0)
alpar@9 1043 { /* remove the element from the row list */
alpar@9 1044 if (aij->r_prev == NULL)
alpar@9 1045 row->ptr = next;
alpar@9 1046 else
alpar@9 1047 aij->r_prev->r_next = next;
alpar@9 1048 if (next == NULL)
alpar@9 1049 ;
alpar@9 1050 else
alpar@9 1051 next->r_prev = aij->r_prev;
alpar@9 1052 /* remove the element from the column list */
alpar@9 1053 if (aij->c_prev == NULL)
alpar@9 1054 aij->col->ptr = aij->c_next;
alpar@9 1055 else
alpar@9 1056 aij->c_prev->c_next = aij->c_next;
alpar@9 1057 if (aij->c_next == NULL)
alpar@9 1058 ;
alpar@9 1059 else
alpar@9 1060 aij->c_next->c_prev = aij->c_prev;
alpar@9 1061 /* return the element to the memory pool */
alpar@9 1062 dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
alpar@9 1063 }
alpar@9 1064 }
alpar@9 1065 }
alpar@9 1066 /* invalidate the basis factorization */
alpar@9 1067 lp->valid = 0;
alpar@9 1068 return;
alpar@9 1069 }
alpar@9 1070
alpar@9 1071 /***********************************************************************
alpar@9 1072 * NAME
alpar@9 1073 *
alpar@9 1074 * glp_check_dup - check for duplicate elements in sparse matrix
alpar@9 1075 *
alpar@9 1076 * SYNOPSIS
alpar@9 1077 *
alpar@9 1078 * int glp_check_dup(int m, int n, int ne, const int ia[],
alpar@9 1079 * const int ja[]);
alpar@9 1080 *
alpar@9 1081 * DESCRIPTION
alpar@9 1082 *
alpar@9 1083 * The routine glp_check_dup checks for duplicate elements (that is,
alpar@9 1084 * elements with identical indices) in a sparse matrix specified in the
alpar@9 1085 * coordinate format.
alpar@9 1086 *
alpar@9 1087 * The parameters m and n specifies, respectively, the number of rows
alpar@9 1088 * and columns in the matrix, m >= 0, n >= 0.
alpar@9 1089 *
alpar@9 1090 * The parameter ne specifies the number of (structurally) non-zero
alpar@9 1091 * elements in the matrix, ne >= 0.
alpar@9 1092 *
alpar@9 1093 * Elements of the matrix are specified as doublets (ia[k],ja[k]) for
alpar@9 1094 * k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index.
alpar@9 1095 *
alpar@9 1096 * The routine glp_check_dup can be used prior to a call to the routine
alpar@9 1097 * glp_load_matrix to check that the constraint matrix to be loaded has
alpar@9 1098 * no duplicate elements.
alpar@9 1099 *
alpar@9 1100 * RETURNS
alpar@9 1101 *
alpar@9 1102 * The routine glp_check_dup returns one of the following values:
alpar@9 1103 *
alpar@9 1104 * 0 - the matrix has no duplicate elements;
alpar@9 1105 *
alpar@9 1106 * -k - indices ia[k] or/and ja[k] are out of range;
alpar@9 1107 *
alpar@9 1108 * +k - element (ia[k],ja[k]) is duplicate. */
alpar@9 1109
alpar@9 1110 int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[])
alpar@9 1111 { int i, j, k, *ptr, *next, ret;
alpar@9 1112 char *flag;
alpar@9 1113 if (m < 0)
alpar@9 1114 xerror("glp_check_dup: m = %d; invalid parameter\n");
alpar@9 1115 if (n < 0)
alpar@9 1116 xerror("glp_check_dup: n = %d; invalid parameter\n");
alpar@9 1117 if (ne < 0)
alpar@9 1118 xerror("glp_check_dup: ne = %d; invalid parameter\n");
alpar@9 1119 if (ne > 0 && ia == NULL)
alpar@9 1120 xerror("glp_check_dup: ia = %p; invalid parameter\n", ia);
alpar@9 1121 if (ne > 0 && ja == NULL)
alpar@9 1122 xerror("glp_check_dup: ja = %p; invalid parameter\n", ja);
alpar@9 1123 for (k = 1; k <= ne; k++)
alpar@9 1124 { i = ia[k], j = ja[k];
alpar@9 1125 if (!(1 <= i && i <= m && 1 <= j && j <= n))
alpar@9 1126 { ret = -k;
alpar@9 1127 goto done;
alpar@9 1128 }
alpar@9 1129 }
alpar@9 1130 if (m == 0 || n == 0)
alpar@9 1131 { ret = 0;
alpar@9 1132 goto done;
alpar@9 1133 }
alpar@9 1134 /* allocate working arrays */
alpar@9 1135 ptr = xcalloc(1+m, sizeof(int));
alpar@9 1136 next = xcalloc(1+ne, sizeof(int));
alpar@9 1137 flag = xcalloc(1+n, sizeof(char));
alpar@9 1138 /* build row lists */
alpar@9 1139 for (i = 1; i <= m; i++)
alpar@9 1140 ptr[i] = 0;
alpar@9 1141 for (k = 1; k <= ne; k++)
alpar@9 1142 { i = ia[k];
alpar@9 1143 next[k] = ptr[i];
alpar@9 1144 ptr[i] = k;
alpar@9 1145 }
alpar@9 1146 /* clear column flags */
alpar@9 1147 for (j = 1; j <= n; j++)
alpar@9 1148 flag[j] = 0;
alpar@9 1149 /* check for duplicate elements */
alpar@9 1150 for (i = 1; i <= m; i++)
alpar@9 1151 { for (k = ptr[i]; k != 0; k = next[k])
alpar@9 1152 { j = ja[k];
alpar@9 1153 if (flag[j])
alpar@9 1154 { /* find first element (i,j) */
alpar@9 1155 for (k = 1; k <= ne; k++)
alpar@9 1156 if (ia[k] == i && ja[k] == j) break;
alpar@9 1157 xassert(k <= ne);
alpar@9 1158 /* find next (duplicate) element (i,j) */
alpar@9 1159 for (k++; k <= ne; k++)
alpar@9 1160 if (ia[k] == i && ja[k] == j) break;
alpar@9 1161 xassert(k <= ne);
alpar@9 1162 ret = +k;
alpar@9 1163 goto skip;
alpar@9 1164 }
alpar@9 1165 flag[j] = 1;
alpar@9 1166 }
alpar@9 1167 /* clear column flags */
alpar@9 1168 for (k = ptr[i]; k != 0; k = next[k])
alpar@9 1169 flag[ja[k]] = 0;
alpar@9 1170 }
alpar@9 1171 /* no duplicate element found */
alpar@9 1172 ret = 0;
alpar@9 1173 skip: /* free working arrays */
alpar@9 1174 xfree(ptr);
alpar@9 1175 xfree(next);
alpar@9 1176 xfree(flag);
alpar@9 1177 done: return ret;
alpar@9 1178 }
alpar@9 1179
alpar@9 1180 /***********************************************************************
alpar@9 1181 * NAME
alpar@9 1182 *
alpar@9 1183 * glp_sort_matrix - sort elements of the constraint matrix
alpar@9 1184 *
alpar@9 1185 * SYNOPSIS
alpar@9 1186 *
alpar@9 1187 * void glp_sort_matrix(glp_prob *P);
alpar@9 1188 *
alpar@9 1189 * DESCRIPTION
alpar@9 1190 *
alpar@9 1191 * The routine glp_sort_matrix sorts elements of the constraint matrix
alpar@9 1192 * rebuilding its row and column linked lists. On exit from the routine
alpar@9 1193 * the constraint matrix is not changed, however, elements in the row
alpar@9 1194 * linked lists become ordered by ascending column indices, and the
alpar@9 1195 * elements in the column linked lists become ordered by ascending row
alpar@9 1196 * indices. */
alpar@9 1197
alpar@9 1198 void glp_sort_matrix(glp_prob *P)
alpar@9 1199 { GLPAIJ *aij;
alpar@9 1200 int i, j;
alpar@9 1201 if (P == NULL || P->magic != GLP_PROB_MAGIC)
alpar@9 1202 xerror("glp_sort_matrix: P = %p; invalid problem object\n",
alpar@9 1203 P);
alpar@9 1204 /* rebuild row linked lists */
alpar@9 1205 for (i = P->m; i >= 1; i--)
alpar@9 1206 P->row[i]->ptr = NULL;
alpar@9 1207 for (j = P->n; j >= 1; j--)
alpar@9 1208 { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next)
alpar@9 1209 { i = aij->row->i;
alpar@9 1210 aij->r_prev = NULL;
alpar@9 1211 aij->r_next = P->row[i]->ptr;
alpar@9 1212 if (aij->r_next != NULL) aij->r_next->r_prev = aij;
alpar@9 1213 P->row[i]->ptr = aij;
alpar@9 1214 }
alpar@9 1215 }
alpar@9 1216 /* rebuild column linked lists */
alpar@9 1217 for (j = P->n; j >= 1; j--)
alpar@9 1218 P->col[j]->ptr = NULL;
alpar@9 1219 for (i = P->m; i >= 1; i--)
alpar@9 1220 { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
alpar@9 1221 { j = aij->col->j;
alpar@9 1222 aij->c_prev = NULL;
alpar@9 1223 aij->c_next = P->col[j]->ptr;
alpar@9 1224 if (aij->c_next != NULL) aij->c_next->c_prev = aij;
alpar@9 1225 P->col[j]->ptr = aij;
alpar@9 1226 }
alpar@9 1227 }
alpar@9 1228 return;
alpar@9 1229 }
alpar@9 1230
alpar@9 1231 /***********************************************************************
alpar@9 1232 * NAME
alpar@9 1233 *
alpar@9 1234 * glp_del_rows - delete rows from problem object
alpar@9 1235 *
alpar@9 1236 * SYNOPSIS
alpar@9 1237 *
alpar@9 1238 * void glp_del_rows(glp_prob *lp, int nrs, const int num[]);
alpar@9 1239 *
alpar@9 1240 * DESCRIPTION
alpar@9 1241 *
alpar@9 1242 * The routine glp_del_rows deletes rows from the specified problem
alpar@9 1243 * object. Ordinal numbers of rows to be deleted should be placed in
alpar@9 1244 * locations num[1], ..., num[nrs], where nrs > 0.
alpar@9 1245 *
alpar@9 1246 * Note that deleting rows involves changing ordinal numbers of other
alpar@9 1247 * rows remaining in the problem object. New ordinal numbers of the
alpar@9 1248 * remaining rows are assigned under the assumption that the original
alpar@9 1249 * order of rows is not changed. */
alpar@9 1250
alpar@9 1251 void glp_del_rows(glp_prob *lp, int nrs, const int num[])
alpar@9 1252 { glp_tree *tree = lp->tree;
alpar@9 1253 GLPROW *row;
alpar@9 1254 int i, k, m_new;
alpar@9 1255 /* mark rows to be deleted */
alpar@9 1256 if (!(1 <= nrs && nrs <= lp->m))
alpar@9 1257 xerror("glp_del_rows: nrs = %d; invalid number of rows\n",
alpar@9 1258 nrs);
alpar@9 1259 for (k = 1; k <= nrs; k++)
alpar@9 1260 { /* take the number of row to be deleted */
alpar@9 1261 i = num[k];
alpar@9 1262 /* obtain pointer to i-th row */
alpar@9 1263 if (!(1 <= i && i <= lp->m))
alpar@9 1264 xerror("glp_del_rows: num[%d] = %d; row number out of range"
alpar@9 1265 "\n", k, i);
alpar@9 1266 row = lp->row[i];
alpar@9 1267 if (tree != NULL && tree->reason != 0)
alpar@9 1268 { if (!(tree->reason == GLP_IROWGEN ||
alpar@9 1269 tree->reason == GLP_ICUTGEN))
alpar@9 1270 xerror("glp_del_rows: operation not allowed\n");
alpar@9 1271 xassert(tree->curr != NULL);
alpar@9 1272 if (row->level != tree->curr->level)
alpar@9 1273 xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
alpar@9 1274 "elete row created not in current subproblem\n", k,i);
alpar@9 1275 if (row->stat != GLP_BS)
alpar@9 1276 xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
alpar@9 1277 "elete active row (constraint)\n", k, i);
alpar@9 1278 tree->reinv = 1;
alpar@9 1279 }
alpar@9 1280 /* check that the row is not marked yet */
alpar@9 1281 if (row->i == 0)
alpar@9 1282 xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n"
alpar@9 1283 "ot allowed\n", k, i);
alpar@9 1284 /* erase symbolic name assigned to the row */
alpar@9 1285 glp_set_row_name(lp, i, NULL);
alpar@9 1286 xassert(row->node == NULL);
alpar@9 1287 /* erase corresponding row of the constraint matrix */
alpar@9 1288 glp_set_mat_row(lp, i, 0, NULL, NULL);
alpar@9 1289 xassert(row->ptr == NULL);
alpar@9 1290 /* mark the row to be deleted */
alpar@9 1291 row->i = 0;
alpar@9 1292 }
alpar@9 1293 /* delete all marked rows from the row list */
alpar@9 1294 m_new = 0;
alpar@9 1295 for (i = 1; i <= lp->m; i++)
alpar@9 1296 { /* obtain pointer to i-th row */
alpar@9 1297 row = lp->row[i];
alpar@9 1298 /* check if the row is marked */
alpar@9 1299 if (row->i == 0)
alpar@9 1300 { /* it is marked, delete it */
alpar@9 1301 dmp_free_atom(lp->pool, row, sizeof(GLPROW));
alpar@9 1302 }
alpar@9 1303 else
alpar@9 1304 { /* it is not marked; keep it */
alpar@9 1305 row->i = ++m_new;
alpar@9 1306 lp->row[row->i] = row;
alpar@9 1307 }
alpar@9 1308 }
alpar@9 1309 /* set new number of rows */
alpar@9 1310 lp->m = m_new;
alpar@9 1311 /* invalidate the basis factorization */
alpar@9 1312 lp->valid = 0;
alpar@9 1313 return;
alpar@9 1314 }
alpar@9 1315
alpar@9 1316 /***********************************************************************
alpar@9 1317 * NAME
alpar@9 1318 *
alpar@9 1319 * glp_del_cols - delete columns from problem object
alpar@9 1320 *
alpar@9 1321 * SYNOPSIS
alpar@9 1322 *
alpar@9 1323 * void glp_del_cols(glp_prob *lp, int ncs, const int num[]);
alpar@9 1324 *
alpar@9 1325 * DESCRIPTION
alpar@9 1326 *
alpar@9 1327 * The routine glp_del_cols deletes columns from the specified problem
alpar@9 1328 * object. Ordinal numbers of columns to be deleted should be placed in
alpar@9 1329 * locations num[1], ..., num[ncs], where ncs > 0.
alpar@9 1330 *
alpar@9 1331 * Note that deleting columns involves changing ordinal numbers of
alpar@9 1332 * other columns remaining in the problem object. New ordinal numbers
alpar@9 1333 * of the remaining columns are assigned under the assumption that the
alpar@9 1334 * original order of columns is not changed. */
alpar@9 1335
alpar@9 1336 void glp_del_cols(glp_prob *lp, int ncs, const int num[])
alpar@9 1337 { glp_tree *tree = lp->tree;
alpar@9 1338 GLPCOL *col;
alpar@9 1339 int j, k, n_new;
alpar@9 1340 if (tree != NULL && tree->reason != 0)
alpar@9 1341 xerror("glp_del_cols: operation not allowed\n");
alpar@9 1342 /* mark columns to be deleted */
alpar@9 1343 if (!(1 <= ncs && ncs <= lp->n))
alpar@9 1344 xerror("glp_del_cols: ncs = %d; invalid number of columns\n",
alpar@9 1345 ncs);
alpar@9 1346 for (k = 1; k <= ncs; k++)
alpar@9 1347 { /* take the number of column to be deleted */
alpar@9 1348 j = num[k];
alpar@9 1349 /* obtain pointer to j-th column */
alpar@9 1350 if (!(1 <= j && j <= lp->n))
alpar@9 1351 xerror("glp_del_cols: num[%d] = %d; column number out of ra"
alpar@9 1352 "nge", k, j);
alpar@9 1353 col = lp->col[j];
alpar@9 1354 /* check that the column is not marked yet */
alpar@9 1355 if (col->j == 0)
alpar@9 1356 xerror("glp_del_cols: num[%d] = %d; duplicate column number"
alpar@9 1357 "s not allowed\n", k, j);
alpar@9 1358 /* erase symbolic name assigned to the column */
alpar@9 1359 glp_set_col_name(lp, j, NULL);
alpar@9 1360 xassert(col->node == NULL);
alpar@9 1361 /* erase corresponding column of the constraint matrix */
alpar@9 1362 glp_set_mat_col(lp, j, 0, NULL, NULL);
alpar@9 1363 xassert(col->ptr == NULL);
alpar@9 1364 /* mark the column to be deleted */
alpar@9 1365 col->j = 0;
alpar@9 1366 /* if it is basic, invalidate the basis factorization */
alpar@9 1367 if (col->stat == GLP_BS) lp->valid = 0;
alpar@9 1368 }
alpar@9 1369 /* delete all marked columns from the column list */
alpar@9 1370 n_new = 0;
alpar@9 1371 for (j = 1; j <= lp->n; j++)
alpar@9 1372 { /* obtain pointer to j-th column */
alpar@9 1373 col = lp->col[j];
alpar@9 1374 /* check if the column is marked */
alpar@9 1375 if (col->j == 0)
alpar@9 1376 { /* it is marked; delete it */
alpar@9 1377 dmp_free_atom(lp->pool, col, sizeof(GLPCOL));
alpar@9 1378 }
alpar@9 1379 else
alpar@9 1380 { /* it is not marked; keep it */
alpar@9 1381 col->j = ++n_new;
alpar@9 1382 lp->col[col->j] = col;
alpar@9 1383 }
alpar@9 1384 }
alpar@9 1385 /* set new number of columns */
alpar@9 1386 lp->n = n_new;
alpar@9 1387 /* if the basis header is still valid, adjust it */
alpar@9 1388 if (lp->valid)
alpar@9 1389 { int m = lp->m;
alpar@9 1390 int *head = lp->head;
alpar@9 1391 for (j = 1; j <= n_new; j++)
alpar@9 1392 { k = lp->col[j]->bind;
alpar@9 1393 if (k != 0)
alpar@9 1394 { xassert(1 <= k && k <= m);
alpar@9 1395 head[k] = m + j;
alpar@9 1396 }
alpar@9 1397 }
alpar@9 1398 }
alpar@9 1399 return;
alpar@9 1400 }
alpar@9 1401
alpar@9 1402 /***********************************************************************
alpar@9 1403 * NAME
alpar@9 1404 *
alpar@9 1405 * glp_copy_prob - copy problem object content
alpar@9 1406 *
alpar@9 1407 * SYNOPSIS
alpar@9 1408 *
alpar@9 1409 * void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names);
alpar@9 1410 *
alpar@9 1411 * DESCRIPTION
alpar@9 1412 *
alpar@9 1413 * The routine glp_copy_prob copies the content of the problem object
alpar@9 1414 * prob to the problem object dest.
alpar@9 1415 *
alpar@9 1416 * The parameter names is a flag. If it is non-zero, the routine also
alpar@9 1417 * copies all symbolic names; otherwise, if it is zero, symbolic names
alpar@9 1418 * are not copied. */
alpar@9 1419
alpar@9 1420 void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names)
alpar@9 1421 { glp_tree *tree = dest->tree;
alpar@9 1422 glp_bfcp bfcp;
alpar@9 1423 int i, j, len, *ind;
alpar@9 1424 double *val;
alpar@9 1425 if (tree != NULL && tree->reason != 0)
alpar@9 1426 xerror("glp_copy_prob: operation not allowed\n");
alpar@9 1427 if (dest == prob)
alpar@9 1428 xerror("glp_copy_prob: copying problem object to itself not al"
alpar@9 1429 "lowed\n");
alpar@9 1430 if (!(names == GLP_ON || names == GLP_OFF))
alpar@9 1431 xerror("glp_copy_prob: names = %d; invalid parameter\n",
alpar@9 1432 names);
alpar@9 1433 glp_erase_prob(dest);
alpar@9 1434 if (names && prob->name != NULL)
alpar@9 1435 glp_set_prob_name(dest, prob->name);
alpar@9 1436 if (names && prob->obj != NULL)
alpar@9 1437 glp_set_obj_name(dest, prob->obj);
alpar@9 1438 dest->dir = prob->dir;
alpar@9 1439 dest->c0 = prob->c0;
alpar@9 1440 if (prob->m > 0)
alpar@9 1441 glp_add_rows(dest, prob->m);
alpar@9 1442 if (prob->n > 0)
alpar@9 1443 glp_add_cols(dest, prob->n);
alpar@9 1444 glp_get_bfcp(prob, &bfcp);
alpar@9 1445 glp_set_bfcp(dest, &bfcp);
alpar@9 1446 dest->pbs_stat = prob->pbs_stat;
alpar@9 1447 dest->dbs_stat = prob->dbs_stat;
alpar@9 1448 dest->obj_val = prob->obj_val;
alpar@9 1449 dest->some = prob->some;
alpar@9 1450 dest->ipt_stat = prob->ipt_stat;
alpar@9 1451 dest->ipt_obj = prob->ipt_obj;
alpar@9 1452 dest->mip_stat = prob->mip_stat;
alpar@9 1453 dest->mip_obj = prob->mip_obj;
alpar@9 1454 for (i = 1; i <= prob->m; i++)
alpar@9 1455 { GLPROW *to = dest->row[i];
alpar@9 1456 GLPROW *from = prob->row[i];
alpar@9 1457 if (names && from->name != NULL)
alpar@9 1458 glp_set_row_name(dest, i, from->name);
alpar@9 1459 to->type = from->type;
alpar@9 1460 to->lb = from->lb;
alpar@9 1461 to->ub = from->ub;
alpar@9 1462 to->rii = from->rii;
alpar@9 1463 to->stat = from->stat;
alpar@9 1464 to->prim = from->prim;
alpar@9 1465 to->dual = from->dual;
alpar@9 1466 to->pval = from->pval;
alpar@9 1467 to->dval = from->dval;
alpar@9 1468 to->mipx = from->mipx;
alpar@9 1469 }
alpar@9 1470 ind = xcalloc(1+prob->m, sizeof(int));
alpar@9 1471 val = xcalloc(1+prob->m, sizeof(double));
alpar@9 1472 for (j = 1; j <= prob->n; j++)
alpar@9 1473 { GLPCOL *to = dest->col[j];
alpar@9 1474 GLPCOL *from = prob->col[j];
alpar@9 1475 if (names && from->name != NULL)
alpar@9 1476 glp_set_col_name(dest, j, from->name);
alpar@9 1477 to->kind = from->kind;
alpar@9 1478 to->type = from->type;
alpar@9 1479 to->lb = from->lb;
alpar@9 1480 to->ub = from->ub;
alpar@9 1481 to->coef = from->coef;
alpar@9 1482 len = glp_get_mat_col(prob, j, ind, val);
alpar@9 1483 glp_set_mat_col(dest, j, len, ind, val);
alpar@9 1484 to->sjj = from->sjj;
alpar@9 1485 to->stat = from->stat;
alpar@9 1486 to->prim = from->prim;
alpar@9 1487 to->dual = from->dual;
alpar@9 1488 to->pval = from->pval;
alpar@9 1489 to->dval = from->dval;
alpar@9 1490 to->mipx = from->mipx;
alpar@9 1491 }
alpar@9 1492 xfree(ind);
alpar@9 1493 xfree(val);
alpar@9 1494 return;
alpar@9 1495 }
alpar@9 1496
alpar@9 1497 /***********************************************************************
alpar@9 1498 * NAME
alpar@9 1499 *
alpar@9 1500 * glp_erase_prob - erase problem object content
alpar@9 1501 *
alpar@9 1502 * SYNOPSIS
alpar@9 1503 *
alpar@9 1504 * void glp_erase_prob(glp_prob *lp);
alpar@9 1505 *
alpar@9 1506 * DESCRIPTION
alpar@9 1507 *
alpar@9 1508 * The routine glp_erase_prob erases the content of the specified
alpar@9 1509 * problem object. The effect of this operation is the same as if the
alpar@9 1510 * problem object would be deleted with the routine glp_delete_prob and
alpar@9 1511 * then created anew with the routine glp_create_prob, with exception
alpar@9 1512 * that the handle (pointer) to the problem object remains valid. */
alpar@9 1513
alpar@9 1514 static void delete_prob(glp_prob *lp);
alpar@9 1515
alpar@9 1516 void glp_erase_prob(glp_prob *lp)
alpar@9 1517 { glp_tree *tree = lp->tree;
alpar@9 1518 if (tree != NULL && tree->reason != 0)
alpar@9 1519 xerror("glp_erase_prob: operation not allowed\n");
alpar@9 1520 delete_prob(lp);
alpar@9 1521 create_prob(lp);
alpar@9 1522 return;
alpar@9 1523 }
alpar@9 1524
alpar@9 1525 /***********************************************************************
alpar@9 1526 * NAME
alpar@9 1527 *
alpar@9 1528 * glp_delete_prob - delete problem object
alpar@9 1529 *
alpar@9 1530 * SYNOPSIS
alpar@9 1531 *
alpar@9 1532 * void glp_delete_prob(glp_prob *lp);
alpar@9 1533 *
alpar@9 1534 * DESCRIPTION
alpar@9 1535 *
alpar@9 1536 * The routine glp_delete_prob deletes the specified problem object and
alpar@9 1537 * frees all the memory allocated to it. */
alpar@9 1538
alpar@9 1539 static void delete_prob(glp_prob *lp)
alpar@9 1540 { lp->magic = 0x3F3F3F3F;
alpar@9 1541 dmp_delete_pool(lp->pool);
alpar@9 1542 #if 0 /* 17/XI-2009 */
alpar@9 1543 xfree(lp->cps);
alpar@9 1544 #else
alpar@9 1545 if (lp->parms != NULL) xfree(lp->parms);
alpar@9 1546 #endif
alpar@9 1547 xassert(lp->tree == NULL);
alpar@9 1548 #if 0
alpar@9 1549 if (lp->cwa != NULL) xfree(lp->cwa);
alpar@9 1550 #endif
alpar@9 1551 xfree(lp->row);
alpar@9 1552 xfree(lp->col);
alpar@9 1553 if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree);
alpar@9 1554 if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree);
alpar@9 1555 xfree(lp->head);
alpar@9 1556 if (lp->bfcp != NULL) xfree(lp->bfcp);
alpar@9 1557 if (lp->bfd != NULL) bfd_delete_it(lp->bfd);
alpar@9 1558 return;
alpar@9 1559 }
alpar@9 1560
alpar@9 1561 void glp_delete_prob(glp_prob *lp)
alpar@9 1562 { glp_tree *tree = lp->tree;
alpar@9 1563 if (tree != NULL && tree->reason != 0)
alpar@9 1564 xerror("glp_delete_prob: operation not allowed\n");
alpar@9 1565 delete_prob(lp);
alpar@9 1566 xfree(lp);
alpar@9 1567 return;
alpar@9 1568 }
alpar@9 1569
alpar@9 1570 /* eof */