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": [],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4

View File

@ -1,6 +1,11 @@
{
"files.associations": {
"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
CC = gcc
# CFLAGS = -Wall -Wextra -Iinclude -g -pg
CFLAGS = -O2 -march=native -DNDEBUG -Wall -Wextra -Werror -Iinclude
LDFLAGS = -lm
CFLAGS = -Wall -Wextra -Iinclude -g -pg -O0
# CFLAGS = -O3 -march=native -DNDEBUG -Wall -Wextra -Werror -Iinclude -s -flto -fno-math-errno
LDFLAGS = -lm -flto
# Directories
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
user: root
command: sleep infinity
volumes:
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 <stdlib.h>
#include <math.h>
#include <stdint.h>
#include "rand_large.h"
// Edge structure
typedef struct Edge {
int src;
int dest;
uint32_t src;
uint32_t dest;
} Edge;
// Function prototypes
int cmpInt(const void *a, const void *b);
unsigned int uv2index(unsigned int u, unsigned int v, unsigned int n);
unsigned int min(unsigned int u, unsigned int v);
unsigned int max(unsigned int u, unsigned int v);
int index2uv(unsigned int index, unsigned int n, int *u, int *v);
void random_spanning_tree(
unsigned int n, unsigned int m, unsigned int seed, Edge *edges);
uint64_t uv2index(uint32_t u, uint32_t v, uint32_t n);
uint32_t min(uint32_t u, uint32_t v);
uint32_t max(uint32_t u, uint32_t v);
int8_t index2uv(uint64_t index, uint32_t n, uint32_t *u, uint32_t *v);
void random_connected_graph(
uint32_t n, uint64_t m, Edge *edges, uint16_t* seed);
#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 <stdio.h>
#include <stdint.h>
// Struct for representing groups
typedef struct {
unsigned int *group; // Pointer to an array of group members
unsigned int size; // Number of members in the group
uint32_t *group; // Pointer to an array of group members
uint32_t size; // Number of members in the group
} Group;
// 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

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

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"
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;
}
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;
}
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) {
unsigned int index = (u * (2*n - u - 1) / 2) + (v - u - 1);
if (index < (n * (n - 1)) / 2) {
return index;
uint64_t uu = (uint64_t)(u);
uint64_t vv = (uint64_t)(v);
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 {
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");
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) {
long long nn = (long long)n;
long long indexx = (long long)index;
long long dd = (2 * nn - 1) * (2 * nn - 1) - 8 * indexx;
double uur = ((double)(2 * n - 1) - sqrt(dd)) / 2;
long long uu = ((double)(2 * n - 1) - sqrt(dd)) / 2;
long long vv = uu + index + 1 - uu * (2*n - uu - 1) / 2;
int64_t nn = (int64_t)n;
int64_t indexx = (int64_t)index;
int64_t dd = (2 * nn - 1) * (2 * nn - 1) - 8 * indexx;
// double uur = ((double)(2 * n - 1) - sqrt(dd)) / 2;
int64_t uu = ((double)(2 * n - 1) - sqrt(dd)) / 2;
int64_t vv = uu + index + 1 - uu * (2*n - uu - 1) / 2;
if (uu >= 0 && uu < n && vv >= uu + 1 && vv < n) {
*u = (unsigned int)uu;
*v = (unsigned int)vv;
*u = (uint32_t)uu;
*v = (uint32_t)vv;
return 0;
} else {
printf("n: %lld\n", nn);
printf("index: %lld\n", indexx);
printf("D: %lld\n", dd);
printf("u: %.10f\n", uur);
fprintf(stderr, "Error: Invalid calculated u or v values. Index: %d, u = %lld, v=%lld\n", index, uu, vv);
// printf("n: %lu\n", nn);
// printf("index: %lu\n", indexx);
// printf("D: %d\n", dd);
// printf("u: %.10f\n", uur);
// fprintf(stderr, "Error: Invalid calculated u or v values. Index: %d, u = %d, v=%d\n", index, uu, vv);
return -1;
}
}
@ -52,83 +62,96 @@ int index2uv(unsigned int index, unsigned int n, int *u, int *v) {
return -1;
}
void random_spanning_tree(
unsigned int n, unsigned int m, unsigned int seed, Edge *edges) {
void random_connected_graph(
uint32_t n, uint64_t m, Edge *edges, uint16_t* seed) {
if (m > n * (n - 1) / 2) {
fprintf(stderr, "Error: Number of edges exceeds the maximum possible for %u vertices.\n", n);
exit(EXIT_FAILURE);
}
unsigned int mmax = n * (n - 1) / 2; // Maximum possible number of edges
unsigned int *N = malloc(n * sizeof(unsigned int)); // Vertices array
unsigned int *M = malloc(mmax * sizeof(unsigned int)); // All edge indices
unsigned int *T = malloc(m * sizeof(unsigned int)); // Selected edges for the graph
uint64_t mmax = (uint64_t)n * ((uint64_t)n - 1) / 2; // Maximum possible number of edges
uint32_t *N = malloc(n * sizeof(uint32_t)); // Vertices array
uint64_t *M = malloc(mmax * sizeof(uint64_t)); // All edge indices
uint64_t *T = malloc(m * sizeof(uint64_t)); // Selected edges for the graph
if (!N || !M || !T) {
fprintf(stderr, "Error: Memory allocation failed.\n");
free(N); free(M); free(T);
exit(EXIT_FAILURE);
fprintf(stderr, "Error: Memory allocation of arrays N, M or T failed.\n");
free(T);
free(M);
free(N);
exit(EXIT_FAILURE);
}
// Initialize vertex and edge index arrays
for (unsigned int i = 0; i < n; i++) N[i] = i;
for (unsigned int i = 0; i < mmax; i++) M[i] = i;
for (uint32_t i = 0; i < n; i++) N[i] = i;
for (uint64_t i = 0; i < mmax; i++) M[i] = i;
// Seed random number generator and shuffle vertices
srand(seed);
for (unsigned int i = n - 1; i > 0; i--) {
unsigned int j = rand() % (i + 1);
unsigned int temp = N[i];
for (uint32_t i = n - 1; i > 0; i--) {
uint32_t j = rand_r_large(seed) % (i + 1);
uint32_t temp = N[i];
N[i] = N[j];
N[j] = temp;
}
// Build spanning tree by randomly selecting edges
for (unsigned int v = 1; v < n; v++) {
unsigned int u = rand() % v;
unsigned int index = uv2index(min(N[u],N[v]), max(N[u],N[v]), n);
if (index == (unsigned int)-1) {
free(N); free(M); free(T);
for (uint32_t v = 1; v < n; v++) {
uint32_t u = rand_r_large(seed) % v;
uint64_t index = uv2index(min(N[u],N[v]), max(N[u],N[v]), n);
if (index == (uint64_t)(-1)) {
free(T);
free(M);
free(N);
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
}
// 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)
for (int i = n-2; i >= 0; i--) {
unsigned int temp = M[mmax - 1 - n + 2 + i];
for (int64_t i = n-2; i >= 0; 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[T[i]] = temp;
}
// Randomly shuffle remaining edges in M[0,...,mmax - n]
for (unsigned int i = mmax - n; i > 0; i--) {
unsigned int j = rand() % (i + 1);
unsigned int temp = M[i];
for (int64_t i = mmax - n; i > 0; i--) {
uint32_t j = rand_r_large(seed) % (i + 1);
uint32_t temp = M[i];
M[i] = M[j];
M[j] = temp;
}
// 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];
}
// 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
unsigned int check = m;
for (unsigned int i = 0; i < m; i++) {
int u, v;
uint64_t check = m;
for (uint64_t i = 0; i < m; i++) {
uint32_t u, v;
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);
}
if (T[i] == check){
@ -144,7 +167,7 @@ void random_spanning_tree(
// Output edges
// Cleanup
free(N);
free(M);
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"
// Helper function to shuffle an array
void shuffle(unsigned int *array, unsigned int size) {
for (unsigned int i = size - 1; i > 0; i--) {
unsigned int j = rand() % (i + 1);
unsigned int temp = array[i];
void shuffle(uint32_t *array, uint32_t size, uint16_t* seed) {
for (uint32_t i = size - 1; i > 0; i--) {
uint32_t j = rand_r((unsigned int* )seed) % (i + 1);
uint32_t temp = array[i];
array[i] = array[j];
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) {
fprintf(stderr, "Error: Number of groups (k) cannot exceed the number of vertices (n).\n");
exit(EXIT_FAILURE);
}
// 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) {
fprintf(stderr, "Error: Memory allocation failed for array N.\n");
exit(EXIT_FAILURE);
}
for (unsigned int i = 0; i < n; i++) {
for (uint32_t i = 0; i < n; 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)
float f;
do {
f = (float)rand() / RAND_MAX;
} while (f <= 0.0 || f >= 0.5);
f = (float) ( rand_r((unsigned int* )seed) / 2.0 ) / RAND_MAX;
unsigned int offset = (unsigned int)(f * n);
uint32_t offset = (uint32_t)(f * 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
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];
}
// Distribute remaining elements to groups
for (unsigned int i = 0; i < k; i++) {
unsigned int start = offset + k;
unsigned int end = offset + k + (n - offset) / k - 1;
shuffle(N + start, end - start + 1);
for (unsigned int j = start; j <= end; j++) {
groups[i].group[groups[i].size++] = N[j];
uint32_t total = (n - offset) / k - 1;
for (uint32_t i = 0; i < k; i++) {
shuffle(I,npool,seed);
for (uint32_t j = 0; j < total; j++) {
groups[i].group[groups[i].size++] = N[offset + k + I[j]];
}
}
// Sort each group
for (unsigned int i = 0; i < k; i++) {
qsort(groups[i].group, groups[i].size, sizeof(unsigned int), cmpInt);
for (uint32_t i = 0; i < k; i++) {
qsort(groups[i].group, groups[i].size, sizeof(uint32_t), cmpInt);
}
// Clean up
free(I);
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);
}
}