Compare commits
10 Commits
9180586d50
...
878470fe73
| Author | SHA1 | Date | |
|---|---|---|---|
| 878470fe73 | |||
| 12eb1d34a4 | |||
| b1a07ddc26 | |||
| 15a95c8e73 | |||
| 899c844c78 | |||
| aae0ce7241 | |||
| 93311c4ad5 | |||
| e45091b066 | |||
| b14156589c | |||
| 1c8ab00c13 |
+5
-1
@@ -1 +1,5 @@
|
||||
benchmarks/**
|
||||
benchmark
|
||||
.direnv
|
||||
*.csv
|
||||
*.png
|
||||
*.txt
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
benchmarks/**
|
||||
dist/**
|
||||
results.txt
|
||||
@@ -7,6 +7,8 @@ def run_benchmark(program_name, array):
|
||||
start = time()
|
||||
process = subprocess.Popen(program_name, stdin=subprocess.PIPE)
|
||||
process.communicate((f"{len(array)}\n" + "\n".join(map(str, array))).encode())
|
||||
if process.returncode == 1:
|
||||
raise RuntimeError("Error while benchmarking")
|
||||
end = time()
|
||||
return end - start
|
||||
|
||||
@@ -25,23 +27,37 @@ def generate_sequence(sequence_type, array_size):
|
||||
raise ValueError("Invalid sequence type")
|
||||
|
||||
def plot(program_name, sequences, array_size):
|
||||
sequence_names = {
|
||||
"random": "Losowy",
|
||||
"sorted": "Posortowany",
|
||||
"reversed": "Odwrócony",
|
||||
"constant": "Stały",
|
||||
"v_shaped": "V-kształtny",
|
||||
}
|
||||
plt.figure(figsize=(10, 6))
|
||||
for sequence_type, timings in sequences.items():
|
||||
plt.plot(array_size, timings, label=sequence_type)
|
||||
plt.xlabel("")
|
||||
plt.plot(array_size, timings, label=sequence_names[sequence_type])
|
||||
plt.xlabel("Rozmiar tablicy")
|
||||
plt.ylabel("Czas (ms)")
|
||||
plt.title(f"{program_name}")
|
||||
plt.title(program_name.capitalize())
|
||||
plt.legend()
|
||||
plt.savefig(f"benchmarks/{program_name}.png")
|
||||
# plt.show()
|
||||
plt.savefig(f"./benchmarks/{program_name}.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
program_names = ["./insertion", "./selection"]
|
||||
program_names = ["insertion", "selection", "heapsort", "mergesort"]
|
||||
sequence_types = ["random", "sorted", "reversed", "constant", "v_shaped"]
|
||||
array_sizes = [i for i in range(1000, 15001, 1000)]
|
||||
tests = 10
|
||||
|
||||
with open("results.txt", "w") as f:
|
||||
for program_name in program_names:
|
||||
if program_name == "heapsort" or program_name == "mergesort":
|
||||
array_sizes = [i for i in range(15000, 40001, 1000)]
|
||||
tests = 20
|
||||
else:
|
||||
array_sizes = [i for i in range(1000, 15001, 1000)]
|
||||
tests = 10
|
||||
|
||||
sequenceTiming = {
|
||||
"random": [],
|
||||
"sorted": [],
|
||||
@@ -54,16 +70,18 @@ if __name__ == "__main__":
|
||||
print(f" - running {sequence_type}")
|
||||
for array_size in array_sizes:
|
||||
sequence = generate_sequence(sequence_type, array_size)
|
||||
print(f" - running {sequence_type} with size {array_size}")
|
||||
durations = []
|
||||
for i in range(10):
|
||||
duration = run_benchmark(program_name, sequence)
|
||||
for i in range(tests):
|
||||
print(f" - running {sequence_type} with size {array_size} {i+1}/{tests}", end="\r")
|
||||
duration = run_benchmark(f"./dist/{program_name}", sequence)
|
||||
duration *= 1000
|
||||
durations.append(duration)
|
||||
sleep(0.1)
|
||||
if program_name == "heapsort" or program_name == "mergesort":
|
||||
sleep(0.1)
|
||||
print()
|
||||
duration = sum(durations) / len(durations)
|
||||
f.write(f"{program_name} {sequence_type} {array_size} {duration}\n")
|
||||
sequenceTiming[sequence_type].append(duration)
|
||||
sleep(0.5)
|
||||
if program_name == "heapsort" or program_name == "mergesort":
|
||||
sleep(0.1)
|
||||
plot(program_name, sequenceTiming, array_sizes)
|
||||
print("Benchmark finished")
|
||||
@@ -4,13 +4,23 @@
|
||||
// Capture the pipe of array contents, first number is the size
|
||||
int main() {
|
||||
int s;
|
||||
scanf("%d", &s);
|
||||
int *array = malloc(sizeof(int) * s);
|
||||
for (int i = 0; i < s; i++) {
|
||||
scanf("%d", &array[i]);
|
||||
int res = scanf("%d", &s);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "Error reading size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int j = 1; j < s; j++) {
|
||||
int *array = malloc(sizeof(int) * s);
|
||||
for (int i = 0; i < s; i++) {
|
||||
res = scanf("%d", &array[i]);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "Error reading array element\n");
|
||||
free(array);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < s; j++) {
|
||||
int key = array[j];
|
||||
int i = j - 1;
|
||||
while (i >= 0 && array[i] > key) {
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void MergeSort(int A[], int l, int r, int B[]) {
|
||||
int m = (l + r) / 2;
|
||||
if (m - l > 0) {
|
||||
MergeSort(A, l, m, B);
|
||||
}
|
||||
|
||||
if (r - m > 0) {
|
||||
MergeSort(A, m + 1, r, B);
|
||||
}
|
||||
|
||||
int i = l;
|
||||
int j = m + 1;
|
||||
for (int k = l; k <= r; k++) {
|
||||
if ((i <= m && j > r) || ((i <= m && j <= r) && A[i] <= A[j])) {
|
||||
B[k] = A[i];
|
||||
i++;
|
||||
} else {
|
||||
B[k] = A[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = l; k <= r; k++) {
|
||||
A[k] = B[k];
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int size;
|
||||
int res = scanf("%d", &size);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "Error reading size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int *arrayA = malloc(sizeof(int) * size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
res = scanf("%d", &arrayA[i]);
|
||||
if (res != 1) {
|
||||
fprintf(stderr, "Error reading array element\n");
|
||||
free(arrayA);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int *arrayB = malloc(sizeof(int) * size);
|
||||
MergeSort(arrayA, 0, size - 1, arrayB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
enum PivotStrategy { RIGHTMOST = 0, MIDDLE = 1, RANDOM = 2 };
|
||||
|
||||
void swap(int *a, int *b) {
|
||||
int temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
int partition(int A[], int left, int right, int pivot_strategy, int length) {
|
||||
int pivot_index;
|
||||
if (pivot_strategy == RIGHTMOST) {
|
||||
pivot_index = right;
|
||||
} else if (pivot_strategy == MIDDLE) {
|
||||
pivot_index = (left + right) / 2;
|
||||
} else if (pivot_strategy == RANDOM) {
|
||||
pivot_index = (rand() % (length + 1));
|
||||
}
|
||||
|
||||
int pivot = A[pivot_index];
|
||||
swap(&A[pivot_index], &A[right]);
|
||||
int i = left - 1;
|
||||
|
||||
for (int j = left; j < right; j++) {
|
||||
if (A[j] <= pivot) {
|
||||
i++;
|
||||
swap(&A[i], &A[j]);
|
||||
}
|
||||
}
|
||||
swap(&A[i + 1], &A[right]);
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void quicksort(int A[], int p, int r, int pivot_strategy, int length) {
|
||||
if (p < r) {
|
||||
int q = partition(A, p, r, pivot_strategy, length);
|
||||
quicksort(A, p, q - 1, pivot_strategy, length);
|
||||
quicksort(A, q + 1, r, pivot_strategy, length);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int size, pivot_strategy;
|
||||
|
||||
if (scanf("%d", &size) != 1) {
|
||||
fprintf(stderr, "Error reading size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (scanf("%d", &pivot_strategy) != 1) {
|
||||
fprintf(stderr, "Error reading pivot strategy\n");
|
||||
return 1;
|
||||
}
|
||||
// Init the random number generator when needed
|
||||
if (pivot_strategy == RANDOM) {
|
||||
srand(size);
|
||||
}
|
||||
|
||||
int *array = malloc(sizeof(int) * size);
|
||||
if (array == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (scanf("%d", &array[i]) != 1) {
|
||||
fprintf(stderr, "Error reading array element\n");
|
||||
free(array);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
quicksort(array, 0, size - 1, pivot_strategy, size);
|
||||
|
||||
free(array);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import subprocess
|
||||
from time import time, sleep
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
pivot_strategies = {
|
||||
"rightmost": 0,
|
||||
"middle": 1,
|
||||
"random": 2
|
||||
}
|
||||
|
||||
def run_benchmark(array, pivot_strategy):
|
||||
input_data = f"{len(array)}\n{pivot_strategies[pivot_strategy]}\n" + "\n".join(map(str, array)) + "\n"
|
||||
|
||||
start = time()
|
||||
process = subprocess.Popen("./dist/quicksort", stdin=subprocess.PIPE)
|
||||
process.communicate(input_data.encode())
|
||||
if process.returncode != 0:
|
||||
raise RuntimeError("Error while benchmarking")
|
||||
end = time()
|
||||
|
||||
return end - start
|
||||
|
||||
def generate_v_shaped(array_size):
|
||||
return [i for i in range(array_size // 2, 0, -1)] + [i for i in range(array_size // 2)]
|
||||
|
||||
def plot(sequences, array_size):
|
||||
pivot_names = {
|
||||
"rightmost": "Pivot prawy",
|
||||
"middle": "Pivot środkowy",
|
||||
"random": "Pivot losowy"
|
||||
}
|
||||
plt.figure(figsize=(10, 6))
|
||||
for pivot_type, timings in sequences.items():
|
||||
plt.plot(array_size, timings, label=pivot_names[pivot_type])
|
||||
plt.xlabel("Rozmiar tablicy")
|
||||
plt.ylabel("Czas (ms)")
|
||||
plt.title("Quicksort")
|
||||
plt.legend()
|
||||
plt.savefig("./benchmarks/quicksort.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
array_sizes = [i for i in range(1000, 15001, 1000)]
|
||||
|
||||
with open("results.txt", "w") as f:
|
||||
sequenceTiming = {
|
||||
"rightmost": [],
|
||||
"middle": [],
|
||||
"random": [],
|
||||
}
|
||||
for pivot_strategy in pivot_strategies:
|
||||
print(f"Running with pivot strategy {pivot_strategy}")
|
||||
for array_size in array_sizes:
|
||||
sequence = generate_v_shaped(array_size)
|
||||
durations = []
|
||||
for i in range(10):
|
||||
print(f" - with size of {array_size} {i+1}/10", end="\r")
|
||||
duration = run_benchmark(sequence, pivot_strategy)
|
||||
duration *= 1000
|
||||
durations.append(duration)
|
||||
sleep(0.1)
|
||||
print()
|
||||
duration = sum(durations) / len(durations)
|
||||
sequenceTiming[pivot_strategy].append(duration)
|
||||
sleep(0.1)
|
||||
plot(sequenceTiming, array_sizes)
|
||||
print("Benchmark finished")
|
||||
@@ -8,6 +8,7 @@ int main() {
|
||||
fprintf(stderr, "Error reading size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int *array = malloc(sizeof(int) * s);
|
||||
for (int i = 0; i < s; i++) {
|
||||
res = scanf("%d", &array[i]);
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "avl.h"
|
||||
#include "algorithm"
|
||||
|
||||
int getHeight(AVL_tree *root) {
|
||||
if (!root)
|
||||
return 0;
|
||||
return root->height;
|
||||
}
|
||||
|
||||
AVL_tree *rightRotate(AVL_tree *y) {
|
||||
AVL_tree *x = y->left;
|
||||
AVL_tree *T2 = x->right;
|
||||
|
||||
x->right = y;
|
||||
y->left = T2;
|
||||
|
||||
y->height = 1 + std::max(getHeight(y->left), getHeight(y->right));
|
||||
x->height = 1 + std::max(getHeight(x->left), getHeight(x->right));
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
AVL_tree *leftRotate(AVL_tree *x) {
|
||||
AVL_tree *y = x->right;
|
||||
AVL_tree *T2 = y->left;
|
||||
|
||||
y->left = x;
|
||||
x->right = T2;
|
||||
|
||||
x->height = 1 + std::max(getHeight(x->left), getHeight(x->right));
|
||||
y->height = 1 + std::max(getHeight(y->left), getHeight(y->right));
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
int getBalance(AVL_tree *root) {
|
||||
if (!root)
|
||||
return 0;
|
||||
return getHeight(root->left) - getHeight(root->right);
|
||||
}
|
||||
|
||||
AVL_tree *insertAVL(AVL_tree *root, int value) {
|
||||
if (root == nullptr) {
|
||||
return new AVL_tree{value, nullptr, nullptr, 1};
|
||||
}
|
||||
|
||||
if (value < root->info) {
|
||||
root->left = insertAVL(root->left, value);
|
||||
} else if (value > root->info) {
|
||||
root->right = insertAVL(root->right, value);
|
||||
} else {
|
||||
return root;
|
||||
}
|
||||
|
||||
root->height = 1 + std::max(getHeight(root->left), getHeight(root->right));
|
||||
|
||||
int balance = getBalance(root);
|
||||
|
||||
if (balance > 1 && value < root->left->info) {
|
||||
return rightRotate(root);
|
||||
}
|
||||
|
||||
if (balance < -1 && value > root->right->info) {
|
||||
return leftRotate(root);
|
||||
}
|
||||
|
||||
if (balance > 1 && value > root->left->info) {
|
||||
root->left = leftRotate(root->left);
|
||||
return rightRotate(root);
|
||||
}
|
||||
|
||||
if (balance < -1 && value < root->right->info) {
|
||||
root->right = rightRotate(root->right);
|
||||
return leftRotate(root);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void deleteAVL(AVL_tree *root){
|
||||
if (root != nullptr) {
|
||||
deleteAVL(root->left);
|
||||
deleteAVL(root->right);
|
||||
delete root;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
struct AVL_tree {
|
||||
int info;
|
||||
AVL_tree *left;
|
||||
AVL_tree *right;
|
||||
int height;
|
||||
};
|
||||
|
||||
int getHeight(AVL_tree *root);
|
||||
AVL_tree *insertAVL(AVL_tree *root, int value);
|
||||
AVL_tree *rotateLeft(AVL_tree *root);
|
||||
AVL_tree *rotateRight(AVL_tree *root);
|
||||
AVL_tree *searchAVL(AVL_tree *root, int value);
|
||||
void deleteAVL(AVL_tree *root);
|
||||
@@ -0,0 +1,178 @@
|
||||
#include "avl/avl.h"
|
||||
#include "bst/bst.h"
|
||||
#include "list/list.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <random>
|
||||
#include <set>
|
||||
|
||||
void measureList(std::vector<int> *sequence, FILE *file) {
|
||||
float buildTime = 0, searchTime = 0, deleteTime = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
std::cout << "- Running list " << i + 1 << "/10\r";
|
||||
fflush(stdout);
|
||||
|
||||
// Measure build time
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
List *head = nullptr;
|
||||
for (int value : *sequence) {
|
||||
head = insert(head, value);
|
||||
}
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||
buildTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
|
||||
// Now we run the search
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
for (int value : *sequence) {
|
||||
search(head, value);
|
||||
}
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
elapsed_seconds = end - start;
|
||||
searchTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
|
||||
// Measure deletion time for list
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
while (head != nullptr) {
|
||||
head = remove(head);
|
||||
}
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
elapsed_seconds = end - start;
|
||||
deleteTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
}
|
||||
|
||||
buildTime /= 10;
|
||||
searchTime /= 10;
|
||||
deleteTime /= 10;
|
||||
|
||||
std::cout << "- List built in " << buildTime << "ms | searched in "
|
||||
<< searchTime << "ms | deleted in " << deleteTime << "ms"
|
||||
<< std::endl;
|
||||
fprintf(file, "List,%f,%f,%f\n", buildTime, searchTime, deleteTime);
|
||||
}
|
||||
|
||||
void measureBST(std::vector<int> *sequence, FILE *file) {
|
||||
float buildTime = 0, searchTime = 0, deleteTime = 0;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
std::cout << "- Running bst " << i + 1 << "/10\r";
|
||||
fflush(stdout);
|
||||
|
||||
// Measure build time
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
Tree *root = nullptr;
|
||||
for (int value : *sequence) {
|
||||
root = insert(root, value);
|
||||
}
|
||||
// root = balance(root);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||
buildTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
|
||||
// Now we run the search
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
for (int value : *sequence) {
|
||||
search(root, value);
|
||||
}
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
elapsed_seconds = end - start;
|
||||
searchTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
|
||||
// Measure deletion time for tree
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
deleteTree(root);
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
elapsed_seconds = end - start;
|
||||
deleteTime += elapsed_seconds.count() * 1000; // Convert to milliseconds
|
||||
}
|
||||
|
||||
buildTime /= 10;
|
||||
searchTime /= 10;
|
||||
deleteTime /= 10;
|
||||
|
||||
std::cout << "- Tree built in " << buildTime << "ms | searched in "
|
||||
<< searchTime << "ms | deleted in " << deleteTime << "ms"
|
||||
<< std::endl;
|
||||
fprintf(file, "BST,%f,%f,%f\n", buildTime, searchTime, deleteTime);
|
||||
}
|
||||
|
||||
void benchmarkAVL(std::vector<int> *sequence, FILE *file) {
|
||||
Tree *bst = nullptr;
|
||||
for (int value : *sequence) {
|
||||
bst = insert(bst, value);
|
||||
}
|
||||
|
||||
int heightBST = getHeight(bst, 0);
|
||||
deleteTree(bst);
|
||||
|
||||
AVL_tree *avl = nullptr;
|
||||
for (int value : *sequence) {
|
||||
avl = insertAVL(avl, value);
|
||||
}
|
||||
|
||||
int heightAVL = getHeight(avl);
|
||||
deleteAVL(avl);
|
||||
|
||||
fprintf(file, "%d,%d\n", heightBST, heightAVL);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Init the random number generator
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<> dis(1, 1000000);
|
||||
|
||||
int mode = 1;
|
||||
std::cout << "Select benchmark to run:\n 1 - Benchmark List vs BST\n 2 - "
|
||||
"Benchmark BST vs AVL"
|
||||
<< std::endl;
|
||||
std::cin >> mode;
|
||||
|
||||
if (mode < 1 && mode > 2) {
|
||||
mode = 1;
|
||||
}
|
||||
|
||||
FILE *file;
|
||||
if (mode == 1) {
|
||||
// Open a file for writing results
|
||||
file = fopen("results.csv", "w");
|
||||
fprintf(file, "Structure,BuildTime,SearchTime,DeleteTime\n");
|
||||
} else {
|
||||
file = fopen("avl.csv", "w");
|
||||
std::fprintf(file, "Structure,Height\n");
|
||||
}
|
||||
|
||||
for (int n = 1; n < 26; n++) {
|
||||
// Using a set here ensures that there are no duplicates
|
||||
std::set<int> sequence;
|
||||
while (sequence.size() < n * 1000) {
|
||||
sequence.insert(dis(gen));
|
||||
}
|
||||
|
||||
std::vector<int> random_sequence_vec;
|
||||
for (int val : sequence) {
|
||||
random_sequence_vec.push_back(val);
|
||||
}
|
||||
|
||||
// Then randomize the sequence so the bst isn't a list (Set keeps the elements in order)
|
||||
std::shuffle(random_sequence_vec.begin(), random_sequence_vec.end(), gen);
|
||||
|
||||
// Display the times like a cascade
|
||||
std::cout << "Running tests for " << n * 1000 << " elements..."
|
||||
<< std::endl;
|
||||
if (mode == 1) {
|
||||
measureList(&random_sequence_vec, file);
|
||||
measureBST(&random_sequence_vec, file);
|
||||
} else {
|
||||
benchmarkAVL(&random_sequence_vec, file);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "bst.h"
|
||||
|
||||
Tree *insert(Tree *root, int value) {
|
||||
if (root == nullptr) {
|
||||
root = new Tree{value, nullptr, nullptr};
|
||||
} else if (value < root->info) {
|
||||
root->left = insert(root->left, value);
|
||||
} else if (value > root->info) {
|
||||
root->right = insert(root->right, value);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
Tree *search(Tree *root, int value) {
|
||||
Tree *ptr = root;
|
||||
while (ptr != nullptr) {
|
||||
if (value > ptr->info)
|
||||
ptr = ptr->right;
|
||||
else if (value < ptr->info)
|
||||
ptr = ptr->left;
|
||||
else
|
||||
return ptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void deleteTree(Tree *root) {
|
||||
if (root != nullptr) {
|
||||
deleteTree(root->left);
|
||||
deleteTree(root->right);
|
||||
delete root;
|
||||
}
|
||||
}
|
||||
|
||||
int getHeight(Tree *root, int height) {
|
||||
if (root == nullptr)
|
||||
return height;
|
||||
height += 1;
|
||||
int leftHeight = getHeight(root->left, height);
|
||||
int rightHeight = getHeight(root->right, height);
|
||||
return std::max(leftHeight, rightHeight) + 1;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <vector>
|
||||
|
||||
struct Tree {
|
||||
int info;
|
||||
Tree *left;
|
||||
Tree *right;
|
||||
};
|
||||
|
||||
Tree *insert(Tree *root, int value);
|
||||
Tree *search(Tree *root, int value);
|
||||
void deleteTree(Tree *root);
|
||||
int getHeight(Tree *root, int height);
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "list.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
List *insert(List *head, int value) {
|
||||
if (head == nullptr) {
|
||||
List *node = new List();
|
||||
node->data = value;
|
||||
node->next = nullptr;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (head->data > value) {
|
||||
List *newHead = new List();
|
||||
newHead->data = value;
|
||||
newHead->next = head;
|
||||
head = newHead;
|
||||
} else {
|
||||
List *tmp = head;
|
||||
while (tmp->next != nullptr && tmp->next->data < value) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
List *tail = new List();
|
||||
tail->data = value;
|
||||
// Set the pointer to the next, we don't know if its at the end or not
|
||||
tail->next = tmp->next;
|
||||
tmp->next = tail;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
List *search(List *list, int value) {
|
||||
List *ptr = list;
|
||||
while (ptr != nullptr && ptr->data != value) {
|
||||
if (ptr->data > value) return nullptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Remove the first element
|
||||
List *remove(List *head) {
|
||||
if (head == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
List *newHead = head->next;
|
||||
delete head;
|
||||
return newHead;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
struct List {
|
||||
int data;
|
||||
List *next;
|
||||
};
|
||||
|
||||
List *insert(List *head, int data);
|
||||
List *search(List *list, int value);
|
||||
List* remove(List *head);
|
||||
@@ -0,0 +1,58 @@
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def plot(header:str, first:list[int], second:list[int], log=False, labels=("Lista", "Drzewo BST"), ylabel= "Czas (ms)"):
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(range(1000,25001,1000), first, label=labels[0])
|
||||
plt.plot(range(1000,25001,1000), second, label=labels[1])
|
||||
plt.xlabel("Rozmiar tablicy")
|
||||
plt.ylabel(ylabel)
|
||||
if log:
|
||||
plt.yscale('log', base=2)
|
||||
plt.title(header)
|
||||
plt.legend()
|
||||
plt.savefig(f"./charts/{header}.png")
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open('results.csv', 'r') as file:
|
||||
data = file.read()
|
||||
lines = data.split('\n')
|
||||
headers = lines[0].split(',')
|
||||
values = [line.split(',') for line in lines[1:]]
|
||||
|
||||
bstTimes = {
|
||||
"build":[],
|
||||
"search":[],
|
||||
"delete":[]
|
||||
}
|
||||
|
||||
listTimes = {
|
||||
"build":[],
|
||||
"search":[],
|
||||
"delete":[]
|
||||
}
|
||||
|
||||
for row in values:
|
||||
if row[0] == 'BST':
|
||||
bstTimes['build'].append(float(row[1]))
|
||||
bstTimes['search'].append(float(row[2]))
|
||||
bstTimes['delete'].append(float(row[3]))
|
||||
elif row[0] == 'List':
|
||||
listTimes['build'].append(float(row[1]))
|
||||
listTimes['search'].append(float(row[2]))
|
||||
listTimes['delete'].append(float(row[3]))
|
||||
|
||||
|
||||
plot("Tworzenie", listTimes['build'], bstTimes['build'], log=True)
|
||||
plot("Wyszukiwanie", listTimes['search'], bstTimes['search'], log=True)
|
||||
plot("Usuwanie", listTimes['delete'], bstTimes['delete'])
|
||||
|
||||
with open("avl.csv", "r") as file:
|
||||
data = file.read()
|
||||
lines = data.split('\n')
|
||||
headers = lines[0].split(',')
|
||||
values = [line.split(',') for line in lines[1:-1]]
|
||||
|
||||
bstHeights = [int(x[0]) for x in values]
|
||||
avlHeights = [int(x[1]) for x in values]
|
||||
|
||||
plot("AVL", bstHeights, avlHeights, log=True, labels=("Drzewo BST", "Drzewo AVL"), ylabel="Wysokość drzewa")
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
import random
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
def generateGraph(n: int, saturation: int):
|
||||
edges = (n * (n - 1)) // 2
|
||||
maxEdges = edges * saturation // 100
|
||||
|
||||
graph = {i: [] for i in range(n)}
|
||||
edgeCount = 0
|
||||
|
||||
# Generate a Hamiltonian cycle
|
||||
cycle = list(range(n))
|
||||
random.shuffle(cycle)
|
||||
for i in range(n):
|
||||
u = cycle[i]
|
||||
v = cycle[(i + 1) % n]
|
||||
graph[u].append(v)
|
||||
graph[v].append(u)
|
||||
edgeCount += 1
|
||||
|
||||
while edgeCount < maxEdges:
|
||||
# Find all pairs (u, v) where u < v, u != v, v not in graph[u], and deg(u)%2 == deg(v)%2
|
||||
candidates = []
|
||||
for u in range(n):
|
||||
for v in range(u + 1, n):
|
||||
if v not in graph[u] and (len(graph[u]) % 2) == (len(graph[v]) % 2):
|
||||
candidates.append((u, v))
|
||||
if not candidates:
|
||||
break # No more valid pairs to add without breaking Eulerian property
|
||||
u, v = random.choice(candidates)
|
||||
graph[u].append(v)
|
||||
graph[v].append(u)
|
||||
edgeCount += 1
|
||||
|
||||
for i in range(n):
|
||||
random.shuffle(graph[i])
|
||||
|
||||
print(f"Generated graph with {n} nodes and {edgeCount} edges (saturation: {saturation}%, max edges: {maxEdges})")
|
||||
|
||||
# # Print the graph as a matrix for debugging
|
||||
# graph_matrix = [[0] * n for _ in range(n)]
|
||||
# for u in range(n):
|
||||
# for v in graph[u]:
|
||||
# graph_matrix[u][v] = 1
|
||||
# print("Graph adjacency matrix:")
|
||||
# for row in graph_matrix:
|
||||
# print(" ".join(map(str, row)))
|
||||
|
||||
return graph
|
||||
|
||||
def graphFromMatrix(matrix: List[List[int]]):
|
||||
n = len(matrix)
|
||||
graph = {i: [] for i in range(n)}
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
if matrix[i][j] == 1:
|
||||
graph[i].append(j)
|
||||
return graph
|
||||
|
||||
def findEulerianCycle(graph_adj_sets) -> List[int] | None:
|
||||
current_graph = {v: set(neighbors) for v, neighbors in graph_adj_sets.items()}
|
||||
|
||||
if not current_graph:
|
||||
return None # No nodes, empty path
|
||||
|
||||
path = []
|
||||
start_vertex = -1
|
||||
for v_check, neigh_check in current_graph.items():
|
||||
if neigh_check:
|
||||
start_vertex = v_check
|
||||
break
|
||||
|
||||
if start_vertex == -1:
|
||||
if len(current_graph) == 1:
|
||||
return [next(iter(current_graph))] # Single node graph
|
||||
return None
|
||||
|
||||
stack = [start_vertex]
|
||||
|
||||
while stack:
|
||||
v = stack[-1]
|
||||
if current_graph.get(v):
|
||||
u = current_graph[v].pop()
|
||||
current_graph[u].remove(v)
|
||||
stack.append(u) # Move to the next vertex
|
||||
else:
|
||||
path.append(stack.pop()) # Backtrack and add to the path
|
||||
|
||||
return path[::-1] # Return the path in reverse order
|
||||
|
||||
def findHamiltonianCycle(graph):
|
||||
n = len(graph)
|
||||
path = []
|
||||
|
||||
def backtrack(v, visited):
|
||||
if len(path) == n:
|
||||
return path[0] in graph[v] # Check if the last node connects to the first
|
||||
|
||||
for neighbor in graph[v]:
|
||||
if neighbor not in visited:
|
||||
visited.add(neighbor)
|
||||
path.append(neighbor)
|
||||
|
||||
if backtrack(neighbor, visited):
|
||||
return True
|
||||
|
||||
visited.remove(neighbor)
|
||||
path.pop()
|
||||
|
||||
return False
|
||||
|
||||
for start in range(n):
|
||||
path.append(start)
|
||||
visited = {start}
|
||||
|
||||
if backtrack(start, visited):
|
||||
return path
|
||||
|
||||
path.pop()
|
||||
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check if there was given a second argument, if yes run a test instead of the benchmark
|
||||
if len(sys.argv) > 1:
|
||||
file = sys.argv[1]
|
||||
"""
|
||||
Format we are expecting:
|
||||
0 0 1 1 1 1
|
||||
0 0 1 1 0 0
|
||||
1 1 0 0 1 1
|
||||
1 1 0 0 1 1
|
||||
1 0 1 1 0 1
|
||||
1 0 1 1 1 0
|
||||
"""
|
||||
with open(file, 'r') as f:
|
||||
lines = f.readlines()
|
||||
matrix = [list(map(int, line.strip().split())) for line in lines]
|
||||
graph = graphFromMatrix(matrix)
|
||||
|
||||
euler = findEulerianCycle(graph)
|
||||
hamilton = findHamiltonianCycle(graph)
|
||||
|
||||
if euler is None:
|
||||
print("Eulerian cycle not found.")
|
||||
exit(1)
|
||||
if hamilton is None:
|
||||
print("Hamiltonian cycle not found.")
|
||||
exit(1)
|
||||
|
||||
# We were asked to print the cycles starting from 1. Add the first node to the end of the list to make it a cycle
|
||||
# Expected: 1 6 5 4 6 3 5 1 4 2 3 1 | Actual: 1 3 2 4 1 5 3 6 4 5 6 1
|
||||
print("Eulerian Cycle:", [v + 1 for v in euler ])
|
||||
# 1 3 2 4 5 6 1 | Real: 1 3 2 4 5 6 1
|
||||
print("Hamiltonian Cycle", [v + 1 for v in hamilton] + [hamilton[0] + 1])
|
||||
|
||||
exit(0)
|
||||
|
||||
n_values = range(10, 26) # Number of nodes to test
|
||||
saturations = [30, 70] # Saturation levels to test
|
||||
results = {}
|
||||
|
||||
for saturation in saturations:
|
||||
hamilton_times = []
|
||||
eulerian_times = []
|
||||
|
||||
for n in n_values:
|
||||
print(f"Running tests for {n} nodes with {saturation}% saturation...")
|
||||
graph = generateGraph(n, saturation)
|
||||
|
||||
eulerian_time = 0
|
||||
hamilton_time = 0
|
||||
for _ in range(10):
|
||||
start_time = time.time()
|
||||
if findHamiltonianCycle(graph) is None:
|
||||
raise ValueError("Hamiltonian cycle not found, which should not happen with the generated graph.")
|
||||
end_time = time.time()
|
||||
measured_time = (end_time - start_time) * 1000
|
||||
hamilton_time += measured_time
|
||||
eulerian_graph_repr = {v_node: set(v_neighbors) for v_node, v_neighbors in graph.items()}
|
||||
start_time = time.time()
|
||||
|
||||
graph_for_eulerian_run = {node: set(adj_nodes) for node, adj_nodes in graph.items()}
|
||||
start_time = time.time()
|
||||
if findEulerianCycle(graph_for_eulerian_run) is None: # Pass the new set-based representation
|
||||
raise ValueError("Eulerian cycle not found...")
|
||||
end_time = time.time()
|
||||
eulerian_time += (end_time - start_time) * 1000
|
||||
|
||||
|
||||
# Average the times over 10 runs
|
||||
hamilton_times.append(hamilton_time / 10)
|
||||
eulerian_times.append(eulerian_time / 10)
|
||||
time.sleep(0.1) # Sleep to avoid overwhelming the system
|
||||
|
||||
results[saturation] = {
|
||||
"hamilton_times": hamilton_times,
|
||||
"eulerian_times": eulerian_times,
|
||||
}
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(n_values, hamilton_times, label="Cykl Hamiltona", marker="o")
|
||||
plt.plot(n_values, eulerian_times, label="Cykl Eulera", marker="s")
|
||||
plt.xlabel("Liczba wierzchołków (n)")
|
||||
plt.ylabel("Czas działania (ms)")
|
||||
plt.title(f"Czas działania algorytmów dla {saturation}% nasycenia")
|
||||
plt.legend()
|
||||
plt.grid(True)
|
||||
if(saturation == 30):
|
||||
plt.yscale('log', base=2)
|
||||
|
||||
filename = f"saturation_{saturation}.png"
|
||||
plt.savefig(filename)
|
||||
print(f"Plot saved as '{filename}'")
|
||||
|
||||
print("All tests completed.")
|
||||
@@ -0,0 +1,126 @@
|
||||
import random
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
def generate_hamiltonian_graph(n, saturation_percent):
|
||||
max_possible_edges = n * (n - 1) // 2
|
||||
target_edges = max_possible_edges * saturation_percent // 100
|
||||
|
||||
# Working on sets, its just easier
|
||||
graph = {i: set() for i in range(n)}
|
||||
edge_count = 0
|
||||
|
||||
cycle = list(range(n))
|
||||
random.shuffle(cycle)
|
||||
for i in range(n):
|
||||
u = cycle[i]
|
||||
v = cycle[(i + 1) % n]
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
graph[v].add(u)
|
||||
edge_count += 1
|
||||
|
||||
possible_edges = {(i, j) for i in range(n) for j in range(i+1, n)}
|
||||
used_edges = {(min(u, v), max(u, v)) for u in graph for v in graph[u]}
|
||||
available_edges = list(possible_edges - used_edges)
|
||||
random.shuffle(available_edges)
|
||||
|
||||
while edge_count < target_edges and available_edges:
|
||||
u, v = available_edges.pop()
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
graph[v].add(u)
|
||||
edge_count += 1
|
||||
|
||||
return {k: list(v) for k, v in graph.items()}
|
||||
|
||||
def graphFromMatrix(matrix: List[List[int]]):
|
||||
n = len(matrix)
|
||||
graph = {i: [] for i in range(n)}
|
||||
for i in range(n):
|
||||
for j in range(n):
|
||||
if matrix[i][j] == 1:
|
||||
graph[i].append(j)
|
||||
return graph
|
||||
|
||||
|
||||
def find_all_hamiltonian_cycles(graph):
|
||||
n = len(graph)
|
||||
cycles = set()
|
||||
|
||||
def backtrack(path, visited):
|
||||
if len(path) == n:
|
||||
if path[0] in graph[path[-1]]:
|
||||
# We have to normalize the cycle to avoid duplicates
|
||||
cycle = tuple(path)
|
||||
rev_cycle = tuple(reversed(path))
|
||||
canonical = min(cycle, rev_cycle)
|
||||
|
||||
min_idx = canonical.index(min(canonical))
|
||||
normalized = canonical[min_idx:] + canonical[:min_idx]
|
||||
cycles.add(normalized)
|
||||
return
|
||||
|
||||
for neighbor in graph[path[-1]]:
|
||||
if neighbor not in visited:
|
||||
visited.add(neighbor)
|
||||
path.append(neighbor)
|
||||
backtrack(path, visited)
|
||||
path.pop()
|
||||
visited.remove(neighbor)
|
||||
|
||||
for start in range(n):
|
||||
backtrack([start], {start})
|
||||
|
||||
return list(cycles)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
file = sys.argv[1]
|
||||
"""
|
||||
Format we are expecting:
|
||||
0 0 1 1 1 1
|
||||
0 0 1 1 0 0
|
||||
1 1 0 0 1 1
|
||||
1 1 0 0 1 1
|
||||
1 0 1 1 0 1
|
||||
1 0 1 1 1 0
|
||||
"""
|
||||
with open(file, 'r') as f:
|
||||
lines = f.readlines()
|
||||
matrix = [list(map(int, line.strip().split())) for line in lines]
|
||||
graph = graphFromMatrix(matrix)
|
||||
|
||||
cycles = find_all_hamiltonian_cycles(graph)
|
||||
|
||||
for cycle in cycles:
|
||||
print(cycle)
|
||||
exit(0)
|
||||
|
||||
n_values = range(5, 15)
|
||||
saturation = 50
|
||||
|
||||
times = []
|
||||
cycle_counts = []
|
||||
|
||||
for n in n_values:
|
||||
graph = generate_hamiltonian_graph(n, saturation)
|
||||
print(f"Running test for n={n}...")
|
||||
start = time.time()
|
||||
cycles = find_all_hamiltonian_cycles(graph)
|
||||
elapsed = (time.time() - start) * 1000
|
||||
times.append(elapsed)
|
||||
cycle_counts.append(len(cycles))
|
||||
print(f"Found {len(cycles)} cycles in {elapsed:.2f} ms")
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(n_values, times, marker="o")
|
||||
plt.xlabel("Liczba wierzchołków (n)")
|
||||
plt.ylabel("Czas działania [ms]")
|
||||
plt.title("Czas znajdowania wszystkich cykli Hamiltona dla nasycenia 50%")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.yscale('log', base=2)
|
||||
plt.savefig("hamilton.png")
|
||||
@@ -0,0 +1,167 @@
|
||||
import random
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
|
||||
def greedy(n, weight, value, capacity ):
|
||||
pairs = list(zip(value, weight))
|
||||
pairs.sort(reverse=True, key=lambda x: x[0] / x[1])
|
||||
|
||||
current_value = 0
|
||||
currentCapacity = capacity
|
||||
|
||||
for i in range(n):
|
||||
if pairs[i][1] <= currentCapacity:
|
||||
current_value += pairs[i][0]
|
||||
currentCapacity -= pairs[i][1]
|
||||
|
||||
return current_value
|
||||
|
||||
def dynamic(n, weight, value, capacity, print_table=False):
|
||||
table = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)]
|
||||
|
||||
for i in range(1, n + 1):
|
||||
for w in range(capacity + 1):
|
||||
if weight[i - 1] <= w:
|
||||
table[i][w] = max(table[i - 1][w], table[i - 1][w - weight[i - 1]] + value[i - 1])
|
||||
else:
|
||||
table[i][w] = table[i - 1][w]
|
||||
|
||||
|
||||
if print_table:
|
||||
print("\n".join(["\t".join(map(str, row)) for row in table]))
|
||||
return table[n][capacity]
|
||||
|
||||
def benchmark_containers(container_list, capacity):
|
||||
greedy_times = []
|
||||
dynamic_times = []
|
||||
greedy_values = []
|
||||
dynamic_values = []
|
||||
rel_errors = []
|
||||
|
||||
# For each container number or capacity
|
||||
for containers in container_list:
|
||||
weights = [random.randint(1, 10) for _ in range(containers)]
|
||||
values = [random.randint(1, 20) for _ in range(containers)]
|
||||
|
||||
# Dynamic
|
||||
start = time.time()
|
||||
dyn = dynamic(containers, weights, values, capacity)
|
||||
dyn_time = (time.time() - start) * 1000
|
||||
|
||||
# Greedy
|
||||
start = time.time()
|
||||
gr = greedy(containers, weights, values, capacity)
|
||||
gr_time = (time.time() - start) * 1000
|
||||
|
||||
greedy_times.append(gr_time)
|
||||
dynamic_times.append(dyn_time)
|
||||
greedy_values.append(gr)
|
||||
dynamic_values.append(dyn)
|
||||
|
||||
print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%")
|
||||
rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0)
|
||||
|
||||
return greedy_times, dynamic_times, rel_errors
|
||||
|
||||
def benchmark_capacity(capacity_list, containers):
|
||||
greedy_times = []
|
||||
dynamic_times = []
|
||||
greedy_values = []
|
||||
dynamic_values = []
|
||||
rel_errors = []
|
||||
|
||||
# For each container number or capacity
|
||||
for capacity in capacity_list:
|
||||
weights = [random.randint(1, 10) for _ in range(containers)]
|
||||
values = [random.randint(2, 20) for _ in range(containers)]
|
||||
|
||||
# Dynamic
|
||||
start = time.time()
|
||||
dyn = dynamic(containers, weights, values, capacity)
|
||||
dyn_time = (time.time() - start) * 1000
|
||||
|
||||
# Greedy
|
||||
start = time.time()
|
||||
gr = greedy(containers, weights, values, capacity)
|
||||
gr_time = (time.time() - start) * 1000
|
||||
|
||||
greedy_times.append(gr_time)
|
||||
dynamic_times.append(dyn_time)
|
||||
greedy_values.append(gr)
|
||||
dynamic_values.append(dyn)
|
||||
print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%")
|
||||
|
||||
rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0)
|
||||
|
||||
return greedy_times, dynamic_times, rel_errors
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check if there was given a second argument, if yes run a test instead of the benchmark
|
||||
if len(sys.argv) > 1:
|
||||
file = sys.argv[1]
|
||||
"""
|
||||
Format we are expecting:
|
||||
5 - liczba elementów
|
||||
3 2 4 3 1 - rozmiary
|
||||
5 3 4 4 2 - wartości
|
||||
8 - rozmiar plecaka
|
||||
"""
|
||||
with open(file, 'r') as f:
|
||||
lines = f.readlines()
|
||||
n = int(lines[0].strip())
|
||||
weights = list(map(int, lines[1].strip().split()))
|
||||
values = list(map(int, lines[2].strip().split()))
|
||||
capacity = int(lines[3].strip())
|
||||
|
||||
dynamic(n, weights, values, capacity, print_table=True)
|
||||
print(greedy(n, weights, values, capacity))
|
||||
exit(0)
|
||||
|
||||
# First test case - constant capacity, variable number of containers
|
||||
containers_list = list(range(1, 51, 2))
|
||||
|
||||
# Constant capacity of 20
|
||||
greedy_times, dynamic_times, rel_errors = benchmark_containers(containers_list, 20)
|
||||
|
||||
plt.figure(figsize=(12,5))
|
||||
plt.subplot(1,2,1)
|
||||
plt.plot(containers_list, greedy_times, label='Zachłanny', )
|
||||
plt.plot(containers_list, dynamic_times, label='Dynamiczny', )
|
||||
plt.xlabel('Liczba kontenerów')
|
||||
plt.ylabel('Czas [ms]')
|
||||
# plt.yscale('log', base=2)
|
||||
plt.title('Czas działania dla zmiennej liczby kontenerów (B=20)')
|
||||
plt.legend()
|
||||
|
||||
axis = plt.subplot(1,2,2)
|
||||
plt.bar(containers_list, rel_errors)
|
||||
plt.xlabel('Liczba kontenerów')
|
||||
plt.ylabel('Błąd względny [%]')
|
||||
axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', ''))
|
||||
plt.title('Błąd względny')
|
||||
plt.savefig('benchmark_vary_n.png')
|
||||
|
||||
|
||||
# Second test case - variable capacity, constant number of containers
|
||||
capacity_list = list(range(5, 101, 5))
|
||||
|
||||
# Constant number of containers of 50
|
||||
greedy_times, dynamic_times, rel_errors = benchmark_capacity(capacity_list, 50)
|
||||
|
||||
plt.figure(figsize=(12,5))
|
||||
plt.subplot(1,2,1)
|
||||
plt.plot(capacity_list, greedy_times, label='Zachłanny' )
|
||||
plt.plot(capacity_list, dynamic_times, label='Dynamiczny')
|
||||
plt.xlabel('Pojemność')
|
||||
plt.ylabel('Czas [ms]')
|
||||
plt.title('Czas działania dla zmiennej pojemności (n=50)')
|
||||
plt.legend()
|
||||
|
||||
axis = plt.subplot(1,2,2)
|
||||
plt.bar(capacity_list, rel_errors )
|
||||
plt.xlabel('Pojemność')
|
||||
plt.ylabel('Błąd względny [%]')
|
||||
axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', ''))
|
||||
plt.title('Błąd względny')
|
||||
plt.savefig('benchmark_vary_capacity.png')
|
||||
Generated
+25
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1739736696,
|
||||
"narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=",
|
||||
"rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f",
|
||||
"revCount": 754461,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.754461%2Brev-d74a2335ac9c133d6bbec9fc98d91a77f1604c1f/01951426-5a87-7b75-8413-1a0d9ec5ff04/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
description = "A Nix-flake-based C/C++ development environment";
|
||||
|
||||
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" ];
|
||||
forEachSupportedSystem = f:
|
||||
nixpkgs.lib.genAttrs supportedSystems
|
||||
(system: f { pkgs = import nixpkgs { inherit system; }; });
|
||||
in {
|
||||
devShells = forEachSupportedSystem ({ pkgs }: {
|
||||
default = pkgs.mkShell.override {
|
||||
# Override stdenv in order to change compiler:
|
||||
# stdenv = pkgs.clangStdenv;
|
||||
} {
|
||||
packages = with pkgs;
|
||||
[
|
||||
clang-tools
|
||||
cmake
|
||||
libgcc
|
||||
python312Packages.matplotlib
|
||||
] ++ (if system == "aarch64-darwin" then [ ] else [ gdb ]);
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
-150
@@ -1,150 +0,0 @@
|
||||
./insertion random 1000 1.0615110397338867
|
||||
./insertion random 2000 1.5358448028564453
|
||||
./insertion random 3000 2.274918556213379
|
||||
./insertion random 4000 3.3971309661865234
|
||||
./insertion random 5000 4.603886604309082
|
||||
./insertion random 6000 6.020760536193848
|
||||
./insertion random 7000 7.8598737716674805
|
||||
./insertion random 8000 9.824132919311523
|
||||
./insertion random 9000 12.162041664123535
|
||||
./insertion random 10000 14.610838890075684
|
||||
./insertion random 11000 17.46840476989746
|
||||
./insertion random 12000 20.206165313720703
|
||||
./insertion random 13000 23.66960048675537
|
||||
./insertion random 14000 27.488040924072266
|
||||
./insertion random 15000 30.75859546661377
|
||||
./insertion sorted 1000 0.8951187133789062
|
||||
./insertion sorted 2000 0.9664773941040039
|
||||
./insertion sorted 3000 1.1182308197021484
|
||||
./insertion sorted 4000 1.237630844116211
|
||||
./insertion sorted 5000 1.397252082824707
|
||||
./insertion sorted 6000 1.5844106674194336
|
||||
./insertion sorted 7000 1.7046451568603516
|
||||
./insertion sorted 8000 1.8734216690063477
|
||||
./insertion sorted 9000 2.349853515625
|
||||
./insertion sorted 10000 2.4387359619140625
|
||||
./insertion sorted 11000 2.462148666381836
|
||||
./insertion sorted 12000 2.5963783264160156
|
||||
./insertion sorted 13000 3.156876564025879
|
||||
./insertion sorted 14000 3.132033348083496
|
||||
./insertion sorted 15000 3.238677978515625
|
||||
./insertion reversed 1000 1.2768268585205078
|
||||
./insertion reversed 2000 2.137279510498047
|
||||
./insertion reversed 3000 3.491377830505371
|
||||
./insertion reversed 4000 5.584287643432617
|
||||
./insertion reversed 5000 7.988524436950684
|
||||
./insertion reversed 6000 10.77868938446045
|
||||
./insertion reversed 7000 14.134597778320312
|
||||
./insertion reversed 8000 18.278932571411133
|
||||
./insertion reversed 9000 22.71718978881836
|
||||
./insertion reversed 10000 27.739286422729492
|
||||
./insertion reversed 11000 33.2233190536499
|
||||
./insertion reversed 12000 39.423227310180664
|
||||
./insertion reversed 13000 45.474839210510254
|
||||
./insertion reversed 14000 52.727437019348145
|
||||
./insertion reversed 15000 60.09998321533203
|
||||
./insertion constant 1000 0.9403467178344727
|
||||
./insertion constant 2000 0.9927988052368164
|
||||
./insertion constant 3000 1.1275291442871094
|
||||
./insertion constant 4000 1.2822389602661133
|
||||
./insertion constant 5000 1.5305280685424805
|
||||
./insertion constant 6000 1.5430212020874023
|
||||
./insertion constant 7000 1.8325090408325195
|
||||
./insertion constant 8000 1.804804801940918
|
||||
./insertion constant 9000 2.2058486938476562
|
||||
./insertion constant 10000 2.1335840225219727
|
||||
./insertion constant 11000 2.322697639465332
|
||||
./insertion constant 12000 2.5031328201293945
|
||||
./insertion constant 13000 2.8443336486816406
|
||||
./insertion constant 14000 2.675914764404297
|
||||
./insertion constant 15000 2.9070377349853516
|
||||
./insertion v_shaped 1000 1.075124740600586
|
||||
./insertion v_shaped 2000 1.6106843948364258
|
||||
./insertion v_shaped 3000 2.419257164001465
|
||||
./insertion v_shaped 4000 3.438878059387207
|
||||
./insertion v_shaped 5000 4.725170135498047
|
||||
./insertion v_shaped 6000 6.513190269470215
|
||||
./insertion v_shaped 7000 7.992100715637207
|
||||
./insertion v_shaped 8000 10.184979438781738
|
||||
./insertion v_shaped 9000 12.364602088928223
|
||||
./insertion v_shaped 10000 15.029740333557129
|
||||
./insertion v_shaped 11000 18.083977699279785
|
||||
./insertion v_shaped 12000 21.661686897277832
|
||||
./insertion v_shaped 13000 24.31178092956543
|
||||
./insertion v_shaped 14000 27.93755531311035
|
||||
./insertion v_shaped 15000 32.60822296142578
|
||||
./selection random 1000 1.4104366302490234
|
||||
./selection random 2000 2.2107839584350586
|
||||
./selection random 3000 3.5886764526367188
|
||||
./selection random 4000 5.592441558837891
|
||||
./selection random 5000 7.922983169555664
|
||||
./selection random 6000 11.436033248901367
|
||||
./selection random 7000 14.230155944824219
|
||||
./selection random 8000 18.193602561950684
|
||||
./selection random 9000 22.896504402160645
|
||||
./selection random 10000 29.131484031677246
|
||||
./selection random 11000 33.37256908416748
|
||||
./selection random 12000 39.19968605041504
|
||||
./selection random 13000 47.031211853027344
|
||||
./selection random 14000 53.545570373535156
|
||||
./selection random 15000 61.37092113494873
|
||||
./selection sorted 1000 1.2252330780029297
|
||||
./selection sorted 2000 2.236461639404297
|
||||
./selection sorted 3000 3.660869598388672
|
||||
./selection sorted 4000 5.638456344604492
|
||||
./selection sorted 5000 8.042407035827637
|
||||
./selection sorted 6000 11.208224296569824
|
||||
./selection sorted 7000 14.447546005249023
|
||||
./selection sorted 8000 18.74523162841797
|
||||
./selection sorted 9000 22.982478141784668
|
||||
./selection sorted 10000 28.246402740478516
|
||||
./selection sorted 11000 34.0437650680542
|
||||
./selection sorted 12000 39.82250690460205
|
||||
./selection sorted 13000 46.31156921386719
|
||||
./selection sorted 14000 53.86967658996582
|
||||
./selection sorted 15000 61.89534664154053
|
||||
./selection reversed 1000 1.210784912109375
|
||||
./selection reversed 2000 2.1828174591064453
|
||||
./selection reversed 3000 3.7517547607421875
|
||||
./selection reversed 4000 5.427956581115723
|
||||
./selection reversed 5000 8.042573928833008
|
||||
./selection reversed 6000 10.962772369384766
|
||||
./selection reversed 7000 14.444756507873535
|
||||
./selection reversed 8000 18.53172779083252
|
||||
./selection reversed 9000 22.98440933227539
|
||||
./selection reversed 10000 28.051161766052246
|
||||
./selection reversed 11000 33.19251537322998
|
||||
./selection reversed 12000 39.997243881225586
|
||||
./selection reversed 13000 45.667243003845215
|
||||
./selection reversed 14000 53.35855484008789
|
||||
./selection reversed 15000 60.373663902282715
|
||||
./selection constant 1000 1.2602806091308594
|
||||
./selection constant 2000 2.1334409713745117
|
||||
./selection constant 3000 3.5085439682006836
|
||||
./selection constant 4000 5.34212589263916
|
||||
./selection constant 5000 7.747673988342285
|
||||
./selection constant 6000 10.555744171142578
|
||||
./selection constant 7000 14.265799522399902
|
||||
./selection constant 8000 18.23742389678955
|
||||
./selection constant 9000 22.236275672912598
|
||||
./selection constant 10000 27.255654335021973
|
||||
./selection constant 11000 32.57889747619629
|
||||
./selection constant 12000 38.65196704864502
|
||||
./selection constant 13000 45.708537101745605
|
||||
./selection constant 14000 51.95658206939697
|
||||
./selection constant 15000 59.54868793487549
|
||||
./selection v_shaped 1000 1.179647445678711
|
||||
./selection v_shaped 2000 2.0728111267089844
|
||||
./selection v_shaped 3000 3.5805463790893555
|
||||
./selection v_shaped 4000 5.700540542602539
|
||||
./selection v_shaped 5000 8.303594589233398
|
||||
./selection v_shaped 6000 10.987281799316406
|
||||
./selection v_shaped 7000 14.623737335205078
|
||||
./selection v_shaped 8000 18.853092193603516
|
||||
./selection v_shaped 9000 22.894835472106934
|
||||
./selection v_shaped 10000 27.98130512237549
|
||||
./selection v_shaped 11000 33.84420871734619
|
||||
./selection v_shaped 12000 39.37234878540039
|
||||
./selection v_shaped 13000 46.07586860656738
|
||||
./selection v_shaped 14000 53.040337562561035
|
||||
./selection v_shaped 15000 60.929179191589355
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB |
Reference in New Issue
Block a user