first working, without arg parser, unoptimized

This commit is contained in:
Слободан Јелић 2024-12-31 11:10:33 +01:00
parent b6150ab95c
commit c7fd378336
20 changed files with 1104 additions and 149 deletions

View File

@ -9,7 +9,8 @@
"defines": [], "defines": [],
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "gnu++17", "cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64" "intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools"
} }
], ],
"version": 4 "version": 4

View File

@ -1,6 +1,11 @@
{ {
"files.associations": { "files.associations": {
"random_graph.h": "c", "random_graph.h": "c",
"random_groups.h": "c" "random_groups.h": "c",
"random_edge_weight.h": "c",
"rand_large.h": "c",
"stdint.h": "c",
"random_group_steiner.h": "c",
"random_vertex_weight.h": "c"
} }
} }

View File

@ -1,8 +1,8 @@
# Compiler and Flags # Compiler and Flags
CC = gcc CC = gcc
# CFLAGS = -Wall -Wextra -Iinclude -g -pg CFLAGS = -Wall -Wextra -Iinclude -g -pg -O0
CFLAGS = -O2 -march=native -DNDEBUG -Wall -Wextra -Werror -Iinclude # CFLAGS = -O3 -march=native -DNDEBUG -Wall -Wextra -Werror -Iinclude -s -flto -fno-math-errno
LDFLAGS = -lm LDFLAGS = -lm -flto
# Directories # Directories
SRC_DIR = src SRC_DIR = src

160
analysis Normal file
View File

