Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: For comments only #3

Open
wants to merge 28 commits into
base: review_base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a47d24e
Completed the porting of Dijkstra's Algorithm. Some small refactoring.
armytrong May 3, 2022
c0374e7
swapped heap in Dijkstra's Algorithm
armytrong Jun 26, 2022
a9b29a2
first steiner calculations seem to be working fine
armytrong Jun 26, 2022
8ec8bbc
added Heap interface, cretaed BinaryHeap, not implemented.
armytrong Jun 27, 2022
64ec9ed
added postscript output
armytrong Jun 27, 2022
2e38ce6
added rudimentary support for DICMAS instances
armytrong Jun 27, 2022
c9643d7
Create cmake.yml
armytrong Jun 27, 2022
388d14f
Merge pull request #1 from armytrong/create-gh-actions
armytrong Jun 27, 2022
5dc1fa9
Update cmake.yml
armytrong Jun 27, 2022
c7ee577
Merge pull request #2 from armytrong/create-gh-actions
armytrong Jun 27, 2022
6787fd1
fixed mistake in Heap that lead to linker error
armytrong Jun 27, 2022
6505fe3
implemented Dalunay triangulation eficciently, other refactorings
armytrong Jun 28, 2022
bfdc026
Update CMakeLists.txt
armytrong Jun 28, 2022
d71f2ff
Repair CMakeLists.txt again...
armytrong Jun 28, 2022
9387852
refactorings
armytrong Jun 28, 2022
cc1c4f1
created ArgumentHandler and ported kruskal to DelaunayGraph
armytrong Jun 29, 2022
c8ac0d0
remove googletest
armytrong Jun 29, 2022
db6bb68
code cleanup, regard static analysis
armytrong Jun 30, 2022
f2a67b0
refactoring and bugfixing, added -t and -s options
armytrong Jul 3, 2022
3f2720f
added ability to add steiner nodes to delaunay graph
armytrong Jul 4, 2022
ba60bcb
created true mehlhorn graph
armytrong Jul 4, 2022
84906cc
implemented kruskal on mehlhorn edges
armytrong Jul 4, 2022
5cb46ff
added coordinate graph
armytrong Jul 5, 2022
c7d81e2
implemented l-shape-flipping
armytrong Jul 5, 2022
68e8733
improved file parser to read multiple instances
armytrong Jul 9, 2022
db07890
refactorings from comments
armytrong Jul 9, 2022
ecd6d3b
undo false changes to CMakeLists.txt
armytrong Jul 9, 2022
79c5415
Merge pull request #4 from armytrong/implement_delaunay_mehlhorn_comb…
armytrong Jul 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CMake

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
CC: gcc-10
CXX: g++-10

jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}

- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
/cmake-build-debug/
/build/
/4_filtered/
/.vscode/
/.idea/
13_hard/
bench_instances/
/PostScript/test.ps
/Output/
/RSMT-ibm/
*.stp
*.ps
!PostScript/template.ps
Empty file added .gitmodules
Empty file.
74 changes: 74 additions & 0 deletions ArgumentHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// Created by jgier on 29.06.2022.
//

#include "ArgumentHandler.h"
#include <fstream>

const ArgumentHandler::Parms &ArgumentHandler::parms() {
return _parms;
}

ArgumentHandler::ArgumentHandler(int argc, char **argv) : _parms{
"",
"",
OutputFormat::STP,
0,
false,
false,
true,
true
} {
for (int i = 1; i < argc; i++) {
std::string arg(argv[i]);
if (arg == "-ps") {
_parms.output_format = OutputFormat::PS;
} else if (arg == "-stp") {
_parms.output_format = OutputFormat::STP;
} else if (arg == "-o") {
i++;
if (i < argc) {
_parms.output_filename = argv[i];
}
} else if (arg == "-v" or arg == "--verbose") {
_parms.verbose = true;
} else if (arg == "-mi" or arg == "--manual_input") {
std::cout << "Specify input file: ";
std::cin >> _parms.input_filename;
} else if (arg == "-mo" or arg == "--manual_output") {
std::cout << "Specify output file: ";
std::cin >> _parms.output_filename;
} else if (arg == "-h" or arg == "--help") {
print_usage(std::cout, argv[0]);
_parms.run = false;
} else if (arg == "-t" or arg == "--nodes-are-terminals") {
_parms.nodes_are_terminals = true;
} else if (arg == "-s" or arg == "--skip-instances") {
i++;
if (i < argc) {
_parms.instances_to_skip = std::stoi(argv[i]);
}
} else if (arg == "--silent") {
_parms.output = false;
} else if (arg[0] == '-') {
std::cerr << argv[0] << ": " << arg << ": invalid option" << std::endl;
print_usage(std::cerr, argv[0]);
_parms.run = false;
} else if (_parms.input_filename.empty()) {
_parms.input_filename = arg;
}
}
}

