infrastructure

This commit is contained in:
TUNQRT 2025-03-22 13:11:20 +01:00
parent 28a209cbd1
commit b66adf7ab5
11 changed files with 417 additions and 63 deletions

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

@ -0,0 +1,46 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Docker C++ Debug",
"type": "cppdbg",
"request": "launch",
"program": "/app/a.out",
"args": [],
"stopAtEntry": true,
"cwd": "/app",
"environment": [],
"externalConsole": false,
"pipeTransport": {
"debuggerPath": "/usr/bin/gdb",
"pipeProgram": "ssh",
"pipeArgs": [
"root@localhost",
"-p", "2222",
"-i", "${workspaceFolder}/key",
"-o", "StrictHostKeychecking=no",
"/usr/bin/gdb --interpreter=mi"
]
},
"sourceFileMap": {
"/app": "${workspaceFolder}"
},
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "skip libpoly",
"text": "skip -gfi libpoly.so",
"ignoreFailures": false
}
]
}
]
}

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

@ -0,0 +1,55 @@
{
"files.associations": {
"condition_variable": "cpp",
"thread": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp",
"map": "cpp"
}
}

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

@ -0,0 +1,32 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "/usr/bin/g++-14",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-Wall",
"-pedantic",
"-pthread",
"-std=c++20"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

22
Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM gcc:latest
COPY ./ /app
WORKDIR /app
RUN apt update && apt install -y gdb gdbserver openssh-server && \
apt clean
RUN make a.out && echo 'yeey'
RUN mv key.pub /root/.ssh/authorized_keys && \
mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
# CMD ["sleep", "infinity"]
# CMD ["/app/a.out"]

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
a.out: triangulation.cpp
g++ -Wl,-rpath=. triangulation.cpp -g -Wall -pedantic -pthread -lpoly -L./ -std=c++20

6
build.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
if [ ! -f key ] || [ ! -f key.pub ]; then
rm -f key key.pub && \
ssh-keygen -t ed25519 -N "" -f key
fi
docker build -t cpp20 .

3
kill.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
docker ps --filter name=triangulation --format "{{.ID}}"| xargs -L1 docker kill

44
libpoly.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef libpoly092986127876186578684563243
#define libpoly092986127876186578684563243
#include <vector>
#include <memory>
#include <ostream>
void test(); // prints to stdout to test linking
struct LP_Point {
double x, y;
auto operator<=>(const LP_Point&) const = default;
};
struct LP_Polygon {
std::vector< LP_Point > points;
LP_Polygon(std::vector< LP_Point >&& p) : points(p) {}
LP_Polygon() {}
};
class LP_Task : public std::enable_shared_from_this< LP_Task > {
struct Private{ explicit Private() = default; };
public:
LP_Task(Private) {}
static std::shared_ptr<LP_Task> create() {
return std::make_shared<LP_Task>(Private());
}
std::shared_ptr<LP_Task> getptr() {
return shared_from_this();
}
LP_Task(LP_Polygon&& _p): p(_p), minimal_triangulation(MAXFLOAT){};
LP_Polygon p;
double minimal_triangulation;
};
using LP_Task_p = std::shared_ptr< LP_Task >;
LP_Task_p pickup_task();
bool submit_task(LP_Task_p&&);
#endif // libpoly092986127876186578684563243

BIN
libpoly.so Normal file

Binary file not shown.

3
run.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run --rm -d --name triangulation -p 2222:22 -p 7777:7777 cpp20

View File

