0

I'm trying to generate combinations of M integers from a set of M^2 consecutive integers, then exclude some combinations based on some (currently irrelevant) criteria, and trying to store them dynamically in memory so that I may be able to access them later.

The combinations are being generated using the 'gsl_combination' structure in the GNU Scientific Library (docs here). As you can see from the code snippet below, the combinations are being generated okay (and exclusions are as desired).

Then I need to append each combination structure object to memory for later retrieval. I'm trying to use glib pointer arrays to do this.

Code: gptrwierd.c

#include <glib.h>
#include <gsl/gsl_combination.h>

//Hardcoded the size of the rigol lattice  
//MUST BE ODD !!!
#define M 3

//Returns GSL_SUCCESS if the combination contains a forbidden site, otherwise returns GSL_FAILURE  
int
is_forbidden (const gsl_combination * test)
{
  int i, forbidden = GSL_FAILURE;   //Not forbidden by default
  size_t k = test->k;
  size_t *data = test->data;
  int halfway = ((M * M - 1) / 2);  //The halfway point in the 2D grid

      ...
      ... //Some code for updating 'forbidden'
      ...
  return forbidden;
}


#undef __FUNCT__
#define __FUNCT__ "main"
int
main (int argc, char **argv)
{
  long count, istride;
  //Generate the basis states
  gsl_combination *c = gsl_combination_calloc (M * M, M);
  //An array that will contain selected basis vectors.
  GPtrArray *basis = g_ptr_array_new ();
  count = 0;
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append c to basis
      g_ptr_array_add (basis, c);   //Appends c to basis
      {
        printf ("count %ld {", count);
        gsl_combination_fprintf (stdout,
                    g_ptr_array_index (basis, count), " %u");
        printf (" }\n");
      }
      count++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);
  printf("\n\n");
  //Now, access each basis element from GArray
  for (istride = 0; istride < basis->len; istride++)
    {
      printf ("istride %ld {", istride);
      gsl_combination_fprintf (stdout, g_ptr_array_index (basis, istride),
                  " %u");
      printf (" }\n");

    }

  gsl_combination_free (c);
  g_ptr_array_free (basis, TRUE);
  return 0;
}

Makefile:

            GSL_FLAGS  = gsl-config --cflags
            GLIB_LOC = pkg-config --cflags --libs glib-2.0
            CFLAGS     = -Wall -O3 `$(GSL_FLAGS)` `$(GLIB_LOC)`

            GSL_LIBS   = gsl-config  --libs-without-cblas 
            GLIB_LIBS = pkg-config --libs glib-2.0



            gptrwierd:
                gcc $(CFLAGS) -c gptrwierd.c 
                gcc -o $@ gptrwierd.o -lgsl -lgslcblas -lm `$(GLIB_LIBS)`

            allclean: clean
                ${RM} gptrwierd *.dat

Compilation and running is done thus (M is hardcoded to 3):

$make gptrwierd
 gcc -Wall -O3 `gsl-config --cflags` `pkg-config --cflags --libs glib-2.0` -c gptrwierd.c 
 gcc -o gptrwierd gptrwierd.o -lgsl -lgslcblas -lm `pkg-config --libs glib-2.0`
 $./gptrwierd > out.dat

contents of output file are pasted below:

count 0 { 1 2 3 }
count 1 { 1 2 4 }
count 2 { 1 2 6 }
count 3 { 1 2 7 }
count 4 { 1 2 8 }
count 5 { 1 3 4 }
count 6 { 1 3 6 }
count 7 { 1 3 7 }
count 8 { 1 3 8 }
count 9 { 1 4 6 }
count 10 { 1 4 7 }
count 11 { 1 4 8 }
count 12 { 1 6 7 }
count 13 { 1 6 8 }

...
...

count 28 { 3 6 7 }
count 29 { 3 6 8 }
count 30 { 3 7 8 }
count 31 { 4 6 7 }
count 32 { 4 6 8 }
count 33 { 4 7 8 }
count 34 { 6 7 8 }

istride 0 { 6 7 8 }
istride 1 { 6 7 8 }
istride 2 { 6 7 8 }
istride 3 { 6 7 8 }
istride 4 { 6 7 8 }
istride 5 { 6 7 8 }
istride 6 { 6 7 8 }
istride 7 { 6 7 8 }
istride 8 { 6 7 8 }
istride 9 { 6 7 8 }
istride 10 { 6 7 8 }
istride 11 { 6 7 8 }
istride 12 { 6 7 8 }