@ -0,0 +1,160 @@
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
100.07 3.36 3.36 2 1.68 1.68 random_connected_graph
0.00 3.36 0.00 6 0.00 0.00 cmpInt
0.00 3.36 0.00 3 0.00 0.00 generate_random_edge_weight
% the percentage of the total running time of the
time program used by this function.
cumulative a running sum of the number of seconds accounted
seconds for by this function and those listed above it.
self the number of seconds accounted for by this
seconds function alone. This is the major sort for this
listing.
calls the number of times this function was invoked, if
this function is profiled, else blank.
self the average number of milliseconds spent in this
ms/call function per call, if this function is profiled,
else blank.
total the average number of milliseconds spent in this
ms/call function and its descendents per call, if this
function is profiled, else blank.
name the name of the function. This is the minor sort
for this listing. The index shows the location of
the function in the gprof listing. If the index is
in parenthesis it shows where it would appear in
the gprof listing if it were to be printed.
Copyright (C) 2012-2023 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
Call graph (explanation follows)
granularity: each sample hit covers 2 byte(s) for 0.30% of 3.36 seconds
index % time self children called name
1.68 0.00 1/2 main [3]
1.68 0.00 1/2 generate_random_group_steiner_instance [2]
[1] 100.0 3.36 0.00 2 random_connected_graph [1]
0.00 0.00 6/6 cmpInt [4]
0.00 0.00 3/3 generate_random_edge_weight [5]
-----------------------------------------------
<spontaneous>
[2] 50.0 0.00 1.68 generate_random_group_steiner_instance [2]
1.68 0.00 1/2 random_connected_graph [1]
-----------------------------------------------
<spontaneous>
[3] 50.0 0.00 1.68 main [3]
1.68 0.00 1/2 random_connected_graph [1]
-----------------------------------------------
0.00 0.00 6/6 random_connected_graph [1]
[4] 0.0 0.00 0.00 6 cmpInt [4]
-----------------------------------------------
0.00 0.00 3/3 random_connected_graph [1]
[5] 0.0 0.00 0.00 3 generate_random_edge_weight [5]
-----------------------------------------------
This table describes the call tree of the program, and was sorted by
the total amount of time spent in each function and its children.
Each entry in this table consists of several lines. The line with the
index number at the left hand margin lists the current function.
The lines above it list the functions that called this function,
and the lines below it list the functions this one called.
This line lists:
index A unique number given to each element of the table.
Index numbers are sorted numerically.
The index number is printed next to every function name so
it is easier to look up where the function is in the table.
% time This is the percentage of the `total' time that was spent
in this function and its children. Note that due to
different viewpoints, functions excluded by options, etc,
these numbers will NOT add up to 100%.
self This is the total amount of time spent in this function.
children This is the total amount of time propagated into this
function by its children.
called This is the number of times the function was called.
If the function called itself recursively, the number
only includes non-recursive calls, and is followed by
a `+' and the number of recursive calls.
name The name of the current function. The index number is
printed after it. If the function is a member of a
cycle, the cycle number is printed between the
function's name and the index number.
For the function's parents, the fields have the following meanings:
self This is the amount of time that was propagated directly
from the function into this parent.
children This is the amount of time that was propagated from
the function's children into this parent.
called This is the number of times this parent called the
function `/' the total number of times the function
was called. Recursive calls to the function are not
included in the number after the `/'.
name This is the name of the parent. The parent's index
number is printed after it. If the parent is a
member of a cycle, the cycle number is printed between
the name and the index number.
If the parents of the function cannot be determined, the word
`<spontaneous>' is printed in the `name' field, and all the other
fields are blank.
For the function's children, the fields have the following meanings:
self This is the amount of time that was propagated directly
from the child into the function.
children This is the amount of time that was propagated from the
child's children to the function.
called This is the number of times the function called
this child `/' the total number of times the child
was called. Recursive calls by the child are not
listed in the number after the `/'.
name This is the name of the child. The child's index
number is printed after it. If the child is a
member of a cycle, the cycle number is printed
between the name and the index number.
If there are any cycles (circles) in the call graph, there is an
entry for the cycle-as-a-whole. This entry shows who called the
cycle (as parents) and the members of the cycle (as children.)
The `+' recursive calls entry shows the number of function calls that
were internal to the cycle, and the calls entry for each member shows,
for that member, how many times it was called from other members of
the cycle.
Copyright (C) 2012-2023 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
Index by function name
[4] cmpInt [5] generate_random_edge_weight [1] random_connected_graph

View File

@ -14,6 +14,5 @@ services:
# - NODE_ENV=development # - NODE_ENV=development
user: root user: root
command: sleep infinity command: sleep infinity
volumes: volumes:
steingen-volume: steingen-volume:

512
example2.txt Normal file
View File

@ -0,0 +1,512 @@
Generated graph edges:
Edge 0 -> 1
Edge 0 -> 2
Edge 0 -> 6
Edge 0 -> 8
Edge 0 -> 9
Edge 0 -> 10
Edge 0 -> 13
Edge 0 -> 14
Edge 0 -> 15
Edge 0 -> 22
Edge 0 -> 23
Edge 0 -> 24
Edge 0 -> 25
Edge 0 -> 26
Edge 0 -> 27
Edge 0 -> 28
Edge 0 -> 29
Edge 0 -> 30
Edge 0 -> 31
Edge 0 -> 32
Edge 0 -> 35
Edge 0 -> 38
Edge 1 -> 3
Edge 1 -> 7
Edge 1 -> 8
Edge 1 -> 10
Edge 1 -> 11
Edge 1 -> 12
Edge 1 -> 13
Edge 1 -> 14
Edge 1 -> 15
Edge 1 -> 17
Edge 1 -> 18
Edge 1 -> 19
Edge 1 -> 20
Edge 1 -> 21
Edge 1 -> 22
Edge 1 -> 24
Edge 1 -> 25
Edge 1 -> 27
Edge 1 -> 28
Edge 1 -> 29
Edge 1 -> 30
Edge 1 -> 31
Edge 1 -> 32
Edge 1 -> 33
Edge 1 -> 35
Edge 1 -> 36
Edge 1 -> 37
Edge 1 -> 39
Edge 2 -> 3
Edge 2 -> 4
Edge 2 -> 7
Edge 2 -> 8
Edge 2 -> 9
Edge 2 -> 12
Edge 2 -> 13
Edge 2 -> 14
Edge 2 -> 15
Edge 2 -> 16
Edge 2 -> 17
Edge 2 -> 18
Edge 2 -> 19
Edge 2 -> 20
Edge 2 -> 21
Edge 2 -> 22
Edge 2 -> 24
Edge 2 -> 27
Edge 2 -> 29
Edge 2 -> 30
Edge 2 -> 31
Edge 2 -> 33
Edge 2 -> 34
Edge 2 -> 36
Edge 2 -> 38
Edge 2 -> 39
Edge 3 -> 4
Edge 3 -> 6
Edge 3 -> 7
Edge 3 -> 9
Edge 3 -> 10
Edge 3 -> 12
Edge 3 -> 13
Edge 3 -> 14
Edge 3 -> 15
Edge 3 -> 16
Edge 3 -> 17
Edge 3 -> 18
Edge 3 -> 19
Edge 3 -> 21
Edge 3 -> 22
Edge 3 -> 23
Edge 3 -> 24
Edge 3 -> 26
Edge 3 -> 27
Edge 3 -> 28
Edge 3 -> 31
Edge 3 -> 32
Edge 3 -> 33
Edge 3 -> 34
Edge 3 -> 35
Edge 3 -> 38
Edge 4 -> 5
Edge 4 -> 6
Edge 4 -> 7
Edge 4 -> 8
Edge 4 -> 9
Edge 4 -> 11
Edge 4 -> 12
Edge 4 -> 13
Edge 4 -> 14
Edge 4 -> 15
Edge 4 -> 17
Edge 4 -> 19
Edge 4 -> 20
Edge 4 -> 21
Edge 4 -> 22
Edge 4 -> 23
Edge 4 -> 25
Edge 4 -> 27
Edge 4 -> 28
Edge 4 -> 29
Edge 4 -> 30
Edge 4 -> 31
Edge 4 -> 32
Edge 4 -> 33
Edge 4 -> 35
Edge 4 -> 38
Edge 4 -> 39
Edge 5 -> 8
Edge 5 -> 9
Edge 5 -> 10
Edge 5 -> 11
Edge 5 -> 12
Edge 5 -> 16
Edge 5 -> 17
Edge 5 -> 18
Edge 5 -> 22
Edge 5 -> 24
Edge 5 -> 25
Edge 5 -> 26
Edge 5 -> 28
Edge 5 -> 34
Edge 5 -> 36
Edge 5 -> 37
Edge 5 -> 38
Edge 5 -> 39
Edge 6 -> 7
Edge 6 -> 9
Edge 6 -> 10
Edge 6 -> 11
Edge 6 -> 12
Edge 6 -> 13
Edge 6 -> 14
Edge 6 -> 15
Edge 6 -> 17
Edge 6 -> 18
Edge 6 -> 20
Edge 6 -> 22
Edge 6 -> 23
Edge 6 -> 26
Edge 6 -> 27
Edge 6 -> 28
Edge 6 -> 29
Edge 6 -> 30
Edge 6 -> 33
Edge 6 -> 36
Edge 6 -> 37
Edge 7 -> 8
Edge 7 -> 9
Edge 7 -> 12
Edge 7 -> 14
Edge 7 -> 15
Edge 7 -> 17
Edge 7 -> 18
Edge 7 -> 19
Edge 7 -> 20
Edge 7 -> 23
Edge 7 -> 24
Edge 7 -> 26
Edge 7 -> 27
Edge 7 -> 32
Edge 7 -> 33
Edge 7 -> 34
Edge 7 -> 35
Edge 7 -> 37
Edge 7 -> 38
Edge 8 -> 10
Edge 8 -> 12
Edge 8 -> 13
Edge 8 -> 14
Edge 8 -> 15
Edge 8 -> 17
Edge 8 -> 18
Edge 8 -> 19
Edge 8 -> 20
Edge 8 -> 21
Edge 8 -> 23
Edge 8 -> 25
Edge 8 -> 27
Edge 8 -> 30
Edge 8 -> 31
Edge 8 -> 35
Edge 8 -> 37
Edge 8 -> 38
Edge 9 -> 10
Edge 9 -> 11
Edge 9 -> 13
Edge 9 -> 14
Edge 9 -> 15
Edge 9 -> 16
Edge 9 -> 17
Edge 9 -> 19
Edge 9 -> 20
Edge 9 -> 21
Edge 9 -> 24
Edge 9 -> 25
Edge 9 -> 26
Edge 9 -> 27
Edge 9 -> 29
Edge 9 -> 31
Edge 9 -> 33
Edge 9 -> 34
Edge 9 -> 37
Edge 9 -> 39
Edge 10 -> 11
Edge 10 -> 12
Edge 10 -> 15
Edge 10 -> 16
Edge 10 -> 17
Edge 10 -> 18
Edge 10 -> 19
Edge 10 -> 20
Edge 10 -> 21
Edge 10 -> 22
Edge 10 -> 24
Edge 10 -> 25
Edge 10 -> 28
Edge 10 -> 29
Edge 10 -> 32
Edge 10 -> 33
Edge 10 -> 34
Edge 10 -> 35
Edge 10 -> 38
Edge 11 -> 12
Edge 11 -> 13
Edge 11 -> 15
Edge 11 -> 16
Edge 11 -> 20
Edge 11 -> 21
Edge 11 -> 22
Edge 11 -> 24
Edge 11 -> 25
Edge 11 -> 27
Edge 11 -> 28
Edge 11 -> 30
Edge 11 -> 31
Edge 11 -> 32
Edge 11 -> 35
Edge 11 -> 36
Edge 11 -> 38
Edge 11 -> 39
Edge 12 -> 13
Edge 12 -> 14
Edge 12 -> 15
Edge 12 -> 16
Edge 12 -> 18
Edge 12 -> 19
Edge 12 -> 20
Edge 12 -> 21
Edge 12 -> 24
Edge 12 -> 25
Edge 12 -> 29
Edge 12 -> 31
Edge 12 -> 32
Edge 12 -> 33
Edge 12 -> 34
Edge 12 -> 35
Edge 12 -> 36
Edge 12 -> 37
Edge 12 -> 38
Edge 12 -> 39
Edge 13 -> 14
Edge 13 -> 15
Edge 13 -> 16
Edge 13 -> 17
Edge 13 -> 18
Edge 13 -> 21
Edge 13 -> 22
Edge 13 -> 24
Edge 13 -> 27
Edge 13 -> 31
Edge 13 -> 32
Edge 13 -> 34
Edge 13 -> 35
Edge 13 -> 38
Edge 14 -> 15
Edge 14 -> 16
Edge 14 -> 17
Edge 14 -> 19
Edge 14 -> 21
Edge 14 -> 22
Edge 14 -> 23
Edge 14 -> 24
Edge 14 -> 25
Edge 14 -> 30
Edge 14 -> 31
Edge 14 -> 32
Edge 14 -> 33
Edge 14 -> 34
Edge 14 -> 35
Edge 14 -> 37
Edge 14 -> 39
Edge 15 -> 16
Edge 15 -> 17
Edge 15 -> 19
Edge 15 -> 21
Edge 15 -> 23
Edge 15 -> 24
Edge 15 -> 25
Edge 15 -> 27
Edge 15 -> 28
Edge 15 -> 29
Edge 15 -> 30
Edge 15 -> 36
Edge 15 -> 37
Edge 15 -> 38
Edge 15 -> 39
Edge 16 -> 17
Edge 16 -> 18
Edge 16 -> 19
Edge 16 -> 20
Edge 16 -> 22
Edge 16 -> 23
Edge 16 -> 24
Edge 16 -> 27
Edge 16 -> 28
Edge 16 -> 29
Edge 16 -> 31
Edge 16 -> 32
Edge 16 -> 33
Edge 16 -> 35
Edge 16 -> 38
Edge 17 -> 18
Edge 17 -> 19
Edge 17 -> 21
Edge 17 -> 23
Edge 17 -> 25
Edge 17 -> 27
Edge 17 -> 28
Edge 17 -> 29
Edge 17 -> 31
Edge 17 -> 32
Edge 17 -> 33
Edge 17 -> 36
Edge 17 -> 37
Edge 17 -> 38
Edge 17 -> 39
Edge 18 -> 19
Edge 18 -> 20
Edge 18 -> 21
Edge 18 -> 22
Edge 18 -> 23
Edge 18 -> 25
Edge 18 -> 26
Edge 18 -> 27
Edge 18 -> 28
Edge 18 -> 29
Edge 18 -> 33
Edge 18 -> 35
Edge 18 -> 36
Edge 18 -> 37
Edge 18 -> 38
Edge 18 -> 39
Edge 19 -> 20
Edge 19 -> 21
Edge 19 -> 22
Edge 19 -> 23
Edge 19 -> 26
Edge 19 -> 27
Edge 19 -> 29
Edge 19 -> 32
Edge 19 -> 34
Edge 19 -> 35
Edge 19 -> 36
Edge 19 -> 37
Edge 19 -> 38
Edge 19 -> 39
Edge 20 -> 21
Edge 20 -> 23
Edge 20 -> 24
Edge 20 -> 25
Edge 20 -> 26
Edge 20 -> 28
Edge 20 -> 29
Edge 20 -> 31
Edge 20 -> 32
Edge 20 -> 37
Edge 20 -> 39
Edge 21 -> 22
Edge 21 -> 23
Edge 21 -> 25
Edge 21 -> 27
Edge 21 -> 29
Edge 21 -> 31
Edge 21 -> 32
Edge 21 -> 33
Edge 21 -> 35
Edge 21 -> 36
Edge 21 -> 38
Edge 21 -> 39
Edge 22 -> 23
Edge 22 -> 24
Edge 22 -> 26
Edge 22 -> 28
Edge 22 -> 29
Edge 22 -> 34
Edge 22 -> 37
Edge 22 -> 38
Edge 22 -> 39
Edge 23 -> 26
Edge 23 -> 27
Edge 23 -> 30
Edge 23 -> 32
Edge 23 -> 33
Edge 23 -> 34
Edge 23 -> 37
Edge 23 -> 38
Edge 24 -> 28
Edge 24 -> 31
Edge 24 -> 33
Edge 24 -> 36
Edge 24 -> 37
Edge 24 -> 38
Edge 24 -> 39
Edge 25 -> 26
Edge 25 -> 27
Edge 25 -> 30
Edge 25 -> 33
Edge 25 -> 34
Edge 25 -> 36
Edge 25 -> 37
Edge 25 -> 38
Edge 25 -> 39
Edge 26 -> 27
Edge 26 -> 28
Edge 26 -> 29
Edge 26 -> 30
Edge 26 -> 32
Edge 26 -> 34
Edge 26 -> 35
Edge 26 -> 36
Edge 26 -> 37
Edge 26 -> 38
Edge 27 -> 29
Edge 27 -> 30
Edge 27 -> 31
Edge 27 -> 35
Edge 27 -> 36
Edge 27 -> 37
Edge 27 -> 39
Edge 28 -> 29
Edge 28 -> 31
Edge 28 -> 33
Edge 28 -> 35
Edge 28 -> 38
Edge 29 -> 30
Edge 29 -> 34
Edge 29 -> 35
Edge 29 -> 37
Edge 29 -> 39
Edge 30 -> 31
Edge 30 -> 32
Edge 30 -> 34
Edge 30 -> 36
Edge 30 -> 37
Edge 30 -> 38
Edge 31 -> 32
Edge 31 -> 33
Edge 31 -> 34
Edge 31 -> 35
Edge 31 -> 39
Edge 32 -> 33
Edge 32 -> 35
Edge 32 -> 36
Edge 32 -> 37
Edge 32 -> 38
Edge 32 -> 39
Edge 33 -> 34
Edge 33 -> 35
Edge 34 -> 36
Edge 34 -> 37
Edge 34 -> 38
Edge 34 -> 39
Edge 35 -> 36
Edge 35 -> 37
Edge 35 -> 38
Edge 36 -> 38
Edge 37 -> 38
Edge 37 -> 39
Random groups:
Group 0: 0 23
Group 1: 10 29
Group 2: 16 25
Group 3: 30 31
Group 4: 5 18
Group 5: 20 27
Group 6: 1 15
Group 7: 2 22
Group 8: 11 16
Group 9: 0 8

17
include/rand_large.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef RAND_R_LARGE_H
#define RAND_R_LARGE_H
#include <stdint.h>
/**
* Generates a large random number by combining two `rand_r` calls.
*
* @param seed A pointer to an unsigned 16-bit seed used for the random number generator.
* The seed is updated after each call to maintain the sequence.
*
* @return A 64-bit unsigned random number.
*/
uint64_t rand_r_large(uint16_t* seed);
#endif // RAND_R_LARGE_H

View File

@ -0,0 +1,14 @@
#ifndef GEOMETRY_WEIGHTS_H
#define GEOMETRY_WEIGHTS_H
#include <stdlib.h>
#include <stdint.h>
// Function to embed vertices into 2D space
void embed_vertices(int N, float B, float *x, float *y, uint16_t* seed);
// Function to generate random edge weight
float generate_random_edge_weight(float *x, float *y, unsigned int N, unsigned int s, unsigned int t,
float a, float b, const char *family, const char *type, uint16_t* seed);
#endif // GEOMETRY_WEIGHTS_H

View File

@ -4,20 +4,22 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <stdint.h>
#include "rand_large.h"
// Edge structure // Edge structure
typedef struct Edge { typedef struct Edge {
int src; uint32_t src;
int dest; uint32_t dest;
} Edge; } Edge;
// Function prototypes // Function prototypes
int cmpInt(const void *a, const void *b); int cmpInt(const void *a, const void *b);
unsigned int uv2index(unsigned int u, unsigned int v, unsigned int n); uint64_t uv2index(uint32_t u, uint32_t v, uint32_t n);
unsigned int min(unsigned int u, unsigned int v); uint32_t min(uint32_t u, uint32_t v);
unsigned int max(unsigned int u, unsigned int v); uint32_t max(uint32_t u, uint32_t v);
int index2uv(unsigned int index, unsigned int n, int *u, int *v); int8_t index2uv(uint64_t index, uint32_t n, uint32_t *u, uint32_t *v);
void random_spanning_tree( void random_connected_graph(
unsigned int n, unsigned int m, unsigned int seed, Edge *edges); uint32_t n, uint64_t m, Edge *edges, uint16_t* seed);
#endif // RANDOM_GRAPH_H #endif // RANDOM_GRAPH_H

View File

@ -0,0 +1,13 @@
#ifndef RANDOM_GROUP_STEINER_H
#define RANDOM_GROUP_STEINER_H
#include "random_groups.h"
#include "random_graph.h"
// Function to generate a random Group Steiner instance
void generate_random_group_steiner_instance(
uint32_t n, uint32_t m, uint16_t k, const char *filename,
float vertex_a, float vertex_b, const char *vertex_weight_type,
float edge_a, float edge_b, const char *edge_weight_family, const char *edge_weight_type, const char *instance_type, uint16_t* seed);
#endif // RANDOM_GROUP_STEINER_H

View File

@ -3,14 +3,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
// Struct for representing groups // Struct for representing groups
typedef struct { typedef struct {
unsigned int *group; // Pointer to an array of group members uint32_t *group; // Pointer to an array of group members
unsigned int size; // Number of members in the group uint32_t size; // Number of members in the group
} Group; } Group;
// Function to generate random groups // Function to generate random groups
void generate_random_groups(unsigned int n, unsigned int k, Group **groups); void shuffle(uint32_t *array, uint32_t size, uint16_t* seed);
void generate_random_groups(uint32_t n, uint16_t k, Group *groups, uint16_t* seed);
#endif // RANDOM_GROUPS_H #endif // RANDOM_GROUPS_H

View File

@ -0,0 +1,12 @@
#ifndef RANDOM_VERTEX_WEIGHT_H
#define RANDOM_VERTEX_WEIGHT_H
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdint.h>
// Function to generate a random vertex weight
float generate_random_vertex_weight(const char *weight_type, float a, float b, uint16_t* seed);
#endif // RANDOM_VERTEX_WEIGHT_H

0
random_instance.stp Normal file
View File

View File

@ -1,38 +1,27 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include "random_group_steiner.h"
#include "random_graph.h"
#include "random_groups.h"
int main() { int main() {
unsigned int n = 20, m = 80, k = 4, seed = 5; uint32_t n = 90000; // Number of vertices
Edge *edges = malloc(m * sizeof(Edge)); uint64_t m = 1000000; // Number of edges
if (!edges) { uint16_t k = 2000; // Number of groups
fprintf(stderr, "Error: Memory allocation of EDGE array: edges FAILED.\n"); uint16_t seed = 12345;
exit(EXIT_FAILURE);
}
random_spanning_tree(n, m, seed, edges);
printf("Generated graph edges:\n");
for (unsigned int i = 0; i < m; i++) {
printf("Edge %d -> %d\n", edges[i].src, edges[i].dest);
}
Group *groups;
generate_random_groups(n, k, &groups);
// Print groups const char *filename = "random_instance.stp";
printf("Random groups:\n"); float vertex_a = 1.0, vertex_b = 10.0;
for (unsigned int i = 0; i < k; i++) { const char *vertex_weight_type = "float";
printf("Group %u: ", i); float edge_a = 1.0, edge_b = 10.0;
for (unsigned int j = 0; j < groups[i].size; j++) { const char *edge_weight_family = "random";
printf("%u ", groups[i].group[j]); const char *edge_weight_type = "float";
} const char *instance_type = "Node Weighted Group Steiner Tree Instance";
printf("\n");
free(groups[i].group); // Free each group's array generate_random_group_steiner_instance(
} n, m, k, filename,
free(groups); // Free the groups array vertex_a, vertex_b, vertex_weight_type,
free(edges); edge_a, edge_b, edge_weight_family, edge_weight_type, instance_type, &seed);
printf("Random Group Steiner instance written to %s\n", filename);
return 0; return 0;
} }

12
src/rand_large.c Normal file
View File

@ -0,0 +1,12 @@
#include <stdint.h>
#include <stdlib.h>
#include "rand_large.h"
/**
* Generates a large random number by combining two `rand_r` calls.
*/
uint64_t rand_r_large(uint16_t* seed) {
// Combine two `rand_r` calls for a larger range
uint64_t large_random = ((uint64_t)rand_r((unsigned int* )seed) << 31) | rand_r((unsigned int* )seed);
return large_random;
}

49
src/random_edge_weight.c Normal file
View File

@ -0,0 +1,49 @@
#include "random_edge_weight.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
// Embed vertices into 2D space with random coordinates between 0 and B
void embed_vertices(int N, float B, float *x, float *y, uint16_t* seed) {
for (int i = 0; i < N; i++) {
x[i] = ((float)rand_r((unsigned int* )seed) / RAND_MAX) * B;
y[i] = ((float)rand_r((unsigned int* )seed) / RAND_MAX) * B;
}
}
// Generate random edge weight based on the given weight type
float generate_random_edge_weight(float *x, float *y, unsigned int N, unsigned int s, unsigned int t,
float a, float b, const char *family, const char *type, uint16_t* seed) {
if (s >= N || t >= N) {
fprintf(stderr, "Error: Vertex indices s (%u) or t (%u) exceed the number of vertices (%d).\n", s, t, N);
exit(EXIT_FAILURE);
}
float weight = 1.0;
if (strcmp(family, "euclid") == 0) {
// Euclidean distance
float dx = x[s] - x[t];
float dy = y[s] - y[t];
weight += sqrt(dx * dx + dy * dy);
} else if (strcmp(family, "grid") == 0) {
// Manhattan distance
weight += fabs(x[s] - x[t]) + fabs(y[s] - y[t]);
} else if (strcmp(family, "random") == 0) {
// Uniform random weight
weight += a + ((float)rand_r((unsigned int* )seed) / RAND_MAX) * (b - a);
} else {
fprintf(stderr, "Error: Invalid weight type '%s'. Use 'euclid', 'grid', or 'random'.\n", family);
exit(EXIT_FAILURE);
}
// Cast to integer if the type is "int"
if (strcmp(type, "int") == 0) {
weight = (float)((int)weight);
} else if (strcmp(type, "float") != 0) {
fprintf(stderr, "Error: Invalid type '%s'. Use 'int' or 'float'.\n", type);
exit(EXIT_FAILURE);
}
return weight;
}

View File

@ -1,50 +1,60 @@
#include "random_graph.h" #include "random_graph.h"
int cmpInt(const void *a, const void *b) { int cmpInt(const void *a, const void *b) {
return (*(unsigned int *)a - *(unsigned int *)b); int64_t int_a = *(int64_t *)a;
int64_t int_b = *(int64_t *)b;
// Return the difference (int_a - int_b)
return (int) ((int_a > int_b) - (int_a < int_b)); // Returns -1, 0, or 1
} }
inline unsigned int min(unsigned int u, unsigned int v){ inline uint32_t min(uint32_t u, uint32_t v){
return u < v ? u : v; return u < v ? u : v;
} }
inline unsigned int max(unsigned int u, unsigned int v){ inline uint32_t max(uint32_t u, uint32_t v){
return u < v ? v : u; return u < v ? v : u;
} }
unsigned int uv2index(unsigned int u, unsigned int v, unsigned int n) { uint64_t uv2index(uint32_t u, uint32_t v, uint32_t n) {
if (u < n && v < n && u < v) { if (u < n && v < n && u < v) {
unsigned int index = (u * (2*n - u - 1) / 2) + (v - u - 1); uint64_t uu = (uint64_t)(u);
if (index < (n * (n - 1)) / 2) { uint64_t vv = (uint64_t)(v);
return index; uint64_t nn = (uint64_t)(n);
uint64_t mmax = (nn * (nn - 1)) / 2;
uint64_t index = (uu * (2*nn - uu - 1))/2 + (vv - uu - 1);
if (index < mmax) {
return (uint64_t)index;
} else { } else {
fprintf(stderr, "Error: Formula should be checked for index calculation.\n"); fprintf(stderr, "Error: Formula should be checked for index calculation.\n");
return (unsigned int)-1; return (uint64_t)(-1);
} }
} }
fprintf(stderr, "Error: Invalid u or v values.\n"); fprintf(stderr, "Error: Invalid u or v values.\n");
return (unsigned int)(-1); return (uint64_t)(-1);
} }
int index2uv(unsigned int index, unsigned int n, int *u, int *v) { int8_t index2uv(uint64_t index, uint32_t n, uint32_t *u, uint32_t *v) {
if (index < (n * (n - 1)) / 2) { if (index < (n * (n - 1)) / 2) {
long long nn = (long long)n; int64_t nn = (int64_t)n;
long long indexx = (long long)index; int64_t indexx = (int64_t)index;
long long dd = (2 * nn - 1) * (2 * nn - 1) - 8 * indexx; int64_t dd = (2 * nn - 1) * (2 * nn - 1) - 8 * indexx;
double uur = ((double)(2 * n - 1) - sqrt(dd)) / 2; // double uur = ((double)(2 * n - 1) - sqrt(dd)) / 2;
long long uu = ((double)(2 * n - 1) - sqrt(dd)) / 2; int64_t uu = ((double)(2 * n - 1) - sqrt(dd)) / 2;
long long vv = uu + index + 1 - uu * (2*n - uu - 1) / 2; int64_t vv = uu + index + 1 - uu * (2*n - uu - 1) / 2;
if (uu >= 0 && uu < n && vv >= uu + 1 && vv < n) { if (uu >= 0 && uu < n && vv >= uu + 1 && vv < n) {
*u = (unsigned int)uu; *u = (uint32_t)uu;
*v = (unsigned int)vv; *v = (uint32_t)vv;
return 0; return 0;
} else { } else {
printf("n: %lld\n", nn); // printf("n: %lu\n", nn);
printf("index: %lld\n", indexx); // printf("index: %lu\n", indexx);
printf("D: %lld\n", dd); // printf("D: %d\n", dd);
printf("u: %.10f\n", uur); // printf("u: %.10f\n", uur);
fprintf(stderr, "Error: Invalid calculated u or v values. Index: %d, u = %lld, v=%lld\n", index, uu, vv); // fprintf(stderr, "Error: Invalid calculated u or v values. Index: %d, u = %d, v=%d\n", index, uu, vv);
return -1; return -1;
} }
} }
@ -52,83 +62,96 @@ int index2uv(unsigned int index, unsigned int n, int *u, int *v) {
return -1; return -1;
} }
void random_spanning_tree( void random_connected_graph(
unsigned int n, unsigned int m, unsigned int seed, Edge *edges) { uint32_t n, uint64_t m, Edge *edges, uint16_t* seed) {
if (m > n * (n - 1) / 2) { if (m > n * (n - 1) / 2) {
fprintf(stderr, "Error: Number of edges exceeds the maximum possible for %u vertices.\n", n); fprintf(stderr, "Error: Number of edges exceeds the maximum possible for %u vertices.\n", n);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
unsigned int mmax = n * (n - 1) / 2; // Maximum possible number of edges uint64_t mmax = (uint64_t)n * ((uint64_t)n - 1) / 2; // Maximum possible number of edges
unsigned int *N = malloc(n * sizeof(unsigned int)); // Vertices array uint32_t *N = malloc(n * sizeof(uint32_t)); // Vertices array
unsigned int *M = malloc(mmax * sizeof(unsigned int)); // All edge indices uint64_t *M = malloc(mmax * sizeof(uint64_t)); // All edge indices
unsigned int *T = malloc(m * sizeof(unsigned int)); // Selected edges for the graph uint64_t *T = malloc(m * sizeof(uint64_t)); // Selected edges for the graph
if (!N || !M || !T) { if (!N || !M || !T) {
fprintf(stderr, "Error: Memory allocation failed.\n"); fprintf(stderr, "Error: Memory allocation of arrays N, M or T failed.\n");
free(N); free(M); free(T); free(T);
exit(EXIT_FAILURE); free(M);
free(N);
exit(EXIT_FAILURE);
} }
// Initialize vertex and edge index arrays // Initialize vertex and edge index arrays
for (unsigned int i = 0; i < n; i++) N[i] = i; for (uint32_t i = 0; i < n; i++) N[i] = i;
for (unsigned int i = 0; i < mmax; i++) M[i] = i; for (uint64_t i = 0; i < mmax; i++) M[i] = i;
// Seed random number generator and shuffle vertices // Seed random number generator and shuffle vertices
srand(seed); for (uint32_t i = n - 1; i > 0; i--) {
for (unsigned int i = n - 1; i > 0; i--) { uint32_t j = rand_r_large(seed) % (i + 1);
unsigned int j = rand() % (i + 1); uint32_t temp = N[i];
unsigned int temp = N[i];
N[i] = N[j]; N[i] = N[j];
N[j] = temp; N[j] = temp;
} }
// Build spanning tree by randomly selecting edges // Build spanning tree by randomly selecting edges
for (unsigned int v = 1; v < n; v++) { for (uint32_t v = 1; v < n; v++) {
unsigned int u = rand() % v; uint32_t u = rand_r_large(seed) % v;
unsigned int index = uv2index(min(N[u],N[v]), max(N[u],N[v]), n); uint64_t index = uv2index(min(N[u],N[v]), max(N[u],N[v]), n);
if (index == (unsigned int)-1) { if (index == (uint64_t)(-1)) {
free(N); free(M); free(T); free(T);
free(M);
free(N);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (index >= mmax){
fprintf(stderr, "u = %u; v = %u", u, v);
fprintf(stderr, "index = %lu; mmax = %lu", index, mmax);
}
T[v - 1] = index; // Add edge index to T T[v - 1] = index; // Add edge index to T
} }
// Sort the initial edges of the spanning tree // Sort the initial edges of the spanning tree
qsort(T, n - 1, sizeof(unsigned int), cmpInt); qsort(T, n - 1, sizeof(uint64_t), cmpInt);
// put all selected edges back to the array (last n-1 elements of M) // put all selected edges back to the array (last n-1 elements of M)
for (int i = n-2; i >= 0; i--) { for (int64_t i = n-2; i >= 0; i--) {
unsigned int temp = M[mmax - 1 - n + 2 + i]; if (T[i] > mmax){
fprintf(stderr, "T[i] = %lu; mmax = %lu", T[i], mmax);
}
uint32_t temp = M[mmax - 1 - n + 2 + i];
M[mmax - 1 - n + 2 + i] = M[T[i]]; M[mmax - 1 - n + 2 + i] = M[T[i]];
M[T[i]] = temp; M[T[i]] = temp;
} }
// Randomly shuffle remaining edges in M[0,...,mmax - n] // Randomly shuffle remaining edges in M[0,...,mmax - n]
for (unsigned int i = mmax - n; i > 0; i--) { for (int64_t i = mmax - n; i > 0; i--) {
unsigned int j = rand() % (i + 1); uint32_t j = rand_r_large(seed) % (i + 1);
unsigned int temp = M[i]; uint32_t temp = M[i];
M[i] = M[j]; M[i] = M[j];
M[j] = temp; M[j] = temp;
} }
// Select the first m - n + 1 additional edges // Select the first m - n + 1 additional edges
for (unsigned int i = 0; i < m - n + 1; i++) { for (uint64_t i = 0; i < m - n + 1; i++) {
T[n - 1 + i] = M[i]; T[n - 1 + i] = M[i];
} }
// Sort the entire T array // Sort the entire T array
qsort(T, m, sizeof(unsigned int), cmpInt); qsort(T, m, sizeof(uint64_t), cmpInt);
// Convert indices to edges and create the edge array // Convert indices to edges and create the edge array
unsigned int check = m; uint64_t check = m;
for (unsigned int i = 0; i < m; i++) { for (uint64_t i = 0; i < m; i++) {
int u, v; uint32_t u, v;
if (index2uv(T[i], n, &u, &v) == -1) { if (index2uv(T[i], n, &u, &v) == -1) {
free(N); free(M); free(T); free(edges); free(T);
free(M);
free(N);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (T[i] == check){ if (T[i] == check){
@ -144,7 +167,7 @@ void random_spanning_tree(
// Output edges // Output edges
// Cleanup // Cleanup
free(N);
free(M);
free(T); free(T);
free(M);
free(N);
} }

131
src/random_group_steiner.c Normal file
View File

@ -0,0 +1,131 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "random_graph.h"
#include "random_groups.h"
#include "random_edge_weight.h"
#include "random_vertex_weight.h"
void generate_random_group_steiner_instance(
uint32_t n, uint32_t m, uint16_t k, const char *filename,
float vertex_a, float vertex_b, const char *vertex_weight_type,
float edge_a, float edge_b, const char *edge_weight_family, const char *edge_weight_type, const char *instance_type, uint16_t* seed) {
// Open file for writing
FILE *file = fopen(filename, "w");
if (!file) {
fprintf(stderr, "Error: Could not open file %s for writing.\n", filename);
exit(EXIT_FAILURE);
}
// Generate a random connected graph
Edge *edges = (Edge *)malloc(m * sizeof(Edge));
if (!edges) {
fprintf(stderr, "Error: Memory allocation failed for edges.\n");
fclose(file);
exit(EXIT_FAILURE);
}
// uint64_t mmax = (uint64_t)(n * (n - 1) / 2);
random_connected_graph(n, m, edges, seed);
// Embed vertices into 2D space for geometry-based edge weights
float *x = (float *)malloc(n * sizeof(float));
if (!x) {
fprintf(stderr, "Error: Memory allocation failed for array x.\n");
free(edges);
fclose(file);
exit(EXIT_FAILURE);
}
float *y = (float *)malloc(n * sizeof(float));
if (!y) {
fprintf(stderr, "Error: Memory allocation failed for array y.\n");
free(x);
free(edges);
fclose(file);
exit(EXIT_FAILURE);
}
embed_vertices(n, 100.0, x, y, seed); // Embedding vertices into [0, 100] space
// Allocate memory for groups
Group *groups = (Group *)malloc(k * sizeof(Group));
if (!groups) {
fprintf(stderr, "Error: Memory allocation failed for groups.\n");
free(y);
free(x);
free(edges);
exit(EXIT_FAILURE);
}
for (unsigned int i = 0; i < k; i++) {
groups[i].group = (uint32_t *)malloc(n * sizeof(uint32_t));
groups[i].size = 0;
if (!groups[i].group) {
fprintf(stderr, "Error: Memory allocation failed for group %u.\n", i);
for (unsigned int j = 0; j < i; j++) {
free(groups[j].group);
}
free(groups);
free(y);
free(x);
free(edges);
exit(EXIT_FAILURE);
}
}
// Generate random groups
generate_random_groups(n, k, groups, seed);
// Write the .stp file header
fprintf(file, "0 string 33D32945 STP Steiner Tree Problem File\n");
fprintf(file, "SECTION Comment\n");
fprintf(file, "Name DWW_NWGST_%s_N=%u_M=%u_k=%u\n",edge_weight_family,n,m,k);
fprintf(file, "Remark '%s'\n",instance_type);
fprintf(file, "END\n\n");
// Write the graph section
fprintf(file, "SECTION Graph\n");
fprintf(file, "Nodes %u\n", n);
fprintf(file, "Edges %u\n", m);
// Write vertex weights
for (unsigned int i = 0; i < n; i++) {
float vertex_weight = generate_random_vertex_weight(vertex_weight_type, vertex_a, vertex_b, seed);
fprintf(file, "N %.1f\n", vertex_weight);
}
// Write edges
for (unsigned int i = 0; i < m; i++) {
float edge_weight = generate_random_edge_weight(
x, y, n, edges[i].src, edges[i].dest, edge_a, edge_b, edge_weight_family, edge_weight_type, seed);
fprintf(file, "E %d %d %.2f\n", edges[i].src, edges[i].dest, edge_weight);
}
fprintf(file, "END\n\n");
// Write the terminals section
fprintf(file, "SECTION Terminals\n");
fprintf(file, "Terminals %u\n", k);
for (unsigned int i = 0; i < k; i++) {
fprintf(file, "T");
for (unsigned int j = 0; j < groups[i].size; j++) {
fprintf(file, " %u", groups[i].group[j]);
}
fprintf(file, "\n");
}
fprintf(file, "END\n\n");
// Write EOF
fprintf(file, "EOF\n");
// Clean up
for (unsigned int i = 0; i < k; i++) {
free(groups[i].group);
}
free(groups);
free(y);
free(x);
free(edges);
fclose(file);
}

View File

@ -2,86 +2,80 @@
#include "random_graph.h" #include "random_graph.h"
// Helper function to shuffle an array // Helper function to shuffle an array
void shuffle(unsigned int *array, unsigned int size) { void shuffle(uint32_t *array, uint32_t size, uint16_t* seed) {
for (unsigned int i = size - 1; i > 0; i--) { for (uint32_t i = size - 1; i > 0; i--) {
unsigned int j = rand() % (i + 1); uint32_t j = rand_r((unsigned int* )seed) % (i + 1);
unsigned int temp = array[i]; uint32_t temp = array[i];
array[i] = array[j]; array[i] = array[j];
array[j] = temp; array[j] = temp;
} }
} }
void generate_random_groups(unsigned int n, unsigned int k, Group **groups_out) { void generate_random_groups(uint32_t n, uint16_t k, Group *groups, uint16_t* seed) {
if (k > n) { if (k > n) {
fprintf(stderr, "Error: Number of groups (k) cannot exceed the number of vertices (n).\n"); fprintf(stderr, "Error: Number of groups (k) cannot exceed the number of vertices (n).\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Allocate memory for array N (vertices) and initialize // Allocate memory for array N (vertices) and initialize
unsigned int *N = (unsigned int *)malloc(n * sizeof(unsigned int)); uint32_t *N = (uint32_t *)malloc(n * sizeof(uint32_t));
if (!N) { if (!N) {
fprintf(stderr, "Error: Memory allocation failed for array N.\n"); fprintf(stderr, "Error: Memory allocation failed for array N.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (unsigned int i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
N[i] = i; N[i] = i;
} }
// Allocate memory for groups
Group *groups = (Group *)malloc(k * sizeof(Group));
if (!groups) {
fprintf(stderr, "Error: Memory allocation failed for groups.\n");
free(N);
exit(EXIT_FAILURE);
}
for (unsigned int i = 0; i < k; i++) {
groups[i].group = (unsigned int *)malloc(n * sizeof(unsigned int));
groups[i].size = 0;
if (!groups[i].group) {
fprintf(stderr, "Error: Memory allocation failed for group %u.\n", i);
for (unsigned int j = 0; j < i; j++) {
free(groups[j].group);
}
free(groups);
free(N);
exit(EXIT_FAILURE);
}
}
// Generate a random float f in the range (0, 0.5) // Generate a random float f in the range (0, 0.5)
float f; float f;
do { f = (float) ( rand_r((unsigned int* )seed) / 2.0 ) / RAND_MAX;
f = (float)rand() / RAND_MAX;
} while (f <= 0.0 || f >= 0.5);
unsigned int offset = (unsigned int)(f * n);
uint32_t offset = (uint32_t)(f * n);
// Shuffle the array N // Shuffle the array N
shuffle(N, n); shuffle(N, n, seed);
if (offset + k > n) {
fprintf(stderr, "Error: Number of Steiner vertices (%d) plus k (%d) is greather than n (%d). \n", offset, k, n);
free(N);
exit(EXIT_FAILURE);
}
uint32_t npool = n - offset - k;
uint32_t *I = (uint32_t *)malloc( npool* sizeof(uint32_t));
if (!I) {
fprintf(stderr, "Error: Memory allocation failed for array I.\n");
free(N);
exit(EXIT_FAILURE);
}
for (uint32_t i = 0; i < npool; i++) {
I[i] = i;
}
// Distribute elements to the first part of each group // Distribute elements to the first part of each group
for (unsigned int i = 0; i < k; i++) { for (uint32_t i = 0; i < k; i++) {
groups[i].group[groups[i].size++] = N[offset + i]; groups[i].group[groups[i].size++] = N[offset + i];
} }
// Distribute remaining elements to groups uint32_t total = (n - offset) / k - 1;
for (unsigned int i = 0; i < k; i++) { for (uint32_t i = 0; i < k; i++) {
unsigned int start = offset + k;
unsigned int end = offset + k + (n - offset) / k - 1; shuffle(I,npool,seed);
shuffle(N + start, end - start + 1); for (uint32_t j = 0; j < total; j++) {
groups[i].group[groups[i].size++] = N[offset + k + I[j]];
for (unsigned int j = start; j <= end; j++) {
groups[i].group[groups[i].size++] = N[j];
} }
} }
// Sort each group // Sort each group
for (unsigned int i = 0; i < k; i++) { for (uint32_t i = 0; i < k; i++) {
qsort(groups[i].group, groups[i].size, sizeof(unsigned int), cmpInt); qsort(groups[i].group, groups[i].size, sizeof(uint32_t), cmpInt);
} }
// Clean up // Clean up
free(I);
free(N); free(N);
*groups_out = groups;
} }

View File

@ -0,0 +1,20 @@
#include "random_vertex_weight.h"
#include <stdio.h>
float generate_random_vertex_weight(const char *weight_type, float a, float b, uint16_t* seed) {
if (a > b) {
fprintf(stderr, "Error: Lower bound 'a' cannot be greater than upper bound 'b'.\n");
exit(EXIT_FAILURE);
}
float random_value = 1 + a + ((float)rand_r((unsigned int* )seed) / RAND_MAX) * (b - a);
// Check the weight type and cast appropriately
if (strcmp(weight_type, "integer") == 0) {
return (float)((int)random_value);
} else if (strcmp(weight_type, "float") == 0) {
return random_value;
} else {
fprintf(stderr, "Error: Invalid weight type '%s'. Use 'integer' or 'float'.\n", weight_type);
exit(EXIT_FAILURE);
}
}