@ -21,21 +21,19 @@ std::condition_variable can_push;
std::atomic_uint32_t active_producents;
std::atomic_uint32_t active_consuments;
std::atomic_bool tasks_incoming;
std::ostream& os = std::cout;
std::mutex os_l;
//############################# MODIFY HERE
constexpr unsigned NUM_PRODUCENTS = 1;
constexpr unsigned NUM_WORKERS = 3;
constexpr unsigned NUM_PRODUCENTS = 2;
constexpr unsigned NUM_WORKERS = 5;
//############################################################ COMMON STRUCTURES
struct Temp_Task: public std::enable_shared_from_this< Temp_Task > {
LP_Polygon p;
double minimal_triangulation;
Temp_Task(LP_Polygon&& _p): p(_p){}
};
@ -45,9 +43,10 @@ class Task {
private:
Temp_Task_p task;
double triangulate(LP_Polygon* p);
double triangulate_basic(LP_Polygon* p);
double triangulate();
double triangulate_subpolys(std::vector<bool> poly_key, std::map<int, double>* m);
std::vector<bool> create_key(std::vector<int>* indices);
public:
Task(): task(nullptr){};
@ -56,13 +55,20 @@ public:
t.task.reset();
}
Task(Temp_Task_p&& tp): task(tp){}
void solve_stupid(){
task->minimal_triangulation = triangulate(&(task->p));
double solution() const { return task->minimal_triangulation; }
bool is_empty() const {
return task.get() == nullptr;
}
void solve_stupid(){
task->minimal_triangulation = triangulate_basic(&(task->p));
}
void solve_less_stupid(){ task->minimal_triangulation = triangulate(); }
Temp_Task_p unwrap(){ // TODO: vymyslet jinak, zaručit po tomto kroku selfdestruct
return std::move(task);
}
double const solution(){ return task->minimal_triangulation; }
};
class Queue{
@ -100,7 +106,7 @@ public:
using task_queue_ptr = std::shared_ptr<Queue>;
//############################################################ PRODUCE THREAD
/*
class Producent{
private:
task_queue_ptr task_queue;
@ -111,30 +117,41 @@ public:
Task get_task(){
//LP_Task_p tp = pickup_task();
os_l.lock();
os << "picked up" << std::endl;
os_l.unlock();
//#########################3TEMP_PART:
std::vector< LP_Point > points;
srand(static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()));
int num_of_points = (rand()%10) + 1;
for(int i = 0; i < num_of_points; i++){
LP_Point p;
// std::vector< LP_Point > points;
// srand(static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()));
// int num_of_points = (rand()%10) + 1;
// for(int i = 0; i < num_of_points; i++){
// LP_Point p;
p.x = rand()%199 +1;
p.y = rand()%199 +1;
points.push_back(p);
}
LP_Polygon p(std::move(points));
Temp_Task_p tp = std::make_shared<Temp_Task>(std::move( p ));
// p.x = rand()%199 +1;
// p.y = rand()%199 +1;
// points.push_back(p);
// }
// LP_Polygon p(std::move(points));
// Temp_Task_p tp = std::make_shared<Temp_Task>(std::move( p ));
return Task(std::move(tp));
}
void fill_queue(){
while(tasks_incoming){
//Task t = get_task();
task_queue->push(get_task());
while(1){
Task t = get_task();
if(t.is_empty()) break;
else{
task_queue->push(std::move(t));
os_l.lock();
os << "queued" << std::endl;
os_l.unlock();
}
}
os_l.lock();
os << "p ready to join" << std::endl;
os_l.unlock();
}
};
@ -154,6 +171,9 @@ public:
~Consument() { active_consuments--; }
Task get_task(){ // might be redundant
os_l.lock();
os << "processing" << std::endl;
os_l.unlock();
return task_queue->pop();
}
@ -161,11 +181,14 @@ public:
while(active_producents || ! task_queue->is_empty()){
Task t = get_task();
t.solve_stupid();
//submit_task(std::move(t.unwrap()));
submit_task(std::move(t.unwrap()));
os_l.lock();
os << t.solution() << std::endl;
os_l.unlock();
}
os_l.lock();
os << "c ready to join" << std::endl;
os_l.unlock();
}
};
@ -173,7 +196,7 @@ void consume_thread(task_queue_ptr task_queue){
Consument c(task_queue);
c.work();
}
*/
//############################################################ TRIANGULATION
struct Line{
@ -191,12 +214,19 @@ struct Line{
Line(Line& l): a(l.a), b(l.b), length(l.length){}
};
double Task::triangulate(LP_Polygon* p){
double Task::triangulate_basic(LP_Polygon* p){
size_t poly_size = p->points.size();
if(poly_size == 3) return 0.;
if(poly_size == 4){
Line cut1(p->points.at( 0 ),
p->points.at( 2 ));
Line cut2(p->points.at( 1 ),
p->points.at( 3 ));
return std::min(cut1.length, cut2.length);
}
double triangulation;
double triangulation = INFINITY;
double min_triangulation = INFINITY;
for (size_t point_idx = 0; point_idx < poly_size; point_idx++){
@ -209,24 +239,31 @@ double Task::triangulate(LP_Polygon* p){
}
LP_Polygon s_p(std::move(smaller_poly));
triangulation = triangulate(&s_p) + cut.length;
triangulation = triangulate_basic(&s_p) + cut.length;
if(triangulation < min_triangulation) min_triangulation = triangulation;
}
return min_triangulation;
}
//############################### dynamic something
//########################### attempt of thought
// build a list (array?) of all cut lengths ... n
// build a list of "quatrogones"-> pentagones -> hexagones -> ....; each of them carries its min_triangulation
// end up with our polygone already w min triang.
// not really better i guess...
//########################### dynamic something
//use std::map to store triangulations of polygons
//KEY CREATION:
// take relative positions of points in polygon, add them as vectors and do something with the amount of them
// maybe num * vx + num^2 * vy
double Task::triangulate(){
std::map<int, double> m;
std::vector<bool> poly_key;
return triangulate_subpolys(poly_key, &m);
std::vector<bool> poly_key(task->p.points.size(), true);
return triangulate_subpolys(poly_key, &m);
//
// return triangulate_subpolys_but_better();
}
int vec_to_int(std::vector<bool>* vec){
@ -237,46 +274,150 @@ int vec_to_int(std::vector<bool>* vec){
return res;
}
std::vector<bool> Task::create_key(std::vector<int>* indices){
size_t key_length = task->p.points.size();
std::vector<bool> key(key_length, false);
for(size_t i = 0; i < indices->size(); i++){
key[indices->at(i)] = true;
}
return key;
}
double Task::triangulate_subpolys(std::vector<bool> poly_key, std::map<int, double>* m){
// convert p to int
int key = vec_to_int(&poly_key);
// try to find in map
// success -> return mapped value
// failure -> compute triangulation
// save value in map
if (m->count(key)) return m->at(key); // ! contains() is c++20
// failure -> create poly from key
std::vector<LP_Point> curr_points;
std::vector<int> curr_indices;
for(size_t i = 0; i < task->p.points.size(); i++){
if(poly_key.at(i)){
curr_points.push_back(task->p.points.at(i));
curr_indices.push_back(i);
}
}
LP_Polygon poly(std::move(curr_points));
// use stupid triangulation but create poly_key instead of small_poly
// save value in map before any return
size_t poly_size = poly.points.size();
if(poly_size == 3){
(*m)[key] = 0.;
return 0.;
}
double triangulation;
double min_triangulation = INFINITY;
for (size_t point_idx = 0; point_idx < poly_size; point_idx++){
Line cut(poly.points.at( (point_idx - 1) % poly_size ),
poly.points.at( (point_idx + 1) % poly_size ));
std::vector<int> sub_indices = curr_indices;
sub_indices.erase(sub_indices.begin() + point_idx);
triangulation = triangulate_subpolys( create_key( &sub_indices ), m )
+ cut.length;
if(triangulation < min_triangulation) min_triangulation = triangulation;
}
(*m)[key] = min_triangulation;
// return found value
// COMPUTE TRIANGULATION
// create polygon poly from p
// use stupid triangulation but create poly_key instead of small_poly
return 0.;
return min_triangulation;
}
//########################### dynamic something but better
//############################################################ TRIANGULATION TEST
void task_test(){
std::vector< LP_Point > v1 = {{0,0}, {1,1}, {3,1}, {2,0}};
std::vector< LP_Point > v2 = {{0,0}, {0,1}, {1,2}, {2,1}, {2,0}};
std::vector< LP_Point > v3 = {{0,0}, {1,1}, {2,2}, {3,1}, {2,0}, {1,-1}};
LP_Polygon p1(std::move(v1));
LP_Polygon p2(std::move(v2));
LP_Polygon p3(std::move(v3));
Temp_Task_p tp1 = std::make_shared<Temp_Task>(std::move(p1));
Temp_Task_p tp2 = std::make_shared<Temp_Task>(std::move(p2));
Temp_Task_p tp3 = std::make_shared<Temp_Task>(std::move(p3));
Task t1(std::move(tp1));
Task t2(std::move(tp2));
Task t3(std::move(tp3));
t1.solve_stupid();
t2.solve_stupid();
t3.solve_stupid();
std::cout << "4 vertices:\ncorrect: calculated:\n" << "1.414 " << t1.solution() << std::endl;
std::cout << "5 vertices:\ncorrect: calculated:\n" << "4.236 " << t2.solution() << std::endl;
std::cout << "6 vertices:\ncorrect: calculated:\n" << "5.414 " << t1.solution() << std::endl << std::endl;
t1.solve_less_stupid();
t2.solve_less_stupid();
t3.solve_less_stupid();
std::cout << "SECOND VERSION:\n\n";
std::cout << "4 vertices:\ncorrect: calculated:\n" << "1.414 " << t1.solution() << std::endl;
std::cout << "5 vertices:\ncorrect: calculated:\n" << "4.236 " << t2.solution() << std::endl;
std::cout << "6 vertices:\ncorrect: calculated:\n" << "5.414 " << t1.solution() << std::endl << std::endl;
}
//############################################################ MAIN
int main(){
active_producents = active_consuments = 0;
tasks_incoming = true;
task_queue_ptr queue_ptr = std::make_shared<Queue>();
std::vector<std::thread> threads;
//############################### MULTI THREAD
for(unsigned int i = 0; i < NUM_PRODUCENTS; i++){
threads.emplace_back(produce_thread, queue_ptr);
}
// active_producents = active_consuments = 0;
for(unsigned int i = 0; i < NUM_WORKERS; i++){
threads.emplace_back(consume_thread, queue_ptr);
}
// task_queue_ptr queue_ptr = std::make_shared<Queue>();
// std::vector<std::thread> threads;
std::this_thread::sleep_for(std::chrono::milliseconds(5));
tasks_incoming = false;
for(auto& t : threads){
t.join();
os_l.lock();
os << "joined" << std::endl;
os_l.unlock();
}
//test();
// for(unsigned int i = 0; i < NUM_PRODUCENTS; i++){
// threads.emplace_back(produce_thread, queue_ptr);
// }
// for(unsigned int i = 0; i < NUM_WORKERS; i++){
// threads.emplace_back(consume_thread, queue_ptr);
// }
// for(auto& t : threads){
// t.join();
// os_l.lock();
// os << "joined" << std::endl;
// os_l.unlock();
// }
//############################### SINGLE THREAD
// while(1){
// LP_Task_p tp = pickup_task();
// if(!tp) break;
// Task t(std::move(tp));
// t.solve_stupid();
// submit_task(std::move(t.unwrap()));
// }
//############################### CONNECTION TEST
// test();
//############################### TRIANGULATION TEST
task_test();
}