Commit 5a014198 authored by jonasseidel's avatar jonasseidel
Browse files

hopefully final test update

parent 72919e86
......@@ -24,13 +24,17 @@ gather_data_to_csv
graph_display
data
test_sets
nincidences_nedges_cyclic
execute_single_test
Images*
connector-capacity_decentralization_clusters_aggregated_networks
nedges_nepochs_cut_networks
nincidences_nedges
share-of-critical_dummy_constant_nincidences
nsteps_nepochs
nincidences_nedges_cyclic
nnodes_nedges
share-of-critical_dummy_network_connectors_buffer
nepochs_decentralization_clusters_aggregated_networks
nsteps_nepochs
nsteps_nepochs_multiple_sources
share-of-critical_connector-capacity_network_connectors_buffer
share-of-critical_dummy
execute_single_test
share-of-critical_dummy_constant_nincidences
share-of-critical_dummy_edge_compensated
thread_test
......@@ -43,10 +43,10 @@ Edge::Edge(std::istream& is, const std::unordered_map<std::string, Node* >& name
IO_THROW(curr, "}");
}
void Edge::update_autolabel(std::string prefix){
void Edge::update_autolabel(std::string prefix, std::string suffix){
if((this->from() == nullptr) || (this->to() == nullptr)) throw std::runtime_error("cannot set autolabel if edge has dangleing connections");
std::stringstream name;
name << prefix << this->from()->description() << "_" << this->to()->description();
name << prefix << this->from()->description() << "_" << this->to()->description() << suffix;
this->description() = name.str();
}
......
......@@ -36,7 +36,7 @@ public:
return this->_description;
}
void update_autolabel(std::string prefix = "");
void update_autolabel(std::string prefix = "", std::string suffix = "");
Node* from() const {
return this->_from;
......
......@@ -11,7 +11,7 @@ random_graph_generator::random_graph_generator(
random_attribute_generator structure_graph_node_tipping_attribute_generator,
random_attribute_generator cluster_edge_tipping_attribute_generator,
random_attribute_generator cluster_node_tipping_attribute_generator)
: _structure_graph_tipping_parameters(structure_graph_tipping_parameters),
: _structure_graph_tipping_parameters(structure_graph_tipping_parameters),
_structure_graph_node_generator(structure_graph_node_generator), _structure_graph_edge_generator(structure_graph_edge_generator),
_cluster_tipping_parameters(cluster_tipping_parameters),
_cluster_node_generator(cluster_node_generator), _cluster_edge_generator(cluster_edge_generator),
......
random_graph_generator& random_graph_generator::operator>>(Graph& var){
var = std::get<5>(this->next());
return *this;
......@@ -33,7 +34,9 @@ std::tuple<std::pair<Node*, Node*>, std::unordered_set<Edge*>, std::unordered_se
}else{
e->reconnect(cluster_st.second, e->to());
}
e->update_autolabel();
std::stringstream suffix;
suffix << "__" << e;
e->update_autolabel("", suffix.str());
}
structure_graph.remove_node(n);
......@@ -42,6 +45,12 @@ std::tuple<std::pair<Node*, Node*>, std::unordered_set<Edge*>, std::unordered_se
aggregated_subnetwork_cores.insert(local_core_network.begin(), local_core_network.end());
}
std::cout << "generation resulted in networks of size:" << std::endl;
std::cout << "core_network: " << core_network.size() << std::endl;
std::cout << "aggregated_subnetwork_cores: " << aggregated_subnetwork_cores.size() << std::endl;
std::cout << "aggregated_subnetworks: " << aggregated_subnetworks.size() << std::endl;
std::cout << "network_connectors: " << network_connectors.size() << std::endl;
std::cout << "complete.size(): " << structure_graph.size().nodes << "," << structure_graph.size().edges << std::endl;
return {std::move(st), std::move(core_network), std::move(aggregated_subnetwork_cores), std::move(aggregated_subnetworks), std::move(network_connectors), std::move(structure_graph)};
}
......@@ -57,77 +66,122 @@ std::tuple<std::pair<Node*, Node*>, std::unordered_set<Edge*>, Graph> random_gra
Node* source = nullptr;
Node* target = nullptr;
if(!tipping_parameters.tip) return {std::pair{source, target}, std::move(core_network), std::move(g)};
if(tipping_parameters.only_tip_fringes){
// connect those nodes to start that have no incoming edges / connect those nodes to target that have no outgoing edges
if(tipping_parameters.only_tip_extreme_layer){
// tips first and last layer
try{
auto [source_, target_] = g.tip_fringes(node_steps.front(), node_steps.back(), edge_attribute_generator, node_attribute_generator, tipping_parameters.shelter_orphans);
source = source_;
target = target_;
}catch(std::invalid_argument& e){
size_t longest_path = 0;
for(Node* n1 : node_steps.front()){
for(Node* n2 : node_steps.back()){
Path curr_path = g.directed_admissible_st_path(n1,n2);
if(curr_path.exists() && curr_path.number_of_edges() > longest_path){
longest_path = curr_path.number_of_edges();
source = n1;
target = n2;
if(!tipping_parameters.tip){
// choose those as source / target that offer the best forward/backward reachibility
size_t best_forward_reachability = 0;
g.for_nodes([&g, &source, &best_forward_reachability](Node* n){
size_t counter = 0;
g.conditional_bfs_all_reachable(
[](Node* from, Edge* via, bool used_in_traversal){},
[&counter](Edge* via, Node* node){
++counter;
return false;
},
{n},
false,
[](const Node* from, const Edge* via){return (via->from() == from);}
);
if(counter >= best_forward_reachability){
best_forward_reachability = counter;
source = n;
}
});
size_t best_backwards_reachability = 0;
g.for_nodes([&g, &target, &best_backwards_reachability](Node* n){
size_t counter = 0;
g.conditional_bfs_all_reachable(
[](Node* from, Edge* via, bool used_in_traversal){},
[&counter](Edge* via, Node* node){
++counter;
return false;
},
{n},
false,
[](const Node* from, const Edge* via){return (via->to() == from);}
);
if(counter >= best_backwards_reachability){
best_backwards_reachability = counter;
target = n;
}
});
if(!g.directed_admissible_st_path(source,target).exists()){
std::cerr << "source / target combination is a unconnected pair; restarting local network generation" << std::endl;
return generate_flow_network(tipping_parameters, edge_generator, node_generator, edge_attribute_generator, node_attribute_generator, node_index_start);
}
}else{
if(tipping_parameters.only_tip_fringes){
// connect those nodes to start that have no incoming edges / connect those nodes to target that have no outgoing edges
if(tipping_parameters.only_tip_extreme_layer){
// tips first and last layer
try{
auto [source_, target_] = g.tip_fringes(node_steps.front(), node_steps.back(), edge_attribute_generator, node_attribute_generator, tipping_parameters.shelter_orphans);
source = source_;
target = target_;
}catch(std::invalid_argument& e){
size_t longest_path = 0;
for(Node* n1 : node_steps.front()){
for(Node* n2 : node_steps.back()){
Path curr_path = g.directed_admissible_st_path(n1,n2);
if(curr_path.exists() && curr_path.number_of_edges() > longest_path){
longest_path = curr_path.number_of_edges();
source = n1;
target = n2;
}
}
}
}
}
}else{
// tips all fringes
try{
auto [source_, target_] = g.tip_fringes(edge_attribute_generator, node_attribute_generator, tipping_parameters.shelter_orphans);
source = source_;
target = target_;
}catch(std::invalid_argument& e){
size_t longest_path = 0;
for(Node* n1 : g.nodes()){
for(Node* n2 : g.nodes()){
Path curr_path = g.directed_admissible_st_path(n1,n2);
if(curr_path.exists() && curr_path.number_of_edges() > longest_path){
longest_path = curr_path.number_of_edges();
source = n1;
target = n2;
}else{
// tips all fringes
try{
auto [source_, target_] = g.tip_fringes(edge_attribute_generator, node_attribute_generator, tipping_parameters.shelter_orphans);
source = source_;
target = target_;
}catch(std::invalid_argument& e){
size_t longest_path = 0;
for(Node* n1 : g.nodes()){
for(Node* n2 : g.nodes()){
Path curr_path = g.directed_admissible_st_path(n1,n2);
if(curr_path.exists() && curr_path.number_of_edges() > longest_path){
longest_path = curr_path.number_of_edges();
source = n1;
target = n2;
}
}
}
}
}
}
if( (source == nullptr) || (target == nullptr) ) {source = *node_steps.front().begin(); target = *node_steps.back().begin();}
}else{
// tips nodes regardless of if they have incoming or outgoing edges
assert(tipping_parameters.only_tip_extreme_layer);
// only those nodes of the first and last generated layers (tipping just everything doesn't make sense)
Node* s = g.add_node(std::to_string(g.lifetime_node_count()), node_attribute_generator.next());
Node* t = g.add_node(std::to_string(g.lifetime_node_count()), node_attribute_generator.next());
for(Node* n : node_steps.front()){
if((n == s) || (n == t)) continue;
if(!tipping_parameters.shelter_orphans && (n->incident().size() == 0)) continue;
std::stringstream name;
name << s->description() << "_" << n->description();
g.add_edge(s, n, name.str(), edge_attribute_generator.next());
}
for(Node* n : node_steps.back()){
if((n == s) || (n == t)) continue;
if(!tipping_parameters.shelter_orphans && (n->incident().size() == 0)) continue;
std::stringstream name;
name << n->description() << "_" << t->description();
g.add_edge(n, t, name.str(), edge_attribute_generator.next());
}
if( (source == nullptr) || (target == nullptr) ) {source = *node_steps.front().begin(); target = *node_steps.back().begin();}
}else{
// tips nodes regardless of if they have incoming or outgoing edges
assert(tipping_parameters.only_tip_extreme_layer);
// only those nodes of the first and last generated layers (tipping just everything doesn't make sense)
Node* s = g.add_node(std::to_string(g.lifetime_node_count()), node_attribute_generator.next());
Node* t = g.add_node(std::to_string(g.lifetime_node_count()), node_attribute_generator.next());
for(Node* n : node_steps.front()){
if((n == s) || (n == t)) continue;
if(!tipping_parameters.shelter_orphans && (n->incident().size() == 0)) continue;
std::stringstream name;
name << s->description() << "_" << n->description();
g.add_edge(s, n, name.str(), edge_attribute_generator.next());
}
for(Node* n : node_steps.back()){
if((n == s) || (n == t)) continue;
if(!tipping_parameters.shelter_orphans && (n->incident().size() == 0)) continue;
std::stringstream name;
name << n->description() << "_" << t->description();
g.add_edge(n, t, name.str(), edge_attribute_generator.next());
}
source = s;
target = t;
source = s;
target = t;
}
}
source->add_attribute("Source", Attribute({fix, 1, Integral}) );
target->add_attribute("Target", Attribute({fix, 1, Integral}) );
......@@ -199,7 +253,7 @@ std::unordered_set<Edge*> random_graph_generator::connect_random(
}
std::stringstream name;
name << from->description() << "_" << to->description();
name << from->description() << "_" << to->description() << "__" << subgraph_superunionunion.lifetime_edge_count();
added_edges.insert(subgraph_superunionunion.add_edge(from, to, name.str(), edge_attribute_generator.next()));
}
return added_edges;
......
......@@ -124,10 +124,10 @@ private:
return {const_cast<Graph*>(this)->nodes().size(), const_cast<Graph*>(this)->edges().size()};
}
size_t& lifetime_node_counter() {
virtual size_t& lifetime_node_counter() {
return this->_lifetime_node_counter;
}
size_t& lifetime_edge_counter() {
virtual size_t& lifetime_edge_counter() {
return this->_lifetime_edge_counter;
}
......@@ -178,10 +178,10 @@ public:
// inlineable
size_t lifetime_node_count() const {
return this->_lifetime_node_counter;
return const_cast<Graph*>(this)->lifetime_node_counter();
}
size_t lifetime_edge_count() const {
return this->_lifetime_edge_counter;
return const_cast<Graph*>(this)->lifetime_edge_counter();
}
bool contains(const Node* node) const {
......
#include "Node.h"
#include "../Common/io_format.h"
#include "Edge.h"
std::unordered_set<Edge*> Node::incoming(){
std::unordered_set<Edge*> incoming_edges;
for(Edge* e : this->incident()){
if(e->to() == this){
incoming_edges.insert(e);
}
}
return incoming_edges;
}
std::unordered_set<Edge*> Node::outgoing(){
std::unordered_set<Edge*> outgoing_edges;
for(Edge* e : this->incident()){
if(e->from() == this){
outgoing_edges.insert(e);
}
}
return outgoing_edges;
}
Node::Node(std::istream& is){
......
......@@ -93,6 +93,11 @@ public:
}
return iter->second;
}
std::unordered_set<Edge*> incoming();
std::unordered_set<Edge*> outgoing();
/*
bool is_target() const;
......
......@@ -74,6 +74,14 @@ class SubGraph : private Graph {
std::unordered_set<Edge*>& local_edges = const_cast<SubGraph*>(this)->local_edges();
return std::unordered_set<const Edge*>(local_edges.begin(), local_edges.end());
}
size_t& lifetime_node_counter() {
return this->supergraph()->lifetime_node_counter();
}
size_t& lifetime_edge_counter() {
return this->supergraph()->lifetime_edge_counter();
}
protected:
friend Graph;
public:
......@@ -107,6 +115,14 @@ public:
return Graph::export_edges();
}
size_t lifetime_node_count() const {
return Graph::lifetime_node_count();
}
size_t lifetime_edge_count() const {
return Graph::lifetime_edge_count();
}
bool contains(Node* node){
return Graph::contains(node);
}
......
CXX := g++-10
CXXFLAGS := -O0 -g -std=c++17 #-Wall -Wextra -Wpedantic
CXXFLAGS := -O0 -g -std=c++20 #-Wall -Wextra -Wpedantic
LIBSCIPOPT := /usr/lib/libscip.so.7.0.2.0
LIBORTOOLS := /usr/lib/libortools.so
......@@ -15,7 +15,7 @@ GRAPH_OUT := $(patsubst %.cpp,%.o,$(shell find -wholename "./Graphtheory/*.cpp")
LP_OUT := $(filter-out %lp_generator.o,$(patsubst %.cpp,%.o,$(shell find -wholename "./Linear_Programming/*.cpp")))
LP_PROBLEMS_OUT := $(patsubst %.cpp,%.o,$(shell find -wholename "./Specialization/LP_Problems/*.cpp" ! -wholename "*retired*"))
COMMON_OUT := $(patsubst %.cpp,%.o,$(shell find -wholename "./Common/*.cpp"))
TESTS_OUT := $(patsubst %.cpp,%.o,$(shell find -wholename "./tests/*.cpp"))
TESTS_OUT := $(patsubst %.cpp,%.o,$(shell find -wholename "./tests/*.cpp" | grep -v "probe_test.cpp"))
targets := graph_test ass_test linear_program_test maintenance_problem_test benders_test scip_test preprocessor_test $(TESTS_OUT:.o=)
......@@ -51,7 +51,7 @@ linear_program_test.o: linear_programming_test.cpp ./Linear_Programming/Linear_P
maintenance_problem_test: maintenance_problem_test.o $(LP_PROBLEMS_OUT) $(LP_OUT) $(GRAPH_OUT) Linear_Programming/lp_generator.o $(LIBSCIPOPT) $(LIBORTOOLS) $(COMMON_OUT)
$(CXX) $(CXXFLAGS) $^ -o $@
$(CXX) $(CXXFLAGS) $^ -o $@ -lpthread
maintenance_problem_test.o: maintenance_problem_test.cpp ./Specialization/LP_Problems/Maintenance_Problem/maintenance_problem_generator.o $(GRAPH_DEP) $(COMMON_DEP) $(LP_DEP) $(LP_PROBLEMS_DEP)
$(CXX) $(CXXFLAGS) -c $< -o $@
......@@ -74,12 +74,18 @@ preprocessor_test: preprocessor_test.o
preprocessor_test.o: preprocessor_test.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
thread_test: thread_test.o
$(CXX) $(CXXFLAGS) $^ -o $@ -pthread
thread_test.o: thread_test.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
.SECONDEXPANSION: TESTING
$(TESTS_OUT:.o=): $$(addsuffix .o, $$@) $(LP_PROBLEMS_OUT) $(LP_OUT) $(GRAPH_OUT) Linear_Programming/lp_generator.o $(LIBSCIPOPT) $(LIBORTOOLS) $(COMMON_OUT)
$(CXX) $(CXXFLAGS) $^ -o $@
$(CXX) $(CXXFLAGS) $^ -o $@ -lpthread
.SECONDEXPANSION: TESTING_O
$(TESTS_OUT): $$(patsubst %.o,%.cpp,$$@)
$(TESTS_OUT) probe_test.o: $$(patsubst %.o,%.cpp,$$@)
$(CXX) $(CXXFLAGS) -c $< -o $@
#gather_data_to_csv: gather_data_to_csv.o $(LP_PROBLEMS_OUT) $(LP_OUT) $(GRAPH_OUT) Linear_Programming/lp_generator.o $(LIBSCIPOPT) $(LIBORTOOLS) $(COMMON_OUT)
......@@ -106,7 +112,10 @@ $(GRAPH_OUT) $(LP_OUT) $(LP_PROBLEMS_OUT) $(COMMON_OUT): $$(patsubst %.o,%.cpp,$
.PHONY: clean
.PHONY: clean clean_tests
clean:
rm -f $(targets) a.out $(shell find -name "*.o") $(shell find -name "*.gch")
clean_tests:
rm -f $(shell find -wholename "./tests/*.o") $(TESTS_OUT:.o=)
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <ctime>
#include <filesystem>
#include <chrono>
bool redo(Data& data){
bool decide = false;
for( auto [formulation, exec_vector] : data.derived_performance ){
for( const Derived_Performance_Data& derived_performance : exec_vector ){
if( derived_performance.gap.second > CMP_EPS ){
decide = true;
}
}
}
bool execute_tests(std::filesystem::path path, bool check_all_problem_data, bool add_new_execution){
std::cerr << "-----------------> execution started in " << path.string() << std::endl;
std::string curr;
// execution function
std::function<bool(Data&)> exec = [check_all_problem_data, add_new_execution](Data& data){
bool all_succeeded = true;
// determining derived problem data
Derived_Problem_Data& derived_prob_data = data.derived_problem;
// number_of_edges
SET_VARIABLE(derived_prob_data, number_of_edges, data.mp.network().size().edges);
// number_of_nodes
SET_VARIABLE(derived_prob_data, number_of_nodes, data.mp.network().size().nodes);
// avg incid per node
double avg_incid_per_node_val = 2*(double)data.mp.network().size().edges/data.mp.network().size().nodes;
SET_VARIABLE(derived_prob_data, avg_incid_per_node, avg_incid_per_node_val);
// number_of_critical_edges
size_t number_of_critical_edges_val = 0;
data.mp.network().for_edges([&number_of_critical_edges_val](const Edge* e){
if(e->attribute_throwing("Selected").value()) number_of_critical_edges_val++;
});
SET_VARIABLE(derived_prob_data, number_of_critical_edges, number_of_critical_edges_val);
// share_of_critical
double share_of_critical_val = (double)number_of_critical_edges_val/data.mp.network().size().edges;
SET_VARIABLE(derived_prob_data, share_of_critical, share_of_critical_val);
// number_of_epochs
SET_VARIABLE(derived_prob_data, number_of_epochs, data.mp.number_of_epochs());
// path_length_lower_bound
auto shortest_path = data.mp.network().directed_admissible_st_path(data.mp.source(), data.mp.target(), [](const Node* from, const Edge* via){return (via->to(from) == via->to()); });
size_t path_length_lower_bound_val;
if(shortest_path.exists()){
path_length_lower_bound_val = shortest_path.number_of_edges();
}else{
std::cerr << "problem execution: no connecting path could be found (variable shortest_path set to \"SIZE_MAX\")" << std::endl;
path_length_lower_bound_val = SIZE_MAX;
if(decide){
decide:
std::cout << "Do you want to include partially unsolved data? [y/redo/mark(save but mark)/skip/print(you will be prompted again)/show(you will be prompted again)]" << std::endl;
while( std::getline(std::cin, curr) && curr != "y" && curr != "redo" && curr != "mark" && curr != "skip" && curr != "print" && curr != "show"){
std::cout << "Do you want to include partially unsolved data? [y/redo/mark(save but mark)/skip/print(you will be prompted again)/show(you will be prompted again)]" << std::endl;
}
SET_VARIABLE(derived_prob_data, path_length_lower_bound, path_length_lower_bound_val);
if(curr == "y"){
return false;
}else if(curr == "redo"){
std::cerr << "recalculating" << std::endl;
return true;
}else if(curr == "mark"){
data.marked = true;
return false;
}else if(curr == "print"){
std::cout << data.mp << std::endl;
goto decide;
}else if(curr == "show"){
std::ofstream ofs_netw("tmp.netw");
ofs_netw << data.mp.network() << std::endl;
ofs_netw.close();
system("./graph_display --file tmp.netw &");
goto decide;
}
std::cout << "invalid choice!" << std::endl;
goto decide;
throw std::runtime_error("unreachable");
}
std::vector<SCIP*> computational_models = data.mp.all_computational_models();
return !data.values_complete();
}
for(SCIP* current_scip : computational_models){
auto scip_iterator = data.derived_performance.find(SCIPgetProbName(current_scip));
if(scip_iterator == data.derived_performance.end()) {
auto [new_scip_iterator, success] = data.derived_performance.insert({SCIPgetProbName(current_scip), std::vector<Derived_Performance_Data>()});
assert(success);
scip_iterator = new_scip_iterator;
}
auto& [name, exec_vector] = *scip_iterator;
if(!add_new_execution && exec_vector.size() != 0
&& exec_vector.back().time_in_sec.first
&& exec_vector.back().number_of_bnb_runs.first
&& exec_vector.back().number_of_reopt_runs.first
&& exec_vector.back().number_of_nodes_explored.first
&& exec_vector.back().max_depth.first
&& exec_vector.back().dual_bound.first
&& exec_vector.back().primal_bound.first
&& exec_vector.back().gap.first
&& exec_vector.back().number_of_primal_sols.first)
{
std::cerr << "problem execution: skipping execution of " << SCIPgetProbName(current_scip) << " due to it having been previously executed" << std::endl;
continue;
}
struct exec_data{
Data* data_ptr;
bool check_all_problem_data;
bool add_new_execution;
};
void* execute(void* info_ptr){
exec_data* info = (exec_data*) info_ptr;
Data& data = *info->data_ptr;
bool check_all_problem_data = info->check_all_problem_data;
bool add_new_execution = info->add_new_execution;
usleep(200);
bool all_succeeded = true;
// determining derived problem data
Derived_Problem_Data& derived_prob_data = data.derived_problem;
// number_of_edges
SET_VARIABLE(derived_prob_data, number_of_edges, data.mp.network().size().edges);
// number_of_nodes
SET_VARIABLE(derived_prob_data, number_of_nodes, data.mp.network().size().nodes);
// avg incid per node
double avg_incid_per_node_val = 2*(double)data.mp.network().size().edges/data.mp.network().size().nodes;
SET_VARIABLE(derived_prob_data, avg_incid_per_node, avg_incid_per_node_val);
// number_of_critical_edges
size_t number_of_critical_edges_val = 0;
data.mp.network().for_edges([&number_of_critical_edges_val](const Edge* e){
if(e->attribute_throwing("Selected").value()) number_of_critical_edges_val++;
});
SET_VARIABLE(derived_prob_data, number_of_critical_edges, number_of_critical_edges_val);
// share_of_critical
double share_of_critical_val = (double)number_of_critical_edges_val/data.mp.network().size().edges;
SET_VARIABLE(derived_prob_data, share_of_critical, share_of_critical_val);
// number_of_epochs
SET_VARIABLE(derived_prob_data, number_of_epochs, data.mp.number_of_epochs());
// path_length_lower_bound
auto shortest_path = data.mp.network().directed_admissible_st_path(data.mp.source(), data.mp.target(), [](const Node* from, const Edge* via){return (via->to(from) == via->to()); });
size_t path_length_lower_bound_val;
if(shortest_path.exists()){
path_length_lower_bound_val = shortest_path.number_of_edges();
}else{
std::cerr << "problem execution: no connecting path could be found (variable shortest_path set to \"SIZE_MAX\")" << std::endl;
path_length_lower_bound_val = SIZE_MAX;
}
SET_VARIABLE(derived_prob_data, path_length_lower_bound, path_length_lower_bound_val);
std::cerr << "---------------->" << SCIPgetProbName(current_scip) << ":" << std::endl;
SCIPsolve(current_scip);
std::vector<SCIP*> computational_models = data.mp.all_computational_models();
if(add_new_execution || exec_vector.size() == 0){
exec_vector.push_back({});
}
Derived_Performance_Data& performance_container = exec_vector.back();
for(SCIP* current_scip : computational_models){
auto scip_iterator = data.derived_performance.find(SCIPgetProbName(current_scip));
if(scip_iterator == data.derived_performance.end()) {
auto [new_scip_iterator, success] = data.derived_performance.insert({SCIPgetProbName(current_scip), std::vector<Derived_Performance_Data>()});
assert(success);