1 /* glpfhv.c (LP basis factorization, FHV eta file version) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
29 /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */
31 #define M_MAX 100000000 /* = 100*10^6 */
32 /* maximal order of the basis matrix */
34 /***********************************************************************
37 * fhv_create_it - create LP basis factorization
42 * FHV *fhv_create_it(void);
46 * The routine fhv_create_it creates a program object, which represents
47 * a factorization of LP basis.
51 * The routine fhv_create_it returns a pointer to the object created. */
53 FHV *fhv_create_it(void)
55 fhv = xmalloc(sizeof(FHV));
56 fhv->m_max = fhv->m = 0;
58 fhv->luf = luf_create_it();
61 fhv->hh_ind = fhv->hh_ptr = fhv->hh_len = NULL;
62 fhv->p0_row = fhv->p0_col = NULL;
70 /***********************************************************************
73 * fhv_factorize - compute LP basis factorization
78 * int fhv_factorize(FHV *fhv, int m, int (*col)(void *info, int j,
79 * int ind[], double val[]), void *info);
83 * The routine fhv_factorize computes the factorization of the basis
84 * matrix B specified by the routine col.
86 * The parameter fhv specified the basis factorization data structure
87 * created by the routine fhv_create_it.
89 * The parameter m specifies the order of B, m > 0.
91 * The formal routine col specifies the matrix B to be factorized. To
92 * obtain j-th column of A the routine fhv_factorize calls the routine
93 * col with the parameter j (1 <= j <= n). In response the routine col
94 * should store row indices and numerical values of non-zero elements
95 * of j-th column of B to locations ind[1,...,len] and val[1,...,len],
96 * respectively, where len is the number of non-zeros in j-th column
97 * returned on exit. Neither zero nor duplicate elements are allowed.
99 * The parameter info is a transit pointer passed to the routine col.
103 * 0 The factorization has been successfully computed.
106 * The specified matrix is singular within the working precision.
109 * The specified matrix is ill-conditioned.
111 * For more details see comments to the routine luf_factorize.
115 * The routine fhv_factorize calls the routine luf_factorize (see the
116 * module GLPLUF), which actually computes LU-factorization of the basis
117 * matrix B in the form
119 * [B] = (F, V, P, Q),
121 * where F and V are such matrices that
125 * and P and Q are such permutation matrices that the matrix
129 * is lower triangular with unity diagonal, and the matrix
133 * is upper triangular.
135 * In order to build the complete representation of the factorization
136 * (see formula (1) in the file glpfhv.h) the routine fhv_factorize just
137 * additionally sets H = I and P0 = P. */
139 int fhv_factorize(FHV *fhv, int m, int (*col)(void *info, int j,
140 int ind[], double val[]), void *info)
143 xfault("fhv_factorize: m = %d; invalid parameter\n", m);
145 xfault("fhv_factorize: m = %d; matrix too big\n", m);
147 /* invalidate the factorization */
149 /* allocate/reallocate arrays, if necessary */
150 if (fhv->hh_ind == NULL)
151 fhv->hh_ind = xcalloc(1+fhv->hh_max, sizeof(int));
152 if (fhv->hh_ptr == NULL)
153 fhv->hh_ptr = xcalloc(1+fhv->hh_max, sizeof(int));
154 if (fhv->hh_len == NULL)
155 fhv->hh_len = xcalloc(1+fhv->hh_max, sizeof(int));
157 { if (fhv->p0_row != NULL) xfree(fhv->p0_row);
158 if (fhv->p0_col != NULL) xfree(fhv->p0_col);
159 if (fhv->cc_ind != NULL) xfree(fhv->cc_ind);
160 if (fhv->cc_val != NULL) xfree(fhv->cc_val);
161 fhv->m_max = m + 100;
162 fhv->p0_row = xcalloc(1+fhv->m_max, sizeof(int));
163 fhv->p0_col = xcalloc(1+fhv->m_max, sizeof(int));
164 fhv->cc_ind = xcalloc(1+fhv->m_max, sizeof(int));
165 fhv->cc_val = xcalloc(1+fhv->m_max, sizeof(double));
167 /* try to factorize the basis matrix */
168 switch (luf_factorize(fhv->luf, m, col, info))
180 /* the basis matrix has been successfully factorized */
185 memcpy(&fhv->p0_row[1], &fhv->luf->pp_row[1], sizeof(int) * m);
186 memcpy(&fhv->p0_col[1], &fhv->luf->pp_col[1], sizeof(int) * m);
187 /* currently H has no factors */
190 done: /* return to the calling program */
194 /***********************************************************************
197 * fhv_h_solve - solve system H*x = b or H'*x = b
201 * #include "glpfhv.h"
202 * void fhv_h_solve(FHV *fhv, int tr, double x[]);
206 * The routine fhv_h_solve solves either the system H*x = b (if the
207 * flag tr is zero) or the system H'*x = b (if the flag tr is non-zero),
208 * where the matrix H is a component of the factorization specified by
209 * the parameter fhv, H' is a matrix transposed to H.
211 * On entry the array x should contain elements of the right-hand side
212 * vector b in locations x[1], ..., x[m], where m is the order of the
213 * matrix H. On exit this array will contain elements of the solution
214 * vector x in the same locations. */
216 void fhv_h_solve(FHV *fhv, int tr, double x[])
217 { int nfs = fhv->hh_nfs;
218 int *hh_ind = fhv->hh_ind;
219 int *hh_ptr = fhv->hh_ptr;
220 int *hh_len = fhv->hh_len;
221 int *sv_ind = fhv->luf->sv_ind;
222 double *sv_val = fhv->luf->sv_val;
223 int i, k, beg, end, ptr;
226 xfault("fhv_h_solve: the factorization is not valid\n");
228 { /* solve the system H*x = b */
229 for (k = 1; k <= nfs; k++)
233 end = beg + hh_len[k] - 1;
234 for (ptr = beg; ptr <= end; ptr++)
235 temp -= sv_val[ptr] * x[sv_ind[ptr]];
240 { /* solve the system H'*x = b */
241 for (k = nfs; k >= 1; k--)
244 if (temp == 0.0) continue;
246 end = beg + hh_len[k] - 1;
247 for (ptr = beg; ptr <= end; ptr++)
248 x[sv_ind[ptr]] -= sv_val[ptr] * temp;
254 /***********************************************************************
257 * fhv_ftran - perform forward transformation (solve system B*x = b)
261 * #include "glpfhv.h"
262 * void fhv_ftran(FHV *fhv, double x[]);
266 * The routine fhv_ftran performs forward transformation, i.e. solves
267 * the system B*x = b, where B is the basis matrix, x is the vector of
268 * unknowns to be computed, b is the vector of right-hand sides.
270 * On entry elements of the vector b should be stored in dense format
271 * in locations x[1], ..., x[m], where m is the number of rows. On exit
272 * the routine stores elements of the vector x in the same locations. */
274 void fhv_ftran(FHV *fhv, double x[])
275 { int *pp_row = fhv->luf->pp_row;
276 int *pp_col = fhv->luf->pp_col;
277 int *p0_row = fhv->p0_row;
278 int *p0_col = fhv->p0_col;
280 xfault("fhv_ftran: the factorization is not valid\n");
281 /* B = F*H*V, therefore inv(B) = inv(V)*inv(H)*inv(F) */
282 fhv->luf->pp_row = p0_row;
283 fhv->luf->pp_col = p0_col;
284 luf_f_solve(fhv->luf, 0, x);
285 fhv->luf->pp_row = pp_row;
286 fhv->luf->pp_col = pp_col;
287 fhv_h_solve(fhv, 0, x);
288 luf_v_solve(fhv->luf, 0, x);
292 /***********************************************************************
295 * fhv_btran - perform backward transformation (solve system B'*x = b)
299 * #include "glpfhv.h"
300 * void fhv_btran(FHV *fhv, double x[]);
304 * The routine fhv_btran performs backward transformation, i.e. solves
305 * the system B'*x = b, where B' is a matrix transposed to the basis
306 * matrix B, x is the vector of unknowns to be computed, b is the vector
307 * of right-hand sides.
309 * On entry elements of the vector b should be stored in dense format
310 * in locations x[1], ..., x[m], where m is the number of rows. On exit
311 * the routine stores elements of the vector x in the same locations. */
313 void fhv_btran(FHV *fhv, double x[])
314 { int *pp_row = fhv->luf->pp_row;
315 int *pp_col = fhv->luf->pp_col;
316 int *p0_row = fhv->p0_row;
317 int *p0_col = fhv->p0_col;
319 xfault("fhv_btran: the factorization is not valid\n");
320 /* B = F*H*V, therefore inv(B') = inv(F')*inv(H')*inv(V') */
321 luf_v_solve(fhv->luf, 1, x);
322 fhv_h_solve(fhv, 1, x);
323 fhv->luf->pp_row = p0_row;
324 fhv->luf->pp_col = p0_col;
325 luf_f_solve(fhv->luf, 1, x);
326 fhv->luf->pp_row = pp_row;
327 fhv->luf->pp_col = pp_col;
331 /***********************************************************************
334 * fhv_update_it - update LP basis factorization
338 * #include "glpfhv.h"
339 * int fhv_update_it(FHV *fhv, int j, int len, const int ind[],
340 * const double val[]);
344 * The routine fhv_update_it updates the factorization of the basis
345 * matrix B after replacing its j-th column by a new vector.
347 * The parameter j specifies the number of column of B, which has been
348 * replaced, 1 <= j <= m, where m is the order of B.
350 * Row indices and numerical values of non-zero elements of the new
351 * column of B should be placed in locations ind[1], ..., ind[len] and
352 * val[1], ..., val[len], resp., where len is the number of non-zeros
353 * in the column. Neither zero nor duplicate elements are allowed.
357 * 0 The factorization has been successfully updated.
360 * The adjacent basis matrix is structurally singular, since after
361 * changing j-th column of matrix V by the new column (see algorithm
362 * below) the case k1 > k2 occured.
365 * The factorization is inaccurate, since after transforming k2-th
366 * row of matrix U = P*V*Q, its diagonal element u[k2,k2] is zero or
370 * Maximal number of H factors has been reached.
373 * Overflow of the sparse vector area.
375 * In case of non-zero return code the factorization becomes invalid.
376 * It should not be used until it has been recomputed with the routine
381 * The routine fhv_update_it is based on the transformation proposed by
382 * Forrest and Tomlin.
384 * Let j-th column of the basis matrix B have been replaced by new
385 * column B[j]. In order to keep the equality B = F*H*V j-th column of
386 * matrix V should be replaced by the column inv(F*H)*B[j].
388 * From the standpoint of matrix U = P*V*Q, replacement of j-th column
389 * of matrix V is equivalent to replacement of k1-th column of matrix U,
390 * where k1 is determined by permutation matrix Q. Thus, matrix U loses
391 * its upper triangular form and becomes the following:
394 * 1 x x * x x x x x x x
395 * . x * x x x x x x x
396 * k1 . . * x x x x x x x
397 * . . * x x x x x x x
398 * . . * . x x x x x x
399 * . . * . . x x x x x
400 * . . * . . . x x x x
401 * k2 . . * . . . . x x x
402 * . . . . . . . . x x
403 * m . . . . . . . . . x
405 * where row index k2 corresponds to the lowest non-zero element of
408 * The routine moves rows and columns k1+1, k1+2, ..., k2 of matrix U
409 * by one position to the left and upwards and moves k1-th row and k1-th
410 * column to position k2. As the result of such symmetric permutations
411 * matrix U becomes the following:
414 * 1 x x x x x x x * x x
415 * . x x x x x x * x x
416 * k1 . . x x x x x * x x
417 * . . . x x x x * x x
418 * . . . . x x x * x x
419 * . . . . . x x * x x
420 * . . . . . . x * x x
421 * k2 . . x x x x x * x x
422 * . . . . . . . . x x
423 * m . . . . . . . . . x
425 * Then the routine performs gaussian elimination to eliminate elements
426 * u[k2,k1], u[k2,k1+1], ..., u[k2,k2-1] using diagonal elements
427 * u[k1,k1], u[k1+1,k1+1], ..., u[k2-1,k2-1] as pivots in the same way
428 * as described in comments to the routine luf_factorize (see the module
429 * GLPLUF). Note that actually all operations are performed on matrix V,
430 * not on matrix U. During the elimination process the routine permutes
431 * neither rows nor columns, so only k2-th row of matrix U is changed.
433 * To keep the main equality B = F*H*V, each time when the routine
434 * applies elementary gaussian transformation to the transformed row of
435 * matrix V (which corresponds to k2-th row of matrix U), it also adds
436 * a new element (gaussian multiplier) to the current row-like factor
437 * of matrix H, which corresponds to the transformed row of matrix V. */
439 int fhv_update_it(FHV *fhv, int j, int len, const int ind[],
443 int *vr_ptr = luf->vr_ptr;
444 int *vr_len = luf->vr_len;
445 int *vr_cap = luf->vr_cap;
446 double *vr_piv = luf->vr_piv;
447 int *vc_ptr = luf->vc_ptr;
448 int *vc_len = luf->vc_len;
449 int *vc_cap = luf->vc_cap;
450 int *pp_row = luf->pp_row;
451 int *pp_col = luf->pp_col;
452 int *qq_row = luf->qq_row;
453 int *qq_col = luf->qq_col;
454 int *sv_ind = luf->sv_ind;
455 double *sv_val = luf->sv_val;
456 double *work = luf->work;
457 double eps_tol = luf->eps_tol;
458 int *hh_ind = fhv->hh_ind;
459 int *hh_ptr = fhv->hh_ptr;
460 int *hh_len = fhv->hh_len;
461 int *p0_row = fhv->p0_row;
462 int *p0_col = fhv->p0_col;
463 int *cc_ind = fhv->cc_ind;
464 double *cc_val = fhv->cc_val;
465 double upd_tol = fhv->upd_tol;
466 int i, i_beg, i_end, i_ptr, j_beg, j_end, j_ptr, k, k1, k2, p, q,
467 p_beg, p_end, p_ptr, ptr, ret;
470 xfault("fhv_update_it: the factorization is not valid\n");
471 if (!(1 <= j && j <= m))
472 xfault("fhv_update_it: j = %d; column number out of range\n",
474 /* check if the new factor of matrix H can be created */
475 if (fhv->hh_nfs == fhv->hh_max)
476 { /* maximal number of updates has been reached */
481 /* convert new j-th column of B to dense format */
482 for (i = 1; i <= m; i++)
484 for (k = 1; k <= len; k++)
486 if (!(1 <= i && i <= m))
487 xfault("fhv_update_it: ind[%d] = %d; row number out of rang"
489 if (cc_val[i] != 0.0)
490 xfault("fhv_update_it: ind[%d] = %d; duplicate row index no"
491 "t allowed\n", k, i);
493 xfault("fhv_update_it: val[%d] = %g; zero element not allow"
497 /* new j-th column of V := inv(F * H) * (new B[j]) */
498 fhv->luf->pp_row = p0_row;
499 fhv->luf->pp_col = p0_col;
500 luf_f_solve(fhv->luf, 0, cc_val);
501 fhv->luf->pp_row = pp_row;
502 fhv->luf->pp_col = pp_col;
503 fhv_h_solve(fhv, 0, cc_val);
504 /* convert new j-th column of V to sparse format */
506 for (i = 1; i <= m; i++)
508 if (temp == 0.0 || fabs(temp) < eps_tol) continue;
509 len++, cc_ind[len] = i, cc_val[len] = temp;
511 /* clear old content of j-th column of matrix V */
513 j_end = j_beg + vc_len[j] - 1;
514 for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++)
515 { /* get row index of v[i,j] */
517 /* find v[i,j] in the i-th row */
519 i_end = i_beg + vr_len[i] - 1;
520 for (i_ptr = i_beg; sv_ind[i_ptr] != j; i_ptr++) /* nop */;
521 xassert(i_ptr <= i_end);
522 /* remove v[i,j] from the i-th row */
523 sv_ind[i_ptr] = sv_ind[i_end];
524 sv_val[i_ptr] = sv_val[i_end];
527 /* now j-th column of matrix V is empty */
528 luf->nnz_v -= vc_len[j];
530 /* add new elements of j-th column of matrix V to corresponding
531 row lists; determine indices k1 and k2 */
532 k1 = qq_row[j], k2 = 0;
533 for (ptr = 1; ptr <= len; ptr++)
534 { /* get row index of v[i,j] */
536 /* at least one unused location is needed in i-th row */
537 if (vr_len[i] + 1 > vr_cap[i])
538 { if (luf_enlarge_row(luf, i, vr_len[i] + 10))
539 { /* overflow of the sparse vector area */
541 luf->new_sva = luf->sv_size + luf->sv_size;
542 xassert(luf->new_sva > luf->sv_size);
547 /* add v[i,j] to i-th row */
548 i_ptr = vr_ptr[i] + vr_len[i];
550 sv_val[i_ptr] = cc_val[ptr];
552 /* adjust index k2 */
553 if (k2 < pp_col[i]) k2 = pp_col[i];
555 /* capacity of j-th column (which is currently empty) should be
556 not less than len locations */
558 { if (luf_enlarge_col(luf, j, len))
559 { /* overflow of the sparse vector area */
561 luf->new_sva = luf->sv_size + luf->sv_size;
562 xassert(luf->new_sva > luf->sv_size);
567 /* add new elements of matrix V to j-th column list */
569 memmove(&sv_ind[j_ptr], &cc_ind[1], len * sizeof(int));
570 memmove(&sv_val[j_ptr], &cc_val[1], len * sizeof(double));
573 /* if k1 > k2, diagonal element u[k2,k2] of matrix U is zero and
574 therefore the adjacent basis matrix is structurally singular */
580 /* perform implicit symmetric permutations of rows and columns of
582 i = pp_row[k1], j = qq_col[k1];
583 for (k = k1; k < k2; k++)
584 { pp_row[k] = pp_row[k+1], pp_col[pp_row[k]] = k;
585 qq_col[k] = qq_col[k+1], qq_row[qq_col[k]] = k;
587 pp_row[k2] = i, pp_col[i] = k2;
588 qq_col[k2] = j, qq_row[j] = k2;
589 /* now i-th row of the matrix V is k2-th row of matrix U; since
590 no pivoting is used, only this row will be transformed */
591 /* copy elements of i-th row of matrix V to the working array and
592 remove these elements from matrix V */
593 for (j = 1; j <= m; j++) work[j] = 0.0;
595 i_end = i_beg + vr_len[i] - 1;
596 for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++)
597 { /* get column index of v[i,j] */
599 /* store v[i,j] to the working array */
600 work[j] = sv_val[i_ptr];
601 /* find v[i,j] in the j-th column */
603 j_end = j_beg + vc_len[j] - 1;
604 for (j_ptr = j_beg; sv_ind[j_ptr] != i; j_ptr++) /* nop */;
605 xassert(j_ptr <= j_end);
606 /* remove v[i,j] from the j-th column */
607 sv_ind[j_ptr] = sv_ind[j_end];
608 sv_val[j_ptr] = sv_val[j_end];
611 /* now i-th row of matrix V is empty */
612 luf->nnz_v -= vr_len[i];
614 /* create the next row-like factor of the matrix H; this factor
615 corresponds to i-th (transformed) row */
617 hh_ind[fhv->hh_nfs] = i;
618 /* hh_ptr[] will be set later */
619 hh_len[fhv->hh_nfs] = 0;
620 /* up to (k2 - k1) free locations are needed to add new elements
621 to the non-trivial row of the row-like factor */
622 if (luf->sv_end - luf->sv_beg < k2 - k1)
623 { luf_defrag_sva(luf);
624 if (luf->sv_end - luf->sv_beg < k2 - k1)
625 { /* overflow of the sparse vector area */
626 fhv->valid = luf->valid = 0;
627 luf->new_sva = luf->sv_size + luf->sv_size;
628 xassert(luf->new_sva > luf->sv_size);
633 /* eliminate subdiagonal elements of matrix U */
634 for (k = k1; k < k2; k++)
635 { /* v[p,q] = u[k,k] */
636 p = pp_row[k], q = qq_col[k];
637 /* this is the crucial point, where even tiny non-zeros should
639 if (work[q] == 0.0) continue;
640 /* compute gaussian multiplier f = v[i,q] / v[p,q] */
641 f = work[q] / vr_piv[p];
642 /* perform gaussian transformation:
643 (i-th row) := (i-th row) - f * (p-th row)
644 in order to eliminate v[i,q] = u[k2,k] */
646 p_end = p_beg + vr_len[p] - 1;
647 for (p_ptr = p_beg; p_ptr <= p_end; p_ptr++)
648 work[sv_ind[p_ptr]] -= f * sv_val[p_ptr];
649 /* store new element (gaussian multiplier that corresponds to
650 p-th row) in the current row-like factor */
652 sv_ind[luf->sv_end] = p;
653 sv_val[luf->sv_end] = f;
654 hh_len[fhv->hh_nfs]++;
656 /* set pointer to the current row-like factor of the matrix H
657 (if no elements were added to this factor, it is unity matrix
658 and therefore can be discarded) */
659 if (hh_len[fhv->hh_nfs] == 0)
662 { hh_ptr[fhv->hh_nfs] = luf->sv_end;
663 fhv->nnz_h += hh_len[fhv->hh_nfs];
665 /* store new pivot which corresponds to u[k2,k2] */
666 vr_piv[i] = work[qq_col[k2]];
667 /* new elements of i-th row of matrix V (which are non-diagonal
668 elements u[k2,k2+1], ..., u[k2,m] of matrix U = P*V*Q) now are
669 contained in the working array; add them to matrix V */
671 for (k = k2+1; k <= m; k++)
672 { /* get column index and value of v[i,j] = u[k2,k] */
675 /* if v[i,j] is close to zero, skip it */
676 if (fabs(temp) < eps_tol) continue;
677 /* at least one unused location is needed in j-th column */
678 if (vc_len[j] + 1 > vc_cap[j])
679 { if (luf_enlarge_col(luf, j, vc_len[j] + 10))
680 { /* overflow of the sparse vector area */
682 luf->new_sva = luf->sv_size + luf->sv_size;
683 xassert(luf->new_sva > luf->sv_size);
688 /* add v[i,j] to j-th column */
689 j_ptr = vc_ptr[j] + vc_len[j];
691 sv_val[j_ptr] = temp;
693 /* also store v[i,j] to the auxiliary array */
694 len++, cc_ind[len] = j, cc_val[len] = temp;
696 /* capacity of i-th row (which is currently empty) should be not
697 less than len locations */
699 { if (luf_enlarge_row(luf, i, len))
700 { /* overflow of the sparse vector area */
702 luf->new_sva = luf->sv_size + luf->sv_size;
703 xassert(luf->new_sva > luf->sv_size);
708 /* add new elements to i-th row list */
710 memmove(&sv_ind[i_ptr], &cc_ind[1], len * sizeof(int));
711 memmove(&sv_val[i_ptr], &cc_val[1], len * sizeof(double));
714 /* updating is finished; check that diagonal element u[k2,k2] is
715 not very small in absolute value among other elements in k2-th
716 row and k2-th column of matrix U = P*V*Q */
717 /* temp = max(|u[k2,*]|, |u[*,k2]|) */
719 /* walk through k2-th row of U which is i-th row of V */
722 i_end = i_beg + vr_len[i] - 1;
723 for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++)
724 if (temp < fabs(sv_val[i_ptr])) temp = fabs(sv_val[i_ptr]);
725 /* walk through k2-th column of U which is j-th column of V */
728 j_end = j_beg + vc_len[j] - 1;
729 for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++)
730 if (temp < fabs(sv_val[j_ptr])) temp = fabs(sv_val[j_ptr]);
731 /* check that u[k2,k2] is not very small */
732 if (fabs(vr_piv[i]) < upd_tol * temp)
733 { /* the factorization seems to be inaccurate and therefore must
739 /* the factorization has been successfully updated */
741 done: /* return to the calling program */
745 /***********************************************************************
748 * fhv_delete_it - delete LP basis factorization
752 * #include "glpfhv.h"
753 * void fhv_delete_it(FHV *fhv);
757 * The routine fhv_delete_it deletes LP basis factorization specified
758 * by the parameter fhv and frees all memory allocated to this program
761 void fhv_delete_it(FHV *fhv)
762 { luf_delete_it(fhv->luf);
763 if (fhv->hh_ind != NULL) xfree(fhv->hh_ind);
764 if (fhv->hh_ptr != NULL) xfree(fhv->hh_ptr);
765 if (fhv->hh_len != NULL) xfree(fhv->hh_len);
766 if (fhv->p0_row != NULL) xfree(fhv->p0_row);
767 if (fhv->p0_col != NULL) xfree(fhv->p0_col);
768 if (fhv->cc_ind != NULL) xfree(fhv->cc_ind);
769 if (fhv->cc_val != NULL) xfree(fhv->cc_val);