Add graph references

This commit is contained in:
Abdelrahman Said
2026-06-28 13:49:01 +01:00
parent 0a9807e448
commit a11edf0c53
2578 changed files with 868045 additions and 0 deletions
+243
View File
@@ -0,0 +1,243 @@
/*
igraph library.
Copyright (C) 2011-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge MA, 02139 USA
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <pthread.h>
#include <string.h>
#include "linalg/arpack_internal.h"
#include "test_utilities.h"
/* Test whether ARPACK is thread-safe. We will create two threads,
each calling a different ARPACK eigensolver. We will make sure that
the ARPACK calls from the two threads overlap */
typedef struct thread_data_t {
igraph_matrix_t *m;
igraph_vector_t *result;
pthread_cond_t *cond;
pthread_mutex_t *mutex;
int *steps, *othersteps;
} thread_data_t;
int arpack_mult(igraph_real_t *to, igraph_real_t *from,
igraph_matrix_t *matrix) {
/* TODO */
igraph_blas_dgemv_array(/*transpose=*/ 0, /*alpha=*/ 1.0, matrix,
from, /*beta=*/ 0.0, to);
return 0;
}
/* This is the function performed by each thread. It calls the
low-level ARPACK symmetric eigensolver, step by step. After each
step, it synchronizes with the other thread.
The synchronization ensures that the two threads are using the
thread-local variables at the same time. If they are really
thread-local, then ARPACK still delivers the correct solution for
the two matrices. Otherwise the result is undefined: maybe results
will be incorrect, or the program will crash.
This function is basically a simplified copy of igraph_arpack_rssolve.
*/
void *thread_function(void *arg) {
thread_data_t *data = (thread_data_t*) arg;
igraph_matrix_t *M = data->m;
igraph_vector_t *result = data->result;
pthread_cond_t *cond = data->cond;
pthread_mutex_t *mutex = data->mutex;
igraph_arpack_options_t options;
igraph_real_t *v, *workl, *workd, *d, *resid, *ax;
int *select;
int ido = 0;
#if IGRAPH_THREAD_SAFE
int rvec = 1;
char *all = "All";
#endif
int i;
igraph_arpack_options_init(&options);
options.n = igraph_matrix_nrow(M);
options.ldv = options.n;
options.nev = 1;
options.ncv = 3;
options.lworkl = options.ncv * (options.ncv + 8);
options.which[0] = 'L';
options.which[1] = 'M';
options.iparam[0] = options.ishift;
options.iparam[2] = options.mxiter;
options.iparam[3] = options.nb;
options.iparam[4] = 0;
options.iparam[6] = options.mode;
options.info = options.start;
v = IGRAPH_CALLOC(options.ldv * options.ncv, igraph_real_t);
workl = IGRAPH_CALLOC(options.lworkl, igraph_real_t);
workd = IGRAPH_CALLOC(3 * options.n, igraph_real_t);
d = IGRAPH_CALLOC(2 * options.ncv, igraph_real_t);
resid = IGRAPH_CALLOC(options.n, igraph_real_t);
ax = IGRAPH_CALLOC(options.n, igraph_real_t);
select = IGRAPH_CALLOC(options.ncv, int);
if (!v || !workl || !workd || !d || !resid || !ax || !select) {
printf("Out of memory\n");
return 0;
}
while (1) {
#if IGRAPH_THREAD_SAFE
igraphdsaupd_(&ido, options.bmat, &options.n, options.which,
&options.nev, &options.tol, resid, &options.ncv, v,
&options.ldv, options.iparam, options.ipntr, workd,
workl, &options.lworkl, &options.info);
#endif
if (ido == -1 || ido == 1) {
igraph_real_t *from = workd + options.ipntr[0] - 1;
igraph_real_t *to = workd + options.ipntr[1] - 1;
arpack_mult(to, from, M);
} else {
break;
}
pthread_mutex_lock(mutex);
*(data->steps) += 1;
if ( *(data->othersteps) == *(data->steps) ) {
pthread_cond_signal(cond);
}
while ( *(data->othersteps) < * (data->steps) && *(data->othersteps) != -1 ) {
pthread_cond_wait(cond, mutex);
}
pthread_mutex_unlock(mutex);
}
pthread_mutex_lock(mutex);
*data->steps = -1;
pthread_cond_signal(cond);
pthread_mutex_unlock(mutex);
if (options.info != 0) {
printf("ARPACK error\n");
return 0;
}
#if IGRAPH_THREAD_SAFE
igraphdseupd_(&rvec, all, select, d, v, &options.ldv,
&options.sigma, options.bmat, &options.n,
options.which, &options.nev, &options.tol,
resid, &options.ncv, v, &options.ldv, options.iparam,
options.ipntr, workd, workl, &options.lworkl,
&options.ierr);
#endif
if (options.ierr != 0) {
printf("ARPACK error\n");
return 0;
}
igraph_vector_resize(result, options.n);
for (i = 0; i < options.n; i++) {
VECTOR(*result)[i] = v[i];
}
if (VECTOR(*result)[0] < 0) {
igraph_vector_scale(result, -1.0);
}
free(v);
free(workl);
free(workd);
free(d);
free(resid);
free(ax);
free(select);
return 0;
}
int main(void) {
pthread_t thread_id1, thread_id2;
void *exit_status1, *exit_status2;
igraph_matrix_t m1, m2;
igraph_vector_t result1, result2;
pthread_cond_t steps_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t steps_mutex = PTHREAD_MUTEX_INITIALIZER;
int steps1 = 0, steps2 = 0;
thread_data_t
data1 = { &m1, &result1, &steps_cond, &steps_mutex, &steps1, &steps2 },
data2 = { &m2, &result2, &steps_cond, &steps_mutex, &steps2, &steps1 };
int i, j;
/* Skip if igraph is not thread safe */
if (!IGRAPH_THREAD_SAFE) {
return 77;
}
igraph_matrix_init(&m1, 10, 10);
igraph_matrix_init(&m2, 10, 10);
igraph_vector_init(&result1, igraph_matrix_nrow(&m1));
igraph_vector_init(&result2, igraph_matrix_nrow(&m2));
igraph_rng_seed(igraph_rng_default(), 42);
for (i = 0; i < igraph_matrix_nrow(&m1); i++) {
for (j = 0; j <= i; j++) {
MATRIX(m1, i, j) = MATRIX(m1, j, i) =
igraph_rng_get_integer(igraph_rng_default(), 0, 10);
}
}
for (i = 0; i < igraph_matrix_nrow(&m2); i++) {
for (j = 0; j <= i; j++) {
MATRIX(m2, i, j) = MATRIX(m2, j, i) =
igraph_rng_get_integer(igraph_rng_default(), 0, 10);
}
}
pthread_create(&thread_id1, NULL, thread_function, (void *) &data1);
pthread_create(&thread_id2, NULL, thread_function, (void *) &data2);
pthread_join(thread_id1, &exit_status1);
pthread_join(thread_id2, &exit_status2);
igraph_matrix_print(&m1);
igraph_vector_print(&result1);
printf("---\n");
igraph_matrix_print(&m2);
igraph_vector_print(&result2);
igraph_vector_destroy(&result1);
igraph_vector_destroy(&result2);
igraph_matrix_destroy(&m1);
igraph_matrix_destroy(&m2);
VERIFY_FINALLY_STACK();
return 0;
}