diff --git a/SOCadmissible.c b/SOCadmissible.c deleted file mode 100644 index 424f94a..0000000 --- a/SOCadmissible.c +++ /dev/null @@ -1,404 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Ämin Baumeler and Eleftherios-Ermis Tselentis -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include -#include -#include - -/*** - * Read graphs from file. - * Input `filename': string - * Input `cnt': pointer to int - * Input `maxdim': pointer to int - * Output: pointer to graph data - * - * This function sets `cnt' to the total number of graphs read from `filename', - * sets `maxdim' to the dimension (number of nodes) of the largest graph, - * and returns the graph data. Graph data is structured as follows: - * {dimension graph 1 | (0,0) | (0,1) | ... | (1,0) | (1,1) | ... | dimension graph 2 | ...} - * The ith graph is at position i*(maxdim*maxdim + 1). - ***/ -int* read_graphs(char* filename, int *cnt, int *maxdim) { - // Open file - FILE *fp; - fp = fopen(filename, "r"); - if(fp == NULL) - return NULL; - // Count number of lines, allocate space and initiate counter - char ch; - int n = 0; - *cnt = 0; // Total number of graphs - *maxdim = 0; // Maximum number of vertices - while(!feof(fp)) { - ch = fgetc(fp); - switch(ch) { - case '\n': - (*cnt)++; - n = 0; - break; - case '{': - case '}': - *maxdim = (n > *maxdim) ? n : *maxdim; - n = 0; - break; - case '0': - case '1': - n++; - break; - case ',': - case ' ': - case 0xffffffff: - break; - default: - return NULL; // Format error - } - } - rewind(fp); // Return to start of file - - // Allocate space for graph data - const int gdatasize = *maxdim * *maxdim + 1; // Size allocation per graph - const int arraysize = (1+ *cnt) * gdatasize; // Total space to allocate - int *graphs = (int*)malloc(sizeof(int)*arraysize); // Allocation - if(!graphs) { - fprintf(stderr, "ERROR: Could not allocate enough memory to store the graphs.\n"); - return NULL; - } - // Parse file - int col = 0; // Column number - int row = 0; // Row number - int i = 0; // Current graph index - n = -1; // Graph dimension - int j = 0; // Running index - while ((ch = fgetc(fp)) != EOF) { - // New line encountered - if(ch == '\n') { - if(row != n) { - fprintf(stderr, "ERROR: File not properly formatted.\n"); - return NULL; - } - graphs[i*gdatasize] = n; - i++; - j = 0; - col = 0; - row = 0; - n = -1; - // Matrix entry encountered - } else if(ch == '0' || ch == '1') { - int x = ch - '0'; - graphs[i*gdatasize + 1 + j] = x; - col++; - j++; - // End-of-row or end-of-matrix encountered - } else if(ch == '}') { - if(n == -1) { - n = col; - } else if(col > 0 && n != col) { - fprintf(stderr, "ERROR: File not properly formatted.\n"); - return NULL; - } - // End of row - if(col != 0) { - row++; - col = 0; - } - } - } - // Close file - fclose(fp); - return graphs; -} - -/*** - * Increase intervention counter by one. - * Returns 0 if we run out of interventions, and 1 otherwise. - ***/ -int nextintervention(int n, int *interventionslen, int *interventionidx) { - for(int i=0; i 0) { - x /= 10; - res++; - } - return res; -} - -/*** - * Verify the admissibility of the graphs - * Go through all graphs and test them - * `startidx': Index from which to start, assumed to be non-negative - * `len': Number of graphs to test, assumed to be non-negative and such that startidx+len does not exceed the length of the `graphs' array - * `maxn': Max. number of nodes - * `graphs': Pointer to graph structure - * - * Return 0 if test succeeds, else return graphidx+1 of failed graph (this is the line number). - * Return -1 on error. - ***/ -int test_graphs(int startidx, int len, int maxn, const int *graphs) { - const int gdatasize = maxn * maxn + 1; // Size allocation per graph - const int idatasize = (maxn+1)*(maxn+1)*2; // Max number of interventions per party - int range[maxn+1]; // Range of intervention - int interventions[maxn*idatasize]; // Hold all interventions per party {f_0(0), f_0(1), g_0(0), g_0(1), ... , f_1(0), f_1(1), ...} - int interventionslen[maxn]; // Number of interventions per party - int interventionidx[maxn]; // Current intervention executed - int parents[maxn*maxn]; // List all parents per party - int parentslen[maxn]; // Number of parents per party - int children[maxn*maxn]; // List all children per party - int childrenlen[maxn]; // Numer of children per party - const int padlen = ceillog10(len); - time_t t0 = time(NULL); - const time_t tstart = t0; - for(int graphidx=startidx; graphidx t0) { - const int count = graphidx - startidx + 1; - const float percentage = 100*(float)count/(float)len; - const int deltat = t1-tstart; - const float rate = (float)count/(float)deltat; - fprintf(stderr, "\r%6.2f%% %*d/%d (%*.2f graphs/s in %d seconds; current line %d)",percentage,padlen,count,len,padlen+3,rate,deltat,graphidx+1); - t0 = t1; - } - // Test graph with index `graphidx' - // `n' is the order of this graph - const int n = graphs[graphidx*gdatasize]; - // Get parents and children - // Adj matrix is such that (row,col) = 1 <=> edge from row to col - for(int i=0; i= 3) - START = atoi(argv[2]); - if(argc >= 4) { - if(argv[3][0] == '+') - NUM = atoi(argv[3]+1); - else - NUM = atoi(argv[3])-START+1; - } - if(!(argc >= 2 && (argc < 3 || START > 0) && (argc < 4 || NUM > 0) && argc <= 4)) { - fprintf(stderr, "Usage: %s [ [ | +]]\n", argv[0]); - fprintf(stderr, " File name with adjacency matrices of simple directed graphs\n"); - fprintf(stderr, " Verify graphs starting from line `startline'\n"); - fprintf(stderr, " Verify graphs up to and including line `endline'\n"); - fprintf(stderr, " + Verify `count' number of graphs\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "[FILE FORMAT]\n"); - fprintf(stderr, " Each line in `filename' must contain the adjacency matrix of a simple directed graph in the format\n"); - fprintf(stderr, " {{a00,a01,...},{a10,a11,...},...} where aij=1 if and only if the graph has the edge i -> j\n"); - fprintf(stderr, " The file `filename' may contain graphs with different order (number of vertices)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "This program verifies the admissibility of simple directed graphs.\n"); - return -1; - } - - // Read Graphs from File - int graphcount = 0; - int maxdimension = -1; - const int *graphs = read_graphs(argv[1], &graphcount, &maxdimension); - if(graphs == NULL) { - fprintf(stderr, "ERROR: Could not read graphs from file `%s'.\n", argv[1]); - return -1; - } - const int startidx = START ? START-1 : 0; // Index of graph to start verifying - const int tot = NUM ? NUM : graphcount-startidx; // Number of graphs to be verified - if(startidx >= graphcount || tot <= 0 || tot+startidx-1 >= graphcount) { - fprintf(stderr, "ERROR: Lines to be verified are out of range\n"); - return -1; - } - - // Test `tot' graphs, starting from index `startidx' - printf("Verifying the admissibility of %d graphs in the file `%s' (line %d to line %d)\n", tot, argv[1], startidx+1, startidx+tot); - const int result = test_graphs(startidx, tot, maxdimension, graphs); - if (result == 0) - printf("These graphs are admissible\n"); - else if(result == -1) - fprintf(stderr, "ERROR: Something went wrong\n"); - else - printf("The function alpha does not represent the fixed point, or the graph on line %d is inadmissible\n", result); - return result; -} diff --git a/SOCgen.c b/SOCgen.c deleted file mode 100644 index 6e53bcc..0000000 --- a/SOCgen.c +++ /dev/null @@ -1,519 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Ämin Baumeler and Eleftherios-Ermis Tselentis -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include -#include -#include -#include - -/*** - * Print the graph's adjacency matrix - ***/ -void dumpgraph(int n, const int *children, const int *childrenlen) { - int adj[n*n]; - for(int i=0; i path[k]) { - smallest = path[k]; - smallestidx = k; - } - } - // Now, copy cycle to `cycle' starting from the smallest - int j=0; // This is the index on where to write on the array `cycle' - for(int i=smallestidx;; i++) { - if(j==*cyclelen) break; // Stop filling in, if we reached the end - if(i==pathlen-1) i = startidx; // If we reach the end of the path, jump to the start - cycle[j] = path[i]; // Write at position `j' the element from the cycle on the path at position `i`' - j++; // Increase index to write on `cycle' - } -} - -/*** - * Return 1 if the cycle is not in `cycles', otherwise 0. - ***/ -int cycleisnew(int n, const int *c, int clen, const int *cycles, const int *cyclescnt) { - const int cnt = cyclescnt[clen]; - const int bs = blocksize(n); - for(int i=0; i parentslen[i+1]) { - return 0; - } else if(parentslen[i] == parentslen[i+1]) { - if(childrenlen[i] > childrenlen[i+1]) { - return 0; - } else if(childrenlen[i] == childrenlen[i+1]) { - if(grandparentslen(i,parents,parentslen) > grandparentslen(i+1,parents,parentslen)) { - return 0; - } else if(grandparentslen(i,parents,parentslen) == grandparentslen(i+1,parents,parentslen)) { - if(grandchildrenlen(i,children,childrenlen) > grandchildrenlen(i+1,children,childrenlen)) { - return 0; - } - } - } - } - } - return 1; -} - -/* Random nubers */ -#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF -#define LOOP_COUNT 1 -#elif RAND_MAX/256 >= 0xFFFFFF -#define LOOP_COUNT 2 -#elif RAND_MAX/256 >= 0x3FFFF -#define LOOP_COUNT 3 -#elif RAND_MAX/256 >= 0x1FF -#define LOOP_COUNT 4 -#else -#define LOOP_COUNT 5 -#endif - -u_int64_t rand_uint64(unsigned long long max) { - u_int64_t r = 0; - for (int i=LOOP_COUNT; i > 0; i--) { - r = r*(RAND_MAX + (u_int64_t)1) + rand(); - } - return r%max; -} -/* End of random numbers */ - -int main(int argc, char *argv[]) { - // Parse command-line arguments - int n = -1; - int NONDAGONLY = 0; - int NOSINK = 0; - int NOSOURCE = 0; - int RANDOM = 0; - int UNKOPTION = 0; - for(int i=1; i [-r ] [FILTER ...]\n", argv[0]); - fprintf(stderr, " -n Generate SOCs with `order' connected nodes\n"); - fprintf(stderr, " -r Pick directed graphs at random, and exit after having found `num' SOCs\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "[FILTER] Consider only simple directed graphs ...\n"); - fprintf(stderr, " -c ... that are cyclic (i.e., not DAGs)\n"); - fprintf(stderr, " --no-sink ... without sink nodes (this logically implies -c)\n"); - fprintf(stderr, " --no-source ... without source nodes (also this logically implies -c)\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "This program prints the found SOCs as adjacency matrices to stdout.\n"); - fprintf(stderr, "To exclude (some) of the isomorphic SOCs, it uses a degree-order filter.\n"); - return -1; - } - // EO Parse command-line arguments - // Setup datastructures - int parents[n*n]; // Each node i can have at most n-1 parents. These are listed at parents[n*i+k] for 0<=k64) { - fprintf(stderr, "Too many graphs to enumarate with an unsiged long long integer (number of node pairs = %d)\n", m); - return -1; - } - const unsigned long long max = 1L << m; // Largest `graphnumber' - const int padlen = (int)((float)m/3.322)+1; // Convert log 2 to log 10 - int len = 0; - time_t t0 = time(NULL); - time_t t = time(NULL); - srand((unsigned) time(&t)); - // EO Initiate graph enumeration - fprintf(stderr, "Generating SOCs with %d nodes\n", n); - if(RANDOM) fprintf(stderr, " Picking graphs at random\n"); - if(NONDAGONLY) fprintf(stderr, " Filter: Omitting DAGs\n"); - if(NOSINK) fprintf(stderr, " Filter: Omitting graphs with sink nodes\n"); - if(NOSOURCE) fprintf(stderr, " Filter: Omitting graphs with source nodes\n"); - unsigned long long graphnumber = 0; // We will always omit the graph with `graphnumber' 0; it is unintersting anyway - unsigned long long graphschecked = 0; - for(;graphnumber < max && (!RANDOM || len < RANDOM);) { - const time_t now = time(NULL); - // Break if we exhaustively check all graphs or if we found enough SOCs at random - //if(graphnumber >= max || (RANDOM && len >= RANDOM)) - // break; - // Print status every second - if(now > t) { - t = now; - const int deltat = now - t0; - const float rate = (float)graphschecked/(float)deltat; - const float SOCrate = (float)len/(float)deltat; - const float percentage = (RANDOM==0) ? 100*(float)graphnumber/(float)max : 100*(float)len/(float)RANDOM; - const float ETC = (RANDOM==0) ? ((float)(max - graphschecked)/(rate))/3600 : ((float)(RANDOM - len)/(SOCrate))/3600; - fprintf(stderr, "\r%6.2f%% %*llu/%llu (%i SOCs found, %d seconds, %*.2f graphs/s, %*.2f SOCs/s, %*.2fh estimated time left)",percentage,padlen,graphnumber,max,len,deltat,padlen+3,rate,padlen+3,SOCrate,padlen,ETC); - fflush(stderr); - } - // Convert graph index `grpahnumber' to the lists parents, children, parentslen, childrenlen - graphnrtolists(n, graphnumber, parents, parentslen, children, childrenlen); - // Increase checked counter and prepare for next iteration - graphschecked++; - if(RANDOM) - graphnumber = rand_uint64(max); - else - graphnumber++; - // EO Increase checked counter and prepare for next iteration - // If enabled, compare against degree options - if(NOSINK || NOSOURCE) { - // Get some degree properties - int minindegree = n; - int minoutdegree = n; - for(int node=0; node parentslen[node]) - minindegree = parentslen[node]; - if(minoutdegree > childrenlen[node]) - minoutdegree = childrenlen[node]; - } - if(NOSINK && minoutdegree == 0) continue; - if(NOSOURCE && minindegree == 0) continue; - } - // Check whether this graph is canonical or not; continue if graph has not proper ordering of degress (there is an isomorphic graphs to this one that has been or will be checked) - if(!isdegreeordered(n, parents, parentslen, children, childrenlen)) continue; - // Ignore graphs that are not connected - if(!isconnected(n, parents, parentslen, children, childrenlen)) continue; - // Find cycles - const int num_cycles = find_cycles(cycles, cyclescnt, n, children, childrenlen); - // If enabled, ignore DAGs - if(NONDAGONLY && num_cycles > 0) continue; - // Test the Siblings-On-Cycles property - // A DAG is trivially a SOC - if(num_cycles > 0 && !gissoc(n, parents, parentslen, children, childrenlen, cycles, cyclescnt)) continue; - // We have found a SOC - len++; - dumpgraph(n, children, childrenlen); - } - const int deltat = time(NULL) - t0; - const float rate = (deltat == 0) ? graphschecked : (float)graphschecked/(float)deltat; - const float SOCrate = (deltat == 0) ? len : (float)len/(float)deltat; - fprintf(stderr, "\r%6.2f%% %*llu/%llu (%i SOCs found, %d seconds, %*.2f graphs/s, %*.2f SOCs/s, %*.2fh estimated time left)",100.00,padlen,graphnumber,max,len,deltat,padlen+3,rate,padlen+3,SOCrate,padlen,0.00); - fprintf(stderr, "\nFound %d SOCs in %d seconds\n", len,deltat); - // Free manually allocated memory - free(cycles); - return 0; -}