| @@ -0,0 +1,723 @@ | |||||
| /**************************************************************************** | |||||
| * * | |||||
| * Copyright (C) 2019-2020 by Natacha Lambert, David B. Blumenthal and * | |||||
| * Linlin Jia * | |||||
| * * | |||||
| * This file should be used by Python. * | |||||
| * Please call the Python module if you want to use GedLib with this code.* | |||||
| * * | |||||
| * Otherwise, you can directly use GedLib for C++. * | |||||
| * * | |||||
| ***************************************************************************/ | |||||
| /*! | |||||
| * @file GedLibBind.ipp | |||||
| * @brief Classe and function definitions to call easly GebLib in Python without Gedlib's types | |||||
| */ | |||||
| #ifndef GEDLIBBIND_IPP | |||||
| #define GEDLIBBIND_IPP | |||||
| //Include standard libraries + GedLib library | |||||
| // #include <iostream> | |||||
| // #include "GedLibBind.h" | |||||
| // #include "../include/gedlib-master/src/env/ged_env.hpp" | |||||
| //#include "../include/gedlib-master/median/src/median_graph_estimator.hpp" | |||||
| using namespace std; | |||||
| //Definition of types and templates used in this code for my human's memory :). | |||||
| //ged::GEDEnv<UserNodeID, UserNodeLabel, UserEdgeLabel> env; | |||||
| //template<class UserNodeID, class UserNodeLabel, class UserEdgeLabel> struct ExchangeGraph | |||||
| //typedef std::map<std::string, std::string> GXLLabel; | |||||
| //typedef std::string GXLNodeID; | |||||
| namespace pyged { | |||||
| //!< List of available edit cost functions readable by Python. | |||||
| std::vector<std::string> editCostStringOptions = { | |||||
| "CHEM_1", | |||||
| "CHEM_2", | |||||
| "CMU", | |||||
| "GREC_1", | |||||
| "GREC_2", | |||||
| "LETTER", | |||||
| "LETTER2", | |||||
| "NON_SYMBOLIC", | |||||
| "FINGERPRINT", | |||||
| "PROTEIN", | |||||
| "CONSTANT" | |||||
| }; | |||||
| //!< Map of available edit cost functions between enum type in C++ and string in Python | |||||
| std::map<std::string, ged::Options::EditCosts> editCostOptions = { | |||||
| {"CHEM_1", ged::Options::EditCosts::CHEM_1}, | |||||
| {"CHEM_2", ged::Options::EditCosts::CHEM_2}, | |||||
| {"CMU", ged::Options::EditCosts::CMU}, | |||||
| {"GREC_1", ged::Options::EditCosts::GREC_1}, | |||||
| {"GREC_2", ged::Options::EditCosts::GREC_2}, | |||||
| {"LETTER", ged::Options::EditCosts::LETTER}, | |||||
| {"LETTER2", ged::Options::EditCosts::LETTER2}, | |||||
| {"NON_SYMBOLIC", ged::Options::EditCosts::NON_SYMBOLIC}, | |||||
| {"FINGERPRINT", ged::Options::EditCosts::FINGERPRINT}, | |||||
| {"PROTEIN", ged::Options::EditCosts::PROTEIN}, | |||||
| {"CONSTANT", ged::Options::EditCosts::CONSTANT} | |||||
| }; | |||||
| //!< List of available computation methods readable by Python. | |||||
| std::vector<std::string> methodStringOptions = { | |||||
| "BRANCH", | |||||
| "BRANCH_FAST", | |||||
| "BRANCH_TIGHT", | |||||
| "BRANCH_UNIFORM", | |||||
| "BRANCH_COMPACT", | |||||
| "PARTITION", | |||||
| "HYBRID", | |||||
| "RING", | |||||
| "ANCHOR_AWARE_GED", | |||||
| "WALKS", | |||||
| "IPFP", | |||||
| "BIPARTITE", | |||||
| "SUBGRAPH", | |||||
| "NODE", | |||||
| "RING_ML", | |||||
| "BIPARTITE_ML", | |||||
| "REFINE", | |||||
| "BP_BEAM", | |||||
| "SIMULATED_ANNEALING", | |||||
| "HED", | |||||
| "STAR" | |||||
| }; | |||||
| //!< Map of available computation methods readables between enum type in C++ and string in Python | |||||
| std::map<std::string, ged::Options::GEDMethod> methodOptions = { | |||||
| {"BRANCH", ged::Options::GEDMethod::BRANCH}, | |||||
| {"BRANCH_FAST", ged::Options::GEDMethod::BRANCH_FAST}, | |||||
| {"BRANCH_TIGHT", ged::Options::GEDMethod::BRANCH_TIGHT}, | |||||
| {"BRANCH_UNIFORM", ged::Options::GEDMethod::BRANCH_UNIFORM}, | |||||
| {"BRANCH_COMPACT", ged::Options::GEDMethod::BRANCH_COMPACT}, | |||||
| {"PARTITION", ged::Options::GEDMethod::PARTITION}, | |||||
| {"HYBRID", ged::Options::GEDMethod::HYBRID}, | |||||
| {"RING", ged::Options::GEDMethod::RING}, | |||||
| {"ANCHOR_AWARE_GED", ged::Options::GEDMethod::ANCHOR_AWARE_GED}, | |||||
| {"WALKS", ged::Options::GEDMethod::WALKS}, | |||||
| {"IPFP", ged::Options::GEDMethod::IPFP}, | |||||
| {"BIPARTITE", ged::Options::GEDMethod::BIPARTITE}, | |||||
| {"SUBGRAPH", ged::Options::GEDMethod::SUBGRAPH}, | |||||
| {"NODE", ged::Options::GEDMethod::NODE}, | |||||
| {"RING_ML", ged::Options::GEDMethod::RING_ML}, | |||||
| {"BIPARTITE_ML",ged::Options::GEDMethod::BIPARTITE_ML}, | |||||
| {"REFINE",ged::Options::GEDMethod::REFINE}, | |||||
| {"BP_BEAM", ged::Options::GEDMethod::BP_BEAM}, | |||||
| {"SIMULATED_ANNEALING", ged::Options::GEDMethod::SIMULATED_ANNEALING}, | |||||
| {"HED", ged::Options::GEDMethod::HED}, | |||||
| {"STAR" , ged::Options::GEDMethod::STAR}, | |||||
| }; | |||||
| //!<List of available initilaization options readable by Python. | |||||
| std::vector<std::string> initStringOptions = { | |||||
| "LAZY_WITHOUT_SHUFFLED_COPIES", | |||||
| "EAGER_WITHOUT_SHUFFLED_COPIES", | |||||
| "LAZY_WITH_SHUFFLED_COPIES", | |||||
| "EAGER_WITH_SHUFFLED_COPIES" | |||||
| }; | |||||
| //!< Map of available initilaization options readables between enum type in C++ and string in Python | |||||
| std::map<std::string, ged::Options::InitType> initOptions = { | |||||
| {"LAZY_WITHOUT_SHUFFLED_COPIES", ged::Options::InitType::LAZY_WITHOUT_SHUFFLED_COPIES}, | |||||
| {"EAGER_WITHOUT_SHUFFLED_COPIES", ged::Options::InitType::EAGER_WITHOUT_SHUFFLED_COPIES}, | |||||
| {"LAZY_WITH_SHUFFLED_COPIES", ged::Options::InitType::LAZY_WITH_SHUFFLED_COPIES}, | |||||
| {"EAGER_WITH_SHUFFLED_COPIES", ged::Options::InitType::EAGER_WITH_SHUFFLED_COPIES} | |||||
| }; | |||||
| std::vector<std::string> getEditCostStringOptions() { | |||||
| return editCostStringOptions; | |||||
| } | |||||
| std::vector<std::string> getMethodStringOptions() { | |||||
| return methodStringOptions; | |||||
| } | |||||
| std::vector<std::string> getInitStringOptions() { | |||||
| return initStringOptions; | |||||
| } | |||||
| static std::size_t getDummyNode() { | |||||
| return ged::GEDGraph::dummy_node(); | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the enum EditCost which correspond to the string parameter | |||||
| * @param editCost Select one of the predefined edit costs in the list. | |||||
| * @return The edit cost function which correspond in the edit cost functions map. | |||||
| */ | |||||
| ged::Options::EditCosts translateEditCost(std::string editCost) { | |||||
| for (std::size_t i = 0; i != editCostStringOptions.size(); i++) { | |||||
| if (editCostStringOptions[i] == editCost) { | |||||
| return editCostOptions[editCostStringOptions[i]]; | |||||
| } | |||||
| } | |||||
| return ged::Options::EditCosts::CONSTANT; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the enum IniType which correspond to the string parameter | |||||
| * @param initOption Select initialization options. | |||||
| * @return The init Type which correspond in the init options map. | |||||
| */ | |||||
| ged::Options::InitType translateInitOptions(std::string initOption) { | |||||
| for (std::size_t i = 0; i != initStringOptions.size(); i++) { | |||||
| if (initStringOptions[i] == initOption) { | |||||
| return initOptions[initStringOptions[i]]; | |||||
| } | |||||
| } | |||||
| return ged::Options::InitType::EAGER_WITHOUT_SHUFFLED_COPIES; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the string correspond to the enum IniType. | |||||
| * @param initOption Select initialization options. | |||||
| * @return The string which correspond to the enum IniType @p initOption. | |||||
| */ | |||||
| std::string initOptionsToString(ged::Options::InitType initOption) { | |||||
| for (std::size_t i = 0; i != initOptions.size(); i++) { | |||||
| if (initOptions[initStringOptions[i]] == initOption) { | |||||
| return initStringOptions[i]; | |||||
| } | |||||
| } | |||||
| return "EAGER_WITHOUT_SHUFFLED_COPIES"; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the enum Method which correspond to the string parameter | |||||
| * @param method Select the method that is to be used. | |||||
| * @return The computation method which correspond in the edit cost functions map. | |||||
| */ | |||||
| ged::Options::GEDMethod translateMethod(std::string method) { | |||||
| for (std::size_t i = 0; i != methodStringOptions.size(); i++) { | |||||
| if (methodStringOptions[i] == method) { | |||||
| return methodOptions[methodStringOptions[i]]; | |||||
| } | |||||
| } | |||||
| return ged::Options::GEDMethod::STAR; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the vector of values which correspond to the pointer parameter. | |||||
| * @param pointer The size_t pointer to convert. | |||||
| * @return The vector which contains the pointer's values. | |||||
| */ | |||||
| std::vector<size_t> translatePointer(std::size_t* pointer, std::size_t dataSize ) { | |||||
| std::vector<size_t> res; | |||||
| for(std::size_t i = 0; i < dataSize; i++) { | |||||
| res.push_back(pointer[i]); | |||||
| } | |||||
| return res; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the vector of values which correspond to the pointer parameter. | |||||
| * @param pointer The double pointer to convert. | |||||
| * @return The vector which contains the pointer's values. | |||||
| */ | |||||
| std::vector<double> translatePointer(double* pointer, std::size_t dataSize ) { | |||||
| std::vector<double> res; | |||||
| for(std::size_t i = 0; i < dataSize; i++) { | |||||
| res.push_back(pointer[i]); | |||||
| } | |||||
| return res; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the vector of values which correspond to the pointer parameter. | |||||
| * @param pointer The size_t pointer to convert. | |||||
| * @return The vector which contains the pointer's values, with double type. | |||||
| */ | |||||
| std::vector<double> translateAndConvertPointer(std::size_t* pointer, std::size_t dataSize ) { | |||||
| std::vector<double> res; | |||||
| for(std::size_t i = 0; i < dataSize; i++) { | |||||
| res.push_back((double)pointer[i]); | |||||
| } | |||||
| return res; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the string which contains all element of a int list. | |||||
| * @param vector The vector to translate. | |||||
| * @return The string which contains all elements separated with a blank space. | |||||
| */ | |||||
| std::string toStringVectorInt(std::vector<int> vector) { | |||||
| std::string res = ""; | |||||
| for (std::size_t i = 0; i != vector.size(); i++) | |||||
| { | |||||
| res += std::to_string(vector[i]) + " "; | |||||
| } | |||||
| return res; | |||||
| } | |||||
| /*! | |||||
| * @brief Returns the string which contains all element of a unsigned long int list. | |||||
| * @param vector The vector to translate. | |||||
| * @return The string which contains all elements separated with a blank space. | |||||
| */ | |||||
| std::string toStringVectorInt(std::vector<unsigned long int> vector) { | |||||
| std::string res = ""; | |||||
| for (std::size_t i = 0; i != vector.size(); i++) | |||||
| { | |||||
| res += std::to_string(vector[i]) + " "; | |||||
| } | |||||
| return res; | |||||
| } | |||||
| PyGEDEnv::PyGEDEnv () { | |||||
| env_ = new ged::GEDEnv<ged::GXLNodeID, ged::GXLLabel, ged::GXLLabel>(); | |||||
| this->initialized = false; | |||||
| } | |||||
| PyGEDEnv::~PyGEDEnv () { | |||||
| if (env_ != NULL) { | |||||
| delete env_; | |||||
| env_ = NULL; | |||||
| } | |||||
| } | |||||
| // bool initialized = false; //Initialization boolean (because Env has one but not accessible). | |||||
| bool PyGEDEnv::isInitialized() { | |||||
| return initialized; | |||||
| } | |||||
| void PyGEDEnv::restartEnv() { | |||||
| if (env_ != NULL) { | |||||
| delete env_; | |||||
| env_ = NULL; | |||||
| } | |||||
| env_ = new ged::GEDEnv<ged::GXLNodeID, ged::GXLLabel, ged::GXLLabel>(); | |||||
| initialized = false; | |||||
| } | |||||
| void PyGEDEnv::loadGXLGraph(const std::string & pathFolder, const std::string & pathXML, bool node_type, bool edge_type) { | |||||
| std::vector<ged::GEDGraph::GraphID> tmp_graph_ids(env_->load_gxl_graph(pathFolder, pathXML, | |||||
| (node_type ? ged::Options::GXLNodeEdgeType::LABELED : ged::Options::GXLNodeEdgeType::UNLABELED), | |||||
| (edge_type ? ged::Options::GXLNodeEdgeType::LABELED : ged::Options::GXLNodeEdgeType::UNLABELED), | |||||
| std::unordered_set<std::string>(), std::unordered_set<std::string>())); | |||||
| } | |||||
| std::pair<std::size_t,std::size_t> PyGEDEnv::getGraphIds() const { | |||||
| return env_->graph_ids(); | |||||
| } | |||||
| std::vector<std::size_t> PyGEDEnv::getAllGraphIds() { | |||||
| std::vector<std::size_t> listID; | |||||
| for (std::size_t i = env_->graph_ids().first; i != env_->graph_ids().second; i++) { | |||||
| listID.push_back(i); | |||||
| } | |||||
| return listID; | |||||
| } | |||||
| const std::string PyGEDEnv::getGraphClass(std::size_t id) const { | |||||
| return env_->get_graph_class(id); | |||||
| } | |||||
| const std::string PyGEDEnv::getGraphName(std::size_t id) const { | |||||
| return env_->get_graph_name(id); | |||||
| } | |||||
| std::size_t PyGEDEnv::addGraph(const std::string & graph_name, const std::string & graph_class) { | |||||
| ged::GEDGraph::GraphID newId = env_->add_graph(graph_name, graph_class); | |||||
| initialized = false; | |||||
| return std::stoi(std::to_string(newId)); | |||||
| } | |||||
| void PyGEDEnv::addNode(std::size_t graphId, const std::string & nodeId, const std::map<std::string, std::string> & nodeLabel) { | |||||
| env_->add_node(graphId, nodeId, nodeLabel); | |||||
| initialized = false; | |||||
| } | |||||
| /*void addEdge(std::size_t graphId, ged::GXLNodeID tail, ged::GXLNodeID head, ged::GXLLabel edgeLabel) { | |||||
| env_->add_edge(graphId, tail, head, edgeLabel); | |||||
| }*/ | |||||
| void PyGEDEnv::addEdge(std::size_t graphId, const std::string & tail, const std::string & head, const std::map<std::string, std::string> & edgeLabel, bool ignoreDuplicates) { | |||||
| env_->add_edge(graphId, tail, head, edgeLabel, ignoreDuplicates); | |||||
| initialized = false; | |||||
| } | |||||
| void PyGEDEnv::clearGraph(std::size_t graphId) { | |||||
| env_->clear_graph(graphId); | |||||
| initialized = false; | |||||
| } | |||||
| ged::ExchangeGraph<ged::GXLNodeID, ged::GXLLabel, ged::GXLLabel> PyGEDEnv::getGraph(std::size_t graphId) const { | |||||
| return env_->get_graph(graphId); | |||||
| } | |||||
| std::size_t PyGEDEnv::getGraphInternalId(std::size_t graphId) { | |||||
| return getGraph(graphId).id; | |||||
| } | |||||
| std::size_t PyGEDEnv::getGraphNumNodes(std::size_t graphId) { | |||||
| return getGraph(graphId).num_nodes; | |||||
| } | |||||
| std::size_t PyGEDEnv::getGraphNumEdges(std::size_t graphId) { | |||||
| return getGraph(graphId).num_edges; | |||||
| } | |||||
| std::vector<std::string> PyGEDEnv::getGraphOriginalNodeIds(std::size_t graphId) { | |||||
| return getGraph(graphId).original_node_ids; | |||||
| } | |||||
| std::vector<std::map<std::string, std::string>> PyGEDEnv::getGraphNodeLabels(std::size_t graphId) { | |||||
| return getGraph(graphId).node_labels; | |||||
| } | |||||
| std::map<std::pair<std::size_t, std::size_t>, std::map<std::string, std::string>> PyGEDEnv::getGraphEdges(std::size_t graphId) { | |||||
| return getGraph(graphId).edge_labels; | |||||
| } | |||||
| std::vector<std::vector<std::size_t>> PyGEDEnv::getGraphAdjacenceMatrix(std::size_t graphId) { | |||||
| return getGraph(graphId).adj_matrix; | |||||
| } | |||||
| void PyGEDEnv::setEditCost(std::string editCost, std::vector<double> editCostConstants) { | |||||
| env_->set_edit_costs(translateEditCost(editCost), editCostConstants); | |||||
| } | |||||
| void PyGEDEnv::setPersonalEditCost(std::vector<double> editCostConstants) { | |||||
| //env_->set_edit_costs(Your EditCost Class(editCostConstants)); | |||||
| } | |||||
| // void PyGEDEnv::initEnv() { | |||||
| // env_->init(); | |||||
| // initialized = true; | |||||
| // } | |||||
| void PyGEDEnv::initEnv(std::string initOption, bool print_to_stdout) { | |||||
| env_->init(translateInitOptions(initOption), print_to_stdout); | |||||
| initialized = true; | |||||
| } | |||||
| void PyGEDEnv::setMethod(std::string method, const std::string & options) { | |||||
| env_->set_method(translateMethod(method), options); | |||||
| } | |||||
| void PyGEDEnv::initMethod() { | |||||
| env_->init_method(); | |||||
| } | |||||
| double PyGEDEnv::getInitime() const { | |||||
| return env_->get_init_time(); | |||||
| } | |||||
| void PyGEDEnv::runMethod(std::size_t g, std::size_t h) { | |||||
| env_->run_method(g, h); | |||||
| } | |||||
| double PyGEDEnv::getUpperBound(std::size_t g, std::size_t h) const { | |||||
| return env_->get_upper_bound(g, h); | |||||
| } | |||||
| double PyGEDEnv::getLowerBound(std::size_t g, std::size_t h) const { | |||||
| return env_->get_lower_bound(g, h); | |||||
| } | |||||
| std::vector<long unsigned int> PyGEDEnv::getForwardMap(std::size_t g, std::size_t h) const { | |||||
| return env_->get_node_map(g, h).get_forward_map(); | |||||
| } | |||||
| std::vector<long unsigned int> PyGEDEnv::getBackwardMap(std::size_t g, std::size_t h) const { | |||||
| return env_->get_node_map(g, h).get_backward_map(); | |||||
| } | |||||
| std::size_t PyGEDEnv::getNodeImage(std::size_t g, std::size_t h, std::size_t nodeId) const { | |||||
| return env_->get_node_map(g, h).image(nodeId); | |||||
| } | |||||
| std::size_t PyGEDEnv::getNodePreImage(std::size_t g, std::size_t h, std::size_t nodeId) const { | |||||
| return env_->get_node_map(g, h).pre_image(nodeId); | |||||
| } | |||||
| double PyGEDEnv::getInducedCost(std::size_t g, std::size_t h) const { | |||||
| return env_->get_node_map(g, h).induced_cost(); | |||||
| } | |||||
| std::vector<pair<std::size_t, std::size_t>> PyGEDEnv::getNodeMap(std::size_t g, std::size_t h) { | |||||
| std::vector<pair<std::size_t, std::size_t>> res; | |||||
| std::vector<ged::NodeMap::Assignment> relation; | |||||
| env_->get_node_map(g, h).as_relation(relation); | |||||
| for (const auto & assignment : relation) { | |||||
| res.push_back(std::make_pair(assignment.first, assignment.second)); | |||||
| } | |||||
| return res; | |||||
| } | |||||
| std::vector<std::vector<int>> PyGEDEnv::getAssignmentMatrix(std::size_t g, std::size_t h) { | |||||
| std::vector<std::vector<int>> res; | |||||
| for(std::size_t i = 0; i != getForwardMap(g, h).size(); i++) { | |||||
| std::vector<int> newLine; | |||||
| bool have1 = false; | |||||
| for(std::size_t j = 0; j != getBackwardMap(g, h).size(); j++) { | |||||
| if (getNodeImage(g, h, i) == j) { | |||||
| newLine.push_back(1); | |||||
| have1 = true; | |||||
| } | |||||
| else{ | |||||
| newLine.push_back(0); | |||||
| } | |||||
| } | |||||
| if(have1) { | |||||
| newLine.push_back(0); | |||||
| } | |||||
| else{ | |||||
| newLine.push_back(1); | |||||
| } | |||||
| res.push_back(newLine); | |||||
| } | |||||
| std::vector<int> lastLine; | |||||
| for (size_t k = 0; k != getBackwardMap(g,h).size(); k++) { | |||||
| if (getBackwardMap(g,h)[k] == ged::GEDGraph::dummy_node()) { | |||||
| lastLine.push_back(1); | |||||
| } | |||||
| else{ | |||||
| lastLine.push_back(0); | |||||
| } | |||||
| } | |||||
| res.push_back(lastLine); | |||||
| return res; | |||||
| } | |||||
| std::vector<std::vector<unsigned long int>> PyGEDEnv::getAllMap(std::size_t g, std::size_t h) { | |||||
| std::vector<std::vector<unsigned long int>> res; | |||||
| res.push_back(getForwardMap(g, h)); | |||||
| res.push_back(getBackwardMap(g,h)); | |||||
| return res; | |||||
| } | |||||
| double PyGEDEnv::getRuntime(std::size_t g, std::size_t h) const { | |||||
| return env_->get_runtime(g, h); | |||||
| } | |||||
| bool PyGEDEnv::quasimetricCosts() const { | |||||
| return env_->quasimetric_costs(); | |||||
| } | |||||
| std::vector<std::vector<size_t>> PyGEDEnv::hungarianLSAP(std::vector<std::vector<std::size_t>> matrixCost) { | |||||
| std::size_t nrows = matrixCost.size(); | |||||
| std::size_t ncols = matrixCost[0].size(); | |||||
| std::size_t *rho = new std::size_t[nrows], *varrho = new std::size_t[ncols]; | |||||
| std::size_t *u = new std::size_t[nrows], *v = new std::size_t[ncols]; | |||||
| std::size_t *C = new std::size_t[nrows*ncols]; | |||||
| // std::size_t i = 0, j; | |||||
| for (std::size_t i = 0; i < nrows; i++) { | |||||
| for (std::size_t j = 0; j < ncols; j++) { | |||||
| C[j*nrows+i] = matrixCost[i][j]; | |||||
| } | |||||
| } | |||||
| lsape::hungarianLSAP<std::size_t>(C,nrows,ncols,rho,u,v,varrho); | |||||
| std::vector<std::vector<size_t>> res; | |||||
| res.push_back(translatePointer(rho, nrows)); | |||||
| res.push_back(translatePointer(varrho, ncols)); | |||||
| res.push_back(translatePointer(u, nrows)); | |||||
| res.push_back(translatePointer(v, ncols)); | |||||
| return res; | |||||
| } | |||||
| std::vector<std::vector<double>> PyGEDEnv::hungarianLSAPE(std::vector<std::vector<double>> matrixCost) { | |||||
| std::size_t nrows = matrixCost.size(); | |||||
| std::size_t ncols = matrixCost[0].size(); | |||||
| std::size_t *rho = new std::size_t[nrows-1], *varrho = new std::size_t[ncols-1]; | |||||
| double *u = new double[nrows], *v = new double[ncols]; | |||||
| double *C = new double[nrows*ncols]; | |||||
| for (std::size_t i = 0; i < nrows; i++) { | |||||
| for (std::size_t j = 0; j < ncols; j++) { | |||||
| C[j*nrows+i] = matrixCost[i][j]; | |||||
| } | |||||
| } | |||||
| lsape::hungarianLSAPE<double,std::size_t>(C,nrows,ncols,rho,varrho,u,v); | |||||
| std::vector<std::vector<double>> res; | |||||
| res.push_back(translateAndConvertPointer(rho, nrows-1)); | |||||
| res.push_back(translateAndConvertPointer(varrho, ncols-1)); | |||||
| res.push_back(translatePointer(u, nrows)); | |||||
| res.push_back(translatePointer(v, ncols)); | |||||
| return res; | |||||
| } | |||||
| std::size_t PyGEDEnv::getNumNodeLabels() const { | |||||
| return env_->num_node_labels(); | |||||
| } | |||||
| std::map<std::string, std::string> PyGEDEnv::getNodeLabel(std::size_t label_id) const { | |||||
| return env_->get_node_label(label_id); | |||||
| } | |||||
| std::size_t PyGEDEnv::getNumEdgeLabels() const { | |||||
| return env_->num_edge_labels(); | |||||
| } | |||||
| std::map<std::string, std::string> PyGEDEnv::getEdgeLabel(std::size_t label_id) const { | |||||
| return env_->get_edge_label(label_id); | |||||
| } | |||||
| // std::size_t PyGEDEnv::getNumNodes(std::size_t graph_id) const { | |||||
| // return env_->get_num_nodes(graph_id); | |||||
| // } | |||||
| double PyGEDEnv::getAvgNumNodes() const { | |||||
| return env_->get_avg_num_nodes(); | |||||
| } | |||||
| double PyGEDEnv::getNodeRelCost(const std::map<std::string, std::string> & node_label_1, const std::map<std::string, std::string> & node_label_2) const { | |||||
| return env_->node_rel_cost(node_label_1, node_label_2); | |||||
| } | |||||
| double PyGEDEnv::getNodeDelCost(const std::map<std::string, std::string> & node_label) const { | |||||
| return env_->node_del_cost(node_label); | |||||
| } | |||||
| double PyGEDEnv::getNodeInsCost(const std::map<std::string, std::string> & node_label) const { | |||||
| return env_->node_ins_cost(node_label); | |||||
| } | |||||
| std::map<std::string, std::string> PyGEDEnv::getMedianNodeLabel(const std::vector<std::map<std::string, std::string>> & node_labels) const { | |||||
| return env_->median_node_label(node_labels); | |||||
| } | |||||
| double PyGEDEnv::getEdgeRelCost(const std::map<std::string, std::string> & edge_label_1, const std::map<std::string, std::string> & edge_label_2) const { | |||||
| return env_->edge_rel_cost(edge_label_1, edge_label_2); | |||||
| } | |||||
| double PyGEDEnv::getEdgeDelCost(const std::map<std::string, std::string> & edge_label) const { | |||||
| return env_->edge_del_cost(edge_label); | |||||
| } | |||||
| double PyGEDEnv::getEdgeInsCost(const std::map<std::string, std::string> & edge_label) const { | |||||
| return env_->edge_ins_cost(edge_label); | |||||
| } | |||||
| std::map<std::string, std::string> PyGEDEnv::getMedianEdgeLabel(const std::vector<std::map<std::string, std::string>> & edge_labels) const { | |||||
| return env_->median_edge_label(edge_labels); | |||||
| } | |||||
| std::string PyGEDEnv::getInitType() const { | |||||
| return initOptionsToString(env_->get_init_type()); | |||||
| } | |||||
| double PyGEDEnv::computeInducedCost(std::size_t g_id, std::size_t h_id, std::vector<pair<std::size_t, std::size_t>> relation) const { | |||||
| ged::NodeMap node_map = ged::NodeMap(env_->get_num_nodes(g_id), env_->get_num_nodes(h_id)); | |||||
| for (const auto & assignment : relation) { | |||||
| node_map.add_assignment(assignment.first, assignment.second); | |||||
| // std::cout << assignment.first << assignment.second << endl; | |||||
| } | |||||
| const std::vector<ged::GEDGraph::NodeID> forward_map = node_map.get_forward_map(); | |||||
| for (std::size_t i{0}; i < node_map.num_source_nodes(); i++) { | |||||
| if (forward_map.at(i) == ged::GEDGraph::undefined_node()) { | |||||
| node_map.add_assignment(i, ged::GEDGraph::dummy_node()); | |||||
| } | |||||
| } | |||||
| const std::vector<ged::GEDGraph::NodeID> backward_map = node_map.get_backward_map(); | |||||
| for (std::size_t i{0}; i < node_map.num_target_nodes(); i++) { | |||||
| if (backward_map.at(i) == ged::GEDGraph::undefined_node()) { | |||||
| node_map.add_assignment(ged::GEDGraph::dummy_node(), i); | |||||
| } | |||||
| } | |||||
| // for (auto & map : node_map.get_forward_map()) { | |||||
| // std::cout << map << ", "; | |||||
| // } | |||||
| // std::cout << endl; | |||||
| // for (auto & map : node_map.get_backward_map()) { | |||||
| // std::cout << map << ", "; | |||||
| // } | |||||
| env_->compute_induced_cost(g_id, h_id, node_map); | |||||
| return node_map.induced_cost(); | |||||
| } | |||||
| // double PyGEDEnv::getNodeCost(std::size_t label1, std::size_t label2) const { | |||||
| // return env_->ged_data_node_cost(label1, label2); | |||||
| // } | |||||
| /*void medianLetter(pathFolder, pathXML, editCost, method, options="", initOption = "EAGER_WITHOUT_SHUFFLED_COPIES") { | |||||
| if(isInitialized()) { | |||||
| restartEnv(); | |||||
| } | |||||
| setEditCost(editCost);*/ | |||||
| /*std::string letter_class("A"); | |||||
| if (argc > 1) { | |||||
| letter_class = std::string(argv[1]); | |||||
| }*/ | |||||
| //std::string seed("0"); | |||||
| /*if (argc > 2) { | |||||
| seed = std::string(argv[2]); | |||||
| }*/ | |||||
| /*loadGXLGraph(pathFolder, pathXML); | |||||
| std::vector<std::size_t> graph_ids = getAllGraphIds(); | |||||
| std::size_t median_id = env_->add_graph("median", ""); | |||||
| initEnv(initOption); | |||||
| setMethod(method); | |||||
| ged::MedianGraphEstimator<ged::GXLNodeID, ged::GXLLabel, ged::GXLLabel> median_estimator(&env, false); | |||||
| median_estimator.set_options("--init-type RANDOM --randomness PSEUDO --seed " + seed); | |||||
| median_estimator.run(graph_ids, median_id); | |||||
| std::string gxl_file_name("../output/gen_median_Letter_HIGH_" + letter_class + ".gxl"); | |||||
| env_->save_as_gxl_graph(median_id, gxl_file_name);*/ | |||||
| /*std::string tikz_file_name("../output/gen_median_Letter_HIGH_" + letter_class + ".tex"); | |||||
| save_letter_graph_as_tikz_file(env_->get_graph(median_id), tikz_file_name);*/ | |||||
| //} | |||||
| } | |||||
| #endif /* SRC_GEDLIB_BIND_IPP */ | |||||
| // namespace shapes { | |||||
| // // Default constructor | |||||
| // Rectangle::Rectangle () {} | |||||
| // // Overloaded constructor | |||||
| // Rectangle::Rectangle (int x0, int y0, int x1, int y1) { | |||||
| // this->x0 = x0; | |||||
| // this->y0 = y0; | |||||
| // this->x1 = x1; | |||||
| // this->y1 = y1; | |||||
| // } | |||||
| // // Destructor | |||||
| // Rectangle::~Rectangle () {} | |||||
| // // Return the area of the rectangle | |||||
| // int Rectangle::getArea () { | |||||
| // return (this->x1 - this->x0) * (this->y1 - this->y0); | |||||
| // } | |||||
| // // Get the size of the rectangle. | |||||
| // // Put the size in the pointer args | |||||
| // void Rectangle::getSize (int *width, int *height) { | |||||
| // (*width) = x1 - x0; | |||||
| // (*height) = y1 - y0; | |||||
| // } | |||||
| // // Move the rectangle by dx dy | |||||
| // void Rectangle::move (int dx, int dy) { | |||||
| // this->x0 += dx; | |||||
| // this->y0 += dy; | |||||
| // this->x1 += dx; | |||||
| // this->y1 += dy; | |||||
| // } | |||||
| // } | |||||