This commit is contained in:
Слободан Јелић 2024-11-25 12:10:39 +01:00
parent 5eae375113
commit 237d4461bc
13 changed files with 180355 additions and 0 deletions

View File

@ -0,0 +1,18 @@
{
"name": "STEINGEN",
"containerUser": "root",
"workspaceFolder": "/steingen",
"dockerComposeFile": "../compose.yaml",
"service": "steingen",
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.makefile-tools",
"george-alisson.html-preview-vscode"
]
}
},
"shutdownAction": "stopCompose"
}

16
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include"
],
"defines": [],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Steiner Tree generator",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/main",
// "args": ["${workspaceFolder}/examples/158_RANDOM_n=800_m=159800_k=28_B=10.stp"],
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"random_graph.h": "c"
}
}

26
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build Program",
"type": "shell",
"command": "make",
"args": [],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": ["$gcc"],
"detail": "Build the project using Makefile"
},
{
"label": "Clean Build",
"type": "shell",
"command": "make",
"args": ["clean"],
"group": "build",
"problemMatcher": []
}
]
}

43
Makefile Normal file
View File

@ -0,0 +1,43 @@
# Compiler and Flags
CC = gcc
# CFLAGS = -Wall -Wextra -Iinclude -g -pg
CFLAGS = -O2 -march=native -DNDEBUG -Wall -Wextra -Werror -Iinclude
LDFLAGS = -lm
# Directories
SRC_DIR = src
INCLUDE_DIR = include
BUILD_DIR = build
# Source and Object Files
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
OBJ_FILES = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC_FILES))
# Binaries
MAIN_BIN = $(BUILD_DIR)/main
# Targets
all: $(MAIN_BIN)
# Main Program
$(MAIN_BIN): $(OBJ_FILES) | $(BUILD_DIR)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
$(CC) $(CFLAGS) -c $< -o $@
# Create Build Directories
$(BUILD_DIR):
mkdir -p $@
# Generate docs
docs:
doxygen Doxyfile
# Clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: all tests clean run-tests

19
compose.yaml Normal file
View File

@ -0,0 +1,19 @@
version: '3'
name: steingen
services:
steingen:
build:
context: .
dockerfile: gcc.dockerfile
container_name: steingen
volumes:
- steingen-volume:/steingen
- .:/steingen
- /var/run/docker.sock:/var/run/docker.sock
# environment:
# - NODE_ENV=development
user: root
command: sleep infinity
volumes:
steingen-volume:

80001
example.txt Normal file

File diff suppressed because it is too large Load Diff

100001
example2.txt Normal file

File diff suppressed because it is too large Load Diff

14
gcc.dockerfile Normal file
View File

@ -0,0 +1,14 @@
# Use a base image with Debian
FROM debian:latest
# Install gcc, gdb, make, and other necessary tools
RUN apt-get update && apt-get install -y \
gcc \
gdb \
make \
doxygen \
valgrind \
&& apt-get clean
RUN ulimit -s unlimited
# Set working directory within the container
WORKDIR /steingen

22
include/random_graph.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef RANDOM_GRAPH_H
#define RANDOM_GRAPH_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Edge structure
typedef struct Edge {
int src;
int dest;
} Edge;
// Function prototypes
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);
#endif // RANDOM_GRAPH_H

22
src/main.c Normal file
View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include "random_graph.h"
int main() {
unsigned int n = 60000, m = 150000, seed = 0;
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);
}
free(edges);
return 0;
}

142
src/random_graph.c Normal file
View File

@ -0,0 +1,142 @@
#include "random_graph.h"
int cmpInt(const void *a, const void *b) {
return (*(unsigned int *)a - *(unsigned int *)b);
}
inline unsigned int min(unsigned int u, unsigned int v){
return u < v ? u : v;
}
inline unsigned int max(unsigned int u, unsigned int v){
return u < v ? v : u;
}
unsigned int uv2index(unsigned int u, unsigned int v, unsigned int 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;
} else {
fprintf(stderr, "Error: Formula should be checked for index calculation.\n");
return (unsigned int)-1;
}
}
fprintf(stderr, "Error: Invalid u or v values.\n");
return (unsigned int)(-1);
}
int index2uv(unsigned int index, unsigned int n, int *u, int *v) {
if (index < (n * (n - 1)) / 2) {
long long uu = (2 * n - 1 - sqrt((2 * n - 1) * (2 * n - 1) - 8 * index)) / 2;
long long 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;
return 0;
} else {
fprintf(stderr, "Error: Invalid calculated u or v values. Index: %d, u = %lld, v=%lld\n", index, uu, vv);
return -1;
}
}
fprintf(stderr, "Error: Invalid edge index. Must be less than n(n-1)/2.\n");
return -1;
}
void random_spanning_tree(
unsigned int n, unsigned int m, unsigned int seed, Edge *edges) {
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
if (!N || !M || !T) {
fprintf(stderr, "Error: Memory allocation failed.\n");
free(N); free(M); free(T);
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;
// 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];
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);
exit(EXIT_FAILURE);
}
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);
// 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];
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];
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++) {
T[n - 1 + i] = M[i];
}
// Sort the entire T array
qsort(T, m, sizeof(unsigned int), 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;
if (index2uv(T[i], n, &u, &v) == -1) {
free(N); free(M); free(T); free(edges);
exit(EXIT_FAILURE);
}
if (T[i] == check){
fprintf(stderr, "Error: Duplicated edge (%d - %d) found.\n", u, v);
exit(EXIT_FAILURE);
}
check = T[i];
edges[i].src = u;
edges[i].dest = v;
}
// Output edges
// Cleanup
free(N);
free(M);
free(T);
}