...
...

istride 30 { 6 7 8 }
istride 31 { 6 7 8 }
istride 32 { 6 7 8 }
istride 33 { 6 7 8 }
istride 34 { 6 7 8 }

As you can see, it prints the combinations correctly in the do...while loop where the combinations are iterated, but only prints the lexicographically final combination when the gptrarray elements are iterated in the subsequent loop.

What am I doing wrong?

Update: One possible workaround seems to be to do away with glib altogether and manually copy the combination data to a dynamically allocated array:

  gsl_combination *c = gsl_combination_calloc (M * M, M);
  long **basis;
  long dim = 0;
  //Evaluate the dimensionality of the Hilbert space (# of allowed combinations)
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append dim
      dim++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);


  //Now, generate the actual basis
  //basis is an array of arrays that will contain the 
  //selected basis vectors. Each basis vector is an array of M integers
  basis = (long **) malloc (dim * sizeof (long *));
  for (count = 0; count < dim; count++)
    basis[count] = (long *) malloc (M * sizeof (long));

  //Reset the combination to the one that is lexicographically first
  gsl_combination_init_first (c);
  count = 0;
  //Now, append all allowed combinations to the basis
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append data in c to basis
      for (istride = 0; istride < M; istride++)
        basis[count][istride] = c->data[istride];
      count++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);

  //Now, access each basis element from GArray
  //basis[i] is the ith combination. jth combination element is basis[i][j]
  printf (
  "Printing all allowed combinations of sites in basis\n"
  "---------------------------------------------------\n");


  for (istride = 0; istride < dim; istride++)
     {
       printf ("stride # %3ld:\t{", istride);
       for (count = 0; count < M; count++)
         printf (" %ld", basis[istride][count]);
   printf (" }\n");
  }
/*Do whatever*/
...
...
free(basis);
4

1 回答 1

0

反例,它有效!所以它证明它与 无关GPtrArray,但 g_ptr_array_add (basis, c); //Appends c to basis你总是将最新的添加到你的 ptr 数组中(但总是指向同一个对象)。因此,您对其进行修改,以反映下一个要添加的内容,并在同一步骤中更改最后添加的内容。

pkg-config --modversion glib-2.0
2.37.7

使用的演示代码:

#include <glib.h>
#include <glib/gprintf.h>

int main()
{
GPtrArray *a = g_ptr_array_new ();
gpointer data = a;
int i;

for (i=0; i<10; i++, data++)
{
    g_ptr_array_add (a, data);
    if (i>0)
        g_printf ("[%i] last: %p \n", i, g_ptr_array_index (a, i-1));
    g_printf ("[%i] current: %p \n", i, g_ptr_array_index (a, i));
}

g_printf ("---- cut ----\n");


for (i=0; i<10; i++, data++)
{
    g_printf ("[%i] recheck: %p \n", i, g_ptr_array_index (a, i));
}

g_ptr_array_unref (a);
return 0;
}

输出:

[0] current: 0x1c1ae00 
[1] last: 0x1c1ae00 
[1] current: 0x1c1ae01 
[2] last: 0x1c1ae01 
[2] current: 0x1c1ae02 
[3] last: 0x1c1ae02 
[3] current: 0x1c1ae03 
[4] last: 0x1c1ae03 
[4] current: 0x1c1ae04 
[5] last: 0x1c1ae04 
[5] current: 0x1c1ae05 
[6] last: 0x1c1ae05 
[6] current: 0x1c1ae06 
[7] last: 0x1c1ae06 
[7] current: 0x1c1ae07 
[8] last: 0x1c1ae07 
[8] current: 0x1c1ae08 
[9] last: 0x1c1ae08 
[9] current: 0x1c1ae09 
---- cut ----
[0] recheck: 0x1c1ae00 
[1] recheck: 0x1c1ae01 
[2] recheck: 0x1c1ae02 
[3] recheck: 0x1c1ae03 
[4] recheck: 0x1c1ae04 
[5] recheck: 0x1c1ae05 
[6] recheck: 0x1c1ae06 
[7] recheck: 0x1c1ae07 
[8] recheck: 0x1c1ae08 
[9] recheck: 0x1c1ae09
于 2013-08-27T07:49:16.720 回答