123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Details at https://graphviz.org
- *************************************************************************/
- #include "config.h"
- #include <cgraph/list.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <math.h>
- #include <time.h>
- #include <graph_generator.h>
- #include <util/alloc.h>
- #include <util/exit.h>
- void makePath(unsigned n, edgefn ef){
- if (n == 1) {
- ef (1, 0);
- return;
- }
- for (unsigned i = 2; i <= n; i++)
- ef (i - 1, i);
- }
- void makeComplete(unsigned n, edgefn ef) {
- if (n == 1) {
- ef (1, 0);
- return;
- }
- for (unsigned i = 1; i < n; i++) {
- for (unsigned j = i + 1; j <= n; j++) {
- ef ( i, j);
- }
- }
- }
- void makeCircle(unsigned n, edgefn ef) {
- if (n < 3) {
- fprintf(stderr, "Warning: degenerate circle of %u vertices\n", n);
- makePath(n, ef);
- return;
- }
- for (unsigned i = 1; i < n; i++)
- ef ( i, i + 1);
- ef (1, n);
- }
- void makeStar(unsigned n, edgefn ef) {
- if (n < 3) {
- fprintf(stderr, "Warning: degenerate star of %u vertices\n", n);
- makePath(n, ef);
- return;
- }
- for (unsigned i = 2; i <= n; i++)
- ef (1, i);
- }
- void makeWheel(unsigned n, edgefn ef) {
- if (n < 4) {
- fprintf(stderr, "Warning: degenerate wheel of %u vertices\n", n);
- makeComplete(n, ef);
- return;
- }
- makeStar(n, ef);
- for (unsigned i = 2; i < n; i++)
- ef( i, i + 1);
- ef (2, n);
- }
- void makeCompleteB(unsigned dim1, unsigned dim2, edgefn ef) {
- for (unsigned i = 1; i <= dim1; i++) {
- for (unsigned j = 1; j <= dim2; j++) {
- ef ( i, dim1 + j);
- }
- }
- }
- void makeTorus(unsigned dim1, unsigned dim2, edgefn ef) {
- for (unsigned i = 1, n = 0; i <= dim1; i++) {
- for (unsigned j = 1; j < dim2; j++) {
- ef( n + j, n + j + 1);
- }
- ef( n + 1, n + dim2);
- n += dim2;
- }
- for (unsigned i = 1; i <= dim2; i++) {
- for (unsigned j = 1; j < dim1; j++) {
- ef( dim2 * (j - 1) + i, dim2 * j + i);
- }
- ef( i, dim2 * (dim1 - 1) + i);
- }
- }
- void makeTwistedTorus(unsigned dim1, unsigned dim2, unsigned t1, unsigned t2,
- edgefn ef) {
- for (unsigned i = 0; i < dim1; i++) {
- for (unsigned j = 0; j < dim2; j++) {
- unsigned li = (i + t1) % dim1;
- unsigned lj = (j + 1) % dim2;
- ef (i+j*dim1+1, li+lj*dim1+1);
- li = (i + 1) % dim1;
- lj = (j + t2) % dim2;
- ef(i+j*dim1+1, li+lj*dim1+1);
- }
- }
- }
- void makeCylinder(unsigned dim1, unsigned dim2, edgefn ef) {
- for (unsigned i = 1, n = 0; i <= dim1; i++) {
- for (unsigned j = 1; j < dim2; j++) {
- ef( n + j, n + j + 1);
- }
- ef( n + 1, n + dim2);
- n += dim2;
- }
- for (unsigned i = 1; i <= dim2; i++) {
- for (unsigned j = 1; j < dim1; j++) {
- ef( dim2 * (j - 1) + i, dim2 * j + i);
- }
- }
- }
- #define OUTE(h) if (tl < (hd=(h))) ef( tl, hd)
- void makeSquareGrid(unsigned dim1, unsigned dim2, int connect_corners, int partial, edgefn ef)
- {
- for (unsigned i = 0; i < dim1; i++)
- for (unsigned j = 0; j < dim2; j++) {
- // write the neighbors of the node i*dim2+j+1
- const unsigned tl = i * dim2 + j + 1;
- unsigned hd;
- if (j + 1 < dim2
- && (!partial || j < 2 * dim2 / 6 || j >= 4 * dim2 / 6
- || i <= 2 * dim1 / 6 || i > 4 * dim1 / 6)) {
- ef(tl, i * dim2 + j + 2);
- }
- if (i + 1 < dim1) {
- ef(tl, (i + 1) * dim2 + j + 1);
- }
- if (connect_corners == 1) {
- if (i == 0 && j == 0) { // upper left
- OUTE((dim1 - 1) * dim2 + dim2);
- } else if (i + 1 == dim1 && j == 0) { // lower left
- OUTE(dim2);
- } else if (i == 0 && j + 1 == dim2) { // upper right
- OUTE((dim1 - 1) * dim2 + 1);
- } else if (i + 1 == dim1 && j + 1 == dim2) { // lower right
- OUTE(1);
- }
- } else if (connect_corners == 2) {
- if (i == 0 && j == 0) { // upper left
- OUTE(dim2);
- } else if (i + 1 == dim1 && j == 0) { // lower left
- OUTE((dim1 - 1) * dim2 + dim2);
- } else if (i == 0 && j + 1 == dim2) { // upper right
- OUTE(1);
- } else if (i + 1 == dim1 && j + 1 == dim2) { // lower right
- OUTE((dim1 - 1) * dim2 + 1);
- }
- }
- }
- }
- void makeTree(unsigned depth, unsigned nary, edgefn ef) {
- const double n = (pow(nary, depth) - 1) / (nary - 1); // no. of non-leaf nodes
- unsigned idx = 2;
- for (unsigned i = 1; i <= n; i++) {
- for (unsigned j = 0; j < nary; j++) {
- ef (i, idx++);
- }
- }
- }
- void makeBinaryTree(unsigned depth, edgefn ef) {
- const unsigned n = (1u << depth) - 1;
- for (unsigned i = 1; i <= n; i++) {
- ef( i, 2 * i);
- ef( i, 2 * i + 1);
- }
- }
- typedef struct {
- unsigned nedges;
- unsigned *edges;
- } vtx_data;
- static void constructSierpinski(unsigned v1, unsigned v2, unsigned v3,
- unsigned depth, vtx_data *graph) {
- static unsigned last_used_node_name = 3;
- if (depth > 0) {
- const unsigned v4 = ++last_used_node_name;
- const unsigned v5 = ++last_used_node_name;
- const unsigned v6 = ++last_used_node_name;
- constructSierpinski(v1, v4, v5, depth - 1, graph);
- constructSierpinski(v2, v5, v6, depth - 1, graph);
- constructSierpinski(v3, v4, v6, depth - 1, graph);
- return;
- }
- // depth==0, Construct graph:
- unsigned nedges = graph[v1].nedges;
- graph[v1].edges[nedges++] = v2;
- graph[v1].edges[nedges++] = v3;
- graph[v1].nedges = nedges;
- nedges = graph[v2].nedges;
- graph[v2].edges[nedges++] = v1;
- graph[v2].edges[nedges++] = v3;
- graph[v2].nedges = nedges;
- nedges = graph[v3].nedges;
- graph[v3].edges[nedges++] = v1;
- graph[v3].edges[nedges++] = v2;
- graph[v3].nedges = nedges;
- }
- void makeSierpinski(unsigned depth, edgefn ef) {
- vtx_data* graph;
- depth--;
- const unsigned n = 3 * (1 + ((unsigned)(pow(3.0, depth) + 0.5) - 1) / 2);
- graph = gv_calloc(n + 1, sizeof(vtx_data));
- unsigned *edges = gv_calloc(4 * n, sizeof(unsigned));
- for (unsigned i = 1; i <= n; i++) {
- graph[i].edges = edges;
- edges += 4;
- graph[i].nedges = 0;
- }
- constructSierpinski(1, 2, 3, depth, graph);
- for (unsigned i = 1; i <= n; i++) {
- // write the neighbors of the node i
- for (unsigned j = 0; j < graph[i].nedges; j++) {
- const unsigned nghbr = graph[i].edges[j];
- if (i < nghbr) ef( i, nghbr);
- }
- }
- free(graph[1].edges);
- free(graph);
- }
- static void constructTetrix(unsigned v1, unsigned v2, unsigned v3, unsigned v4,
- unsigned depth, vtx_data* graph) {
- static unsigned last_used_node_name = 4;
- if (depth > 0) {
- const unsigned v5 = ++last_used_node_name;
- const unsigned v6 = ++last_used_node_name;
- const unsigned v7 = ++last_used_node_name;
- const unsigned v8 = ++last_used_node_name;
- const unsigned v9 = ++last_used_node_name;
- const unsigned v10 = ++last_used_node_name;
- constructTetrix(v1, v5, v6, v8, depth - 1, graph);
- constructTetrix(v2, v6, v7, v9, depth - 1, graph);
- constructTetrix(v3, v5, v7, v10, depth - 1, graph);
- constructTetrix(v4, v8, v9, v10, depth - 1, graph);
- return;
- }
- // depth==0, Construct graph:
- unsigned nedges = graph[v1].nedges;
- graph[v1].edges[nedges++] = v2;
- graph[v1].edges[nedges++] = v3;
- graph[v1].edges[nedges++] = v4;
- graph[v1].nedges = nedges;
- nedges = graph[v2].nedges;
- graph[v2].edges[nedges++] = v1;
- graph[v2].edges[nedges++] = v3;
- graph[v2].edges[nedges++] = v4;
- graph[v2].nedges = nedges;
- nedges = graph[v3].nedges;
- graph[v3].edges[nedges++] = v1;
- graph[v3].edges[nedges++] = v2;
- graph[v3].edges[nedges++] = v4;
- graph[v3].nedges = nedges;
- nedges = graph[v4].nedges;
- graph[v4].edges[nedges++] = v1;
- graph[v4].edges[nedges++] = v2;
- graph[v4].edges[nedges++] = v3;
- graph[v4].nedges = nedges;
- }
- void makeTetrix(unsigned depth, edgefn ef) {
- vtx_data* graph;
- depth--;
- const unsigned n = 4 + 2 * (((unsigned)(pow(4.0, depth) + 0.5) - 1));
- graph = gv_calloc(n + 1, sizeof(vtx_data));
- unsigned *edges = gv_calloc(6 * n, sizeof(unsigned));
- for (unsigned i = 1; i <= n; i++) {
- graph[i].edges = edges;
- edges += 6;
- graph[i].nedges = 0;
- }
- constructTetrix(1, 2, 3, 4, depth, graph);
- for (unsigned i = 1; i <= n; i++) {
- // write the neighbors of the node i
- for (unsigned j = 0; j < graph[i].nedges; j++) {
- const unsigned nghbr = graph[i].edges[j];
- if (i < nghbr) ef( i, nghbr);
- }
- }
- free(graph[1].edges);
- free(graph);
- }
- void makeHypercube(unsigned dim, edgefn ef) {
- const unsigned n = 1u << dim;
- for (unsigned i = 0; i < n; i++) {
- for (unsigned j = 0; j < dim; j++) {
- const unsigned neighbor = (i ^ (1u << j)) + 1;
- if (i < neighbor)
- ef( i + 1, neighbor);
- }
- }
- }
- void makeTriMesh(unsigned sz, edgefn ef) {
- if (sz == 1) {
- ef (1, 0);
- return;
- }
- ef(1,2);
- ef(1,3);
- unsigned idx = 2;
- for (unsigned i = 2; i < sz; i++) {
- for (unsigned j = 1; j <= i; j++) {
- ef(idx,idx+i);
- ef(idx,idx+i+1);
- if (j < i)
- ef(idx,idx+1);
- idx++;
- }
- }
- for (unsigned j = 1; j < sz; j++) {
- ef (idx,idx+1);
- idx++;
- }
- }
- void makeBall(unsigned w, unsigned h, edgefn ef) {
- makeCylinder (w, h, ef);
- for (unsigned i = 1; i <= h; i++)
- ef (0, i);
- const unsigned cap = w * h + 1;
- for (unsigned i = (w - 1) * h + 1; i <= w * h; i++)
- ef (i, cap);
- }
- /* makeRandom:
- * No. of nodes is largest 2^n - 1 less than or equal to h.
- */
- void makeRandom(unsigned h, unsigned w, edgefn ef) {
- srand((unsigned)time(0));
- const int type = rand() % 2;
- unsigned size = 0;
- unsigned depth = 0;
- while (size <= h) {
- size += 1u << depth;
- depth++;
- }
- depth--;
- if (size > h) {
- size -= 1u << depth;
- depth--;
- }
- if (type)
- makeBinaryTree (depth, ef);
- else
- makePath (size, ef);
- for (unsigned i = 3; i <= size; i++) {
- for (unsigned j = 1; j + 1 < i; j++) {
- const unsigned th = (unsigned)rand() % (size * size);
- if ((th <= w * w && (i < 5 || (i + 4 > h && j + 4 > h))) || th <= w)
- ef(j,i);
- }
- }
- }
- void makeMobius(unsigned w, unsigned h, edgefn ef) {
- if (h == 1) {
- fprintf(stderr, "Warning: degenerate Moebius strip of %u vertices\n", w);
- makePath(w, ef);
- return;
- }
- if (w == 1) {
- fprintf(stderr, "Warning: degenerate Moebius strip of %u vertices\n", h);
- makePath(h, ef);
- return;
- }
- for (unsigned i = 0; i + 1 < w; i++) {
- for (unsigned j = 1; j < h; j++){
- ef(j + i*h, j + (i+1)*h);
- ef(j + i*h, j+1 + i*h);
- }
- }
- for (unsigned i = 1; i < h; i++){
- ef (i + (w-1)*h, i+1 + (w-1)*h);
- }
- for (unsigned i=1; i < w; i++) {
- ef(i*h , (i+1)*h);
- ef(i*h, (w-i)*h+1);
- }
- ef(1,w*h);
- }
- typedef struct {
- unsigned j, d;
- } pair;
- typedef struct {
- unsigned top, root;
- unsigned* p;
- } tree_t;
- static tree_t *mkTree(unsigned sz) {
- tree_t* tp = gv_alloc(sizeof(tree_t));
- tp->root = 0;
- tp->top = 0;
- tp->p = gv_calloc(sz, sizeof(unsigned));
- return tp;
- }
- static void
- freeTree (tree_t* tp)
- {
- free (tp->p);
- free (tp);
- }
- static void
- resetTree (tree_t* tp)
- {
- tp->root = 0;
- tp->top = 0;
- }
- static unsigned treeRoot(tree_t* tp) {
- return tp->root;
- }
- static unsigned prevRoot(tree_t *tp) {
- return tp->p[tp->root];
- }
- static unsigned treeSize(tree_t *tp) {
- return tp->top - tp->root + 1;
- }
- static unsigned treeTop(tree_t *tp) {
- return tp->top;
- }
- static void
- treePop (tree_t* tp)
- {
- tp->root = prevRoot(tp);
- }
- static void addTree(tree_t *tp, unsigned sz) {
- tp->p[tp->top+1] = tp->root;
- tp->root = tp->top+1;
- tp->top += sz;
- if (sz > 1) tp->p[tp->top] = tp->top-1;
- }
- static void treeDup(tree_t *tp, unsigned J) {
- unsigned M = treeSize(tp);
- unsigned L = treeRoot(tp);
- unsigned LL = prevRoot(tp);
- unsigned LS = L + (J-1)*M - 1;
- for (unsigned i = L; i <= LS; i++) {
- if ((i-L)%M == 0) tp->p[i+M] = LL;
- else tp->p[i+M] = tp->p[i] + M;
- }
- tp->top = LS + M;
- }
- /*****************/
- DEFINE_LIST(int_stack, unsigned)
- static void push(int_stack_t *sp, unsigned j, unsigned d) {
- int_stack_push_back(sp, j);
- int_stack_push_back(sp, d);
- }
- static pair pop(int_stack_t *sp) {
- // extract ints in the opposite order in which they were pushed
- const unsigned d = int_stack_pop_back(sp);
- const unsigned j = int_stack_pop_back(sp);
- return (pair){j, d};
- }
- /*****************/
- static unsigned *genCnt(unsigned NN) {
- unsigned* T = gv_calloc(NN + 1, sizeof(unsigned));
- unsigned NLAST = 1;
- T[1] = 1;
- while (NN > NLAST) {
- unsigned SUM = 0;
- for (unsigned D = 1; D <= NLAST; D++) {
- unsigned I = NLAST + 1;
- const unsigned TD = T[D] * D;
- for (unsigned J = 1; J <= NLAST; J++) {
- if (I <= D) break;
- I = I-D;
- SUM += T[I]*TD;
- }
- }
- NLAST++;
- T[NLAST] = SUM/(NLAST-1);
- }
- return T;
- }
- static double
- drand(void)
- {
- double d;
- d = rand();
- d = d / RAND_MAX;
- return d;
- }
- static void genTree(unsigned NN, unsigned *T, int_stack_t *stack,
- tree_t *TREE) {
- double v;
- pair p;
- unsigned J;
- unsigned N = NN;
- while (1) {
- while (N > 2) {
- v = (N-1)*T[N];
- double Z = floor(v * drand());
- unsigned D = 0;
- bool more = true;
- unsigned M;
- do {
- D++;
- const unsigned TD = D*T[D];
- M = N;
- J = 0;
- do {
- J++;
- if (M < D + 1) break;
- M -= D;
- if (Z < T[M] * TD) {
- more = false;
- break;
- }
- Z -= T[M]*TD;
- } while (true);
- } while (more);
- push(stack, J, D);
- N = M;
- }
- addTree (TREE, N);
-
- while (1) {
- p = pop(stack);
- N = p.d;
- if (N != 0) {
- push(stack,p.j,0);
- break;
- }
- J = p.j;
- if (J > 1) treeDup (TREE, J);
- if (treeTop(TREE) == NN) return;
- treePop(TREE);
- }
- }
- }
- static void
- writeTree (tree_t* tp, edgefn ef)
- {
- for (unsigned i = 2; i <= tp->top; i++)
- ef (tp->p[i], i);
- }
- struct treegen_s {
- unsigned N;
- unsigned* T;
- int_stack_t sp;
- tree_t* tp;
- };
- treegen_t *makeTreeGen(unsigned N) {
- treegen_t* tg = gv_alloc(sizeof(treegen_t));
- tg->N = N;
- tg->T = genCnt(N);
- tg->sp = (int_stack_t){0};
- tg->tp = mkTree(N+1);
- srand((unsigned)time(0));
- return tg;
- }
- void makeRandomTree (treegen_t* tg, edgefn ef)
- {
- int_stack_clear(&tg->sp);
- resetTree(tg->tp);
- genTree(tg->N, tg->T, &tg->sp, tg->tp);
- writeTree (tg->tp, ef);
- }
- void
- freeTreeGen(treegen_t* tg)
- {
- free (tg->T);
- int_stack_free(&tg->sp);
- freeTree (tg->tp);
- free (tg);
- }
|