void ArgumentHandler::print_usage(std::ostream &os, std::string const &program_name) {
os << "Usage: " << program_name
<< " [-ps | -stp] [-o OUTPUT_FILE] [-mi] [-mo] [-v] [-t] [-s NUM] [INPUT_FILENAME]"
<< std::endl << std::endl;
os << "Options: " << std::endl;
os << "\t -ps | -stp \t\t output result as PostScript or .stp respectively" << std::endl;
os << "\t -o OUTPUT_FILE \t specify file to write output to. Blank for standard output" << std::endl;
os << "\t -mi -mo \t\t Specify input respectively output file during runtime via standard input" << std::endl;
os << "\t -v \t\t\t print verbose information" << std::endl;
os << "\t -t \t\t\t treat nodes as terminals" << std::endl;
os << "\t -s NUMBER \t\t skip number of instances in input" << std::endl;
}
43 changes: 43 additions & 0 deletions ArgumentHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// Created by jgier on 29.06.2022.
//

#ifndef HAUPTAUFGABE_2_ARGUMENTHANDLER_H
#define HAUPTAUFGABE_2_ARGUMENTHANDLER_H


#include <optional>
#include <string>
#include <iostream>
#include <fstream>

enum struct OutputFormat {
PS, STP
};

class ArgumentHandler {
public:
struct Parms {
std::string input_filename;
std::string output_filename;
OutputFormat output_format;
size_t instances_to_skip;
bool nodes_are_terminals;
bool verbose;
bool output;
bool run;
};

ArgumentHandler(int argc, char **argv);

static void print_usage(std::ostream &os, std::string const &program_name);

Parms const &parms();

private:
Parms _parms;
std::optional<std::ofstream> _file;
};


#endif //HAUPTAUFGABE_2_ARGUMENTHANDLER_H
33 changes: 32 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,35 @@ project(Hauptaufgabe_2)

set(CMAKE_CXX_STANDARD 20)

add_executable(Hauptaufgabe_2 main.cpp SteinerTreeAproximator.cpp SteinerTreeAproximator.h STPFileParser.cpp STPFileParser.h dijkstra/DijkstraGraph.cpp dijkstra/DijkstraGraph.h graph/Graph.cpp graph/Graph.h graph/Edge.cpp graph/Edge.h dijkstra/FibonacciHeap.cpp dijkstra/FibonacciHeap.h)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address -g")

include_directories(.)

add_executable(Hauptaufgabe_2
main.cpp
STPFileParser.cpp STPFileParser.h
dijkstra/DijkstraGraph.cpp
dijkstra/DijkstraGraph.h
graph/Graph.cpp graph/Graph.h
heap/FibonacciHeap.cpp
heap/FibonacciHeap.h
typedefs.h
MehlhornGraphFactory.cpp
MehlhornGraphFactory.h
kruskal/kruskal_ind.cpp
kruskal/kruskal_ind.h
heap/StandardHeap.cpp
heap/StandardHeap.h
graph/RectilinearGraph.cpp
graph/RectilinearGraph.h
heap/BinaryHeap.cpp
heap/BinaryHeap.h
heap/Heap.h
delaunay/DelaunayGraph.cpp
delaunay/DelaunayGraph.h
delaunay/DelaunaySet.cpp
delaunay/DelaunaySet.h
delaunay/DelaunayPriorityQueue.cpp
delaunay/DelaunayPriorityQueue.h
ArgumentHandler.cpp
ArgumentHandler.h mehlhorn/MehlhornGraph.cpp mehlhorn/MehlhornGraph.h graph/CoordinateGraph.cpp graph/CoordinateGraph.h)
97 changes: 97 additions & 0 deletions MehlhornGraphFactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Created by jgier on 20.06.2022.
//

#include <cassert>
#include <optional>
#include "MehlhornGraphFactory.h"

