⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glpnet01.c

📁 著名的大规模线性规划求解器源码GLPK.C语言版本,可以修剪.内有详细帮助文档.
💻 C
字号:
/* glpnet01.c (permutations for zero-free diagonal) *//************************************************************************  This code is part of GLPK (GNU Linear Programming Kit).**  This code is the result of translation of the Fortran subroutines*  MC21A and MC21B associated with the following paper:**  I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM*  Trans. on Math. Softw. 7 (1981), 387-390.**  Use of ACM Algorithms is subject to the ACM Software Copyright and*  License Agreement. See <http://www.acm.org/publications/policies>.**  The translation was made by Andrew Makhorin <mao@mai2.rcnet.ru>.**  GLPK is free software: you can redistribute it and/or modify it*  under the terms of the GNU General Public License as published by*  the Free Software Foundation, either version 3 of the License, or*  (at your option) any later version.**  GLPK is distributed in the hope that it will be useful, but WITHOUT*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public*  License for more details.**  You should have received a copy of the GNU General Public License*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.***********************************************************************/#include "glpnet.h"/************************************************************************  NAME**  mc21a - permutations for zero-free diagonal**  SYNOPSIS**  #include "glpnet.h"*  int mc21a(int n, const int icn[], const int ip[], const int lenr[],*     int iperm[], int pr[], int arp[], int cv[], int out[]);**  DESCRIPTION**  Given the pattern of nonzeros of a sparse matrix, the routine mc21a*  attempts to find a permutation of its rows that makes the matrix have*  no zeros on its diagonal.**  INPUT PARAMETERS**  n     order of matrix.**  icn   array containing the column indices of the non-zeros. Those*        belonging to a single row must be contiguous but the ordering*        of column indices within each row is unimportant and wasted*        space between rows is permitted.**  ip    ip[i], i = 1,2,...,n, is the position in array icn of the*        first column index of a non-zero in row i.**  lenr  lenr[i], i = 1,2,...,n, is the number of non-zeros in row i.**  OUTPUT PARAMETER**  iperm contains permutation to make diagonal have the smallest*        number of zeros on it. Elements (iperm[i], i), i = 1,2,...,n,*        are non-zero at the end of the algorithm unless the matrix is*        structurally singular. In this case, (iperm[i], i) will be*        zero for n - numnz entries.**  WORKING ARRAYS**  pr    working array of length [1+n], where pr[0] is not used.*        pr[i] is the previous row to i in the depth first search.**  arp   working array of length [1+n], where arp[0] is not used.*        arp[i] is one less than the number of non-zeros in row i which*        have not been scanned when looking for a cheap assignment.**  cv    working array of length [1+n], where cv[0] is not used.*        cv[i] is the most recent row extension at which column i was*        visited.**  out   working array of length [1+n], where out[0] is not used.*        out[i] is one less than the number of non-zeros in row i*        which have not been scanned during one pass through the main*        loop.**  RETURNS**  The routine mc21a returns numnz, the number of non-zeros on diagonal*  of permuted matrix. */int mc21a(int n, const int icn[], const int ip[], const int lenr[],      int iperm[], int pr[], int arp[], int cv[], int out[]){     int i, ii, in1, in2, j, j1, jord, k, kk, numnz;      /* Initialization of arrays. */      for (i = 1; i <= n; i++)      {  arp[i] = lenr[i] - 1;         cv[i] = iperm[i] = 0;      }      numnz = 0;      /* Main loop. */      /* Each pass round this loop either results in a new assignment         or gives a row with no assignment. */      for (jord = 1; jord <= n; jord++)      {  j = jord;         pr[j] = -1;         for (k = 1; k <= jord; k++)         {  /* Look for a cheap assignment. */            in1 = arp[j];            if (in1 >= 0)            {  in2 = ip[j] + lenr[j] - 1;               in1 = in2 - in1;               for (ii = in1; ii <= in2; ii++)               {  i = icn[ii];                  if (iperm[i] == 0) goto L110;               }               /* No cheap assignment in row. */               arp[j] = -1;            }            /* Begin looking for assignment chain starting with row j.*/            out[j] = lenr[j] - 1;            /* Inner loop. Extends chain by one or backtracks. */            for (kk = 1; kk <= jord; kk++)            {  in1 = out[j];               if (in1 >= 0)               {  in2 = ip[j] + lenr[j] - 1;                  in1 = in2 - in1;                  /* Forward scan. */                  for (ii = in1; ii <= in2; ii++)                  {  i = icn[ii];                     if (cv[i] != jord)                     {  /* Column i has not yet been accessed during                           this pass. */                        j1 = j;                        j = iperm[i];                        cv[i] = jord;                        pr[j] = j1;                        out[j1] = in2 - ii - 1;                        goto L100;                     }                  }               }               /* Backtracking step. */               j = pr[j];               if (j == -1) goto L130;            }L100:       ;         }L110:    /* New assignment is made. */         iperm[i] = j;         arp[j] = in2 - ii - 1;         numnz++;         for (k = 1; k <= jord; k++)         {  j = pr[j];            if (j == -1) break;            ii = ip[j] + lenr[j] - out[j] - 2;            i = icn[ii];            iperm[i] = j;         }L130:    ;      }      /* If matrix is structurally singular, we now complete the         permutation iperm. */      if (numnz < n)      {  for (i = 1; i <= n; i++)            arp[i] = 0;         k = 0;         for (i = 1; i <= n; i++)         {  if (iperm[i] == 0)               out[++k] = i;            else               arp[iperm[i]] = i;         }         k = 0;         for (i = 1; i <= n; i++)         {  if (arp[i] == 0)               iperm[out[++k]] = i;         }      }      return numnz;}/**********************************************************************/#if 0#include "glplib.h"int sing;void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum,      int iw[]);void fa01bs(int max, int *nrand);int main(void){     /* test program for the routine mc21a */      /* these runs on random matrices cause all possible statements in         mc21a to be executed */      int i, iold, j, j1, j2, jj, knum, l, licn, n, nov4, num, numnz;      int ip[1+21], icn[1+1000], iperm[1+20], lenr[1+20], iw1[1+80];      licn = 1000;      /* run on random matrices of orders 1 through 20 */      for (n = 1; n <= 20; n++)      {  nov4 = n / 4;         if (nov4 < 1) nov4 = 1;L10:     fa01bs(nov4, &l);         knum = l * n;         /* knum is requested number of non-zeros in random matrix */         if (knum > licn) goto L10;         /* if sing is false, matrix is guaranteed structurally            non-singular */         sing = ((n / 2) * 2 == n);         /* call to subroutine to generate random matrix */         ranmat(n, n, icn, ip, n+1, &knum, iw1);         /* knum is now actual number of non-zeros in random matrix */         if (knum > licn) goto L10;         xprintf("n = %2d; nz = %4d; sing = %d\n", n, knum, sing);         /* set up array of row lengths */         for (i = 1; i <= n; i++)            lenr[i] = ip[i+1] - ip[i];         /* call to mc21a */         numnz = mc21a(n, icn, ip, lenr, iperm, &iw1[0], &iw1[n],            &iw1[n+n], &iw1[n+n+n]);         /* testing to see if there are numnz non-zeros on the diagonal            of the permuted matrix. */         num = 0;         for (i = 1; i <= n; i++)         {  iold = iperm[i];            j1 = ip[iold];            j2 = j1 + lenr[iold] - 1;            if (j2 < j1) continue;            for (jj = j1; jj <= j2; jj++)            {  j = icn[jj];               if (j == i)               {  num++;                  break;               }            }         }         if (num != numnz)            xprintf("Failure in mc21a, numnz = %d instead of %d\n",               numnz, num);      }      return 0;}void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum,      int iw[]){     /* subroutine to generate random matrix */      int i, ii, inum, j, lrow, matnum;      inum = (*knum / n) * 2;      if (inum > n-1) inum = n-1;      matnum = 1;      /* each pass through this loop generates a row of the matrix */      for (j = 1; j <= m; j++)      {  iptr[j] = matnum;         if (!(sing || j > n))            icn[matnum++] = j;         if (n == 1) continue;         for (i = 1; i <= n; i++) iw[i] = 0;         if (!sing) iw[j] = 1;         fa01bs(inum, &lrow);         lrow--;         if (lrow == 0) continue;         /* lrow off-diagonal non-zeros in row j of the matrix */         for (ii = 1; ii <= lrow; ii++)         {  for (;;)            {  fa01bs(n, &i);               if (iw[i] != 1) break;            }            iw[i] = 1;            icn[matnum++] = i;         }      }      for (i = m+1; i <= nnnp1; i++)         iptr[i] = matnum;      *knum = matnum - 1;      return;}double g = 1431655765.0;double fa01as(int i){     /* random number generator */      g = fmod(g * 9228907.0, 4294967296.0);      if (i >= 0)         return g / 4294967296.0;      else         return 2.0 * g / 4294967296.0 - 1.0;}void fa01bs(int max, int *nrand){     *nrand = (int)(fa01as(1) * (double)max) + 1;      return;}#endif/* eof */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -