initial
This commit is contained in:
parent
5eae375113
commit
237d4461bc
18
.devcontainer/devcontainer.json
Normal file
18
.devcontainer/devcontainer.json
Normal 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
16
.vscode/c_cpp_properties.json
vendored
Normal 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
26
.vscode/launch.json
vendored
Normal 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
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"random_graph.h": "c"
|
||||
}
|
||||
}
|
26
.vscode/tasks.json
vendored
Normal file
26
.vscode/tasks.json
vendored
Normal 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
43
Makefile
Normal 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
19
compose.yaml
Normal 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
80001
example.txt
Normal file
File diff suppressed because it is too large
Load Diff
100001
example2.txt
Normal file
100001
example2.txt
Normal file
File diff suppressed because it is too large
Load Diff
14
gcc.dockerfile
Normal file
14
gcc.dockerfile
Normal 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
22
include/random_graph.h
Normal 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
22
src/main.c
Normal 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
142
src/random_graph.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user