void MehlhornGraphFactory::bucket_sort(
std::vector<CandidateEdge> &vector,
MehlhornGraphFactory::TypeToNodeId<CandidateEdge> type_to_node_id,
NodeId max_id) {
std::vector<std::vector<CandidateEdge>> bucket_list;
bucket_list.resize(max_id);
for (auto const &t: vector) {
bucket_list[type_to_node_id(t)].emplace_back(t);
}
size_t orig_i = 0;
for (auto const &bucket: bucket_list) {
for (auto const &item: bucket) {
vector[orig_i] = item;
orig_i++;
}
}
}

Graph MehlhornGraphFactory::create_melhorn_graph(
DijkstraGraph const &dijkstra_graph,
Graph const &graph
) {
assert(dijkstra_graph.calculation_finished());
std::vector<CandidateEdge> candidate_edges;
for (auto const &edge: graph.edges()) {
NodeId terminal_1 = dijkstra_graph[edge._head].closest_terminal;
NodeId terminal_2 = dijkstra_graph[edge._tail].closest_terminal;
// The distance to root equals the distance to the closest terminal
WeightType weight = dijkstra_graph[edge._head].distance_to_root + edge._weight + dijkstra_graph[edge._tail]
.distance_to_root;
if (terminal_1 != terminal_2) {
candidate_edges.emplace_back(terminal_1, terminal_2, weight);
}
}

bucket_sort(
candidate_edges,
[](CandidateEdge const &candidate_edge) { return candidate_edge.smaller_terminal; },
graph.num_nodes()
);

bucket_sort(
candidate_edges,
[](CandidateEdge const &candidate_edge) { return candidate_edge.larger_terminal; },
graph.num_nodes()
);

std::vector<Graph::Edge> edges;

std::optional<CandidateEdge> current_mincost_edge = std::nullopt;

for (auto candidate_edge: candidate_edges) {
if (not current_mincost_edge.has_value()
or current_mincost_edge->weight >
candidate_edge.weight) { current_mincost_edge = candidate_edge; }

else if (not(
current_mincost_edge->larger_terminal == candidate_edge.larger_terminal and
current_mincost_edge->smaller_terminal == candidate_edge.smaller_terminal
)) {
edges.emplace_back(
current_mincost_edge->smaller_terminal,
current_mincost_edge->larger_terminal,
current_mincost_edge->weight
);
current_mincost_edge = candidate_edge;
}
}
edges.emplace_back(
current_mincost_edge->smaller_terminal,
current_mincost_edge->larger_terminal,
current_mincost_edge->weight
);

return {graph.num_nodes(), graph.terminals(), edges};
}

Graph MehlhornGraphFactory::create_melhorn_graph(const Graph &graph) {
DijkstraGraph dijkstra_graph(graph);
NodeId root_node = dijkstra_graph.add_node(graph.terminals(), std::vector<WeightType>(graph.terminals().size(), 0));
dijkstra_graph.dijkstras_algorithm(root_node);
return create_melhorn_graph(dijkstra_graph, graph);
}

MehlhornGraphFactory::CandidateEdge::CandidateEdge(NodeId terminal_1, NodeId terminal_2, WeightType weight) :
smaller_terminal(std::min(terminal_1, terminal_2)),
larger_terminal(std::max(terminal_1, terminal_2)),
weight(weight) {}

39 changes: 39 additions & 0 deletions MehlhornGraphFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Created by jgier on 20.06.2022.
//

#ifndef HAUPTAUFGABE_2_MEHLHORNGRAPHFACTORY_H
#define HAUPTAUFGABE_2_MEHLHORNGRAPHFACTORY_H


#include "graph/Graph.h"
#include "dijkstra/DijkstraGraph.h"

class [[maybe_unused]] MehlhornGraphFactory {
public:


[[maybe_unused]] static Graph create_melhorn_graph(Graph const &graph);

static Graph create_melhorn_graph(DijkstraGraph const &dijkstra_graph, Graph const &graph);

private:
struct CandidateEdge {
CandidateEdge(NodeId terminal_1, NodeId terminal_2, WeightType weight);

// structuring the edges with smaller and larger terminals makes using them easier, as edges between the same
// nodes are grouped together in sorting.
NodeId smaller_terminal;
NodeId larger_terminal;
WeightType weight;
};

template<typename T>
using TypeToNodeId = NodeId (*)(T const &element);

static void
bucket_sort(std::vector<CandidateEdge> &vector, TypeToNodeId<CandidateEdge> type_to_node_id, NodeId max_id);
};


#endif //HAUPTAUFGABE_2_MEHLHORNGRAPHFACTORY_H
Binary file added PostScript/template.ps
Binary file not shown.
Loading