Skip to content

Commit

Permalink
added subgraph computation algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
SJulianS committed May 8, 2024
1 parent 12d39dd commit 0324065
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// MIT License
//
// Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
// Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
// Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
// Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#pragma once

#include "hal_core/defines.h"
#include "hal_core/utilities/result.h"

#include <igraph/igraph.h>
#include <set>

namespace hal
{
class Gate;

namespace graph_algorithm
{
class NetlistGraph;

/**
* Compute the subgraph induced by the specified gates, including all edges between the corresponding vertices.
*
* @param[in] graph - The netlist graph.
* @param[in] subgraph_gates - A vector of gates that make up the subgraph.
* @returns The subgraph as a new netlist graph on success, an error otherwise.
*/
Result<std::unique_ptr<NetlistGraph>> get_subgraph(NetlistGraph* graph, const std::vector<Gate*>& subgraph_gates);

/**
* Compute the subgraph induced by the specified vertices, including all edges between these vertices.
*
* @param[in] graph - The netlist graph.
* @param[in] subgraph_vertices - A vector of vertices that make up the subgraph.
* @returns The subgraph as a new netlist graph on success, an error otherwise.
*/
Result<std::unique_ptr<NetlistGraph>> get_subgraph(NetlistGraph* graph, const std::vector<u32>& subgraph_vertices);

/**
* Compute the subgraph induced by the specified vertices, including all edges between these vertices.
*
* @param[in] graph - The netlist graph.
* @param[in] subgraph_vertices - An igraph vector of vertices that make up the subgraph.
* @returns The subgraph as a new netlist graph on success, an error otherwise.
*/
Result<std::unique_ptr<NetlistGraph>> get_subgraph_igraph(NetlistGraph* graph, const igraph_vector_int_t* subgraph_vertices);
} // namespace graph_algorithm
} // namespace hal
51 changes: 51 additions & 0 deletions plugins/graph_algorithm/python/python_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "graph_algorithm/algorithms/components.h"
#include "graph_algorithm/algorithms/neighborhood.h"
#include "graph_algorithm/algorithms/subgraph.h"
#include "graph_algorithm/netlist_graph.h"
#include "graph_algorithm/plugin_graph_algorithm.h"

Expand Down Expand Up @@ -527,6 +528,56 @@ namespace hal
:rtype: list[list[int]] or None
)");

m.def(
"get_subgraph",
[](graph_algorithm::NetlistGraph* graph, const std::vector<Gate*>& subgraph_gates) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
auto res = graph_algorithm::get_subgraph(graph, subgraph_gates);
if (res.is_ok())
{
return res.get();
}
else
{
log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
return std::nullopt;
}
},
py::arg("graph"),
py::arg("subgraph_gates"),
R"(
Compute the subgraph induced by the specified gates, including all edges between the corresponding vertices.
:param graph_algorithm.NetlistGraph graph: The netlist graph.
:param list[hal_py.Gate] subgraph_gates: A list of gates that make up the subgraph.
:returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
:rtype: graph_algorithm.NetlistGraph or None
)");

m.def(
"get_subgraph",
[](graph_algorithm::NetlistGraph* graph, const std::vector<u32>& subgraph_vertices) -> std::optional<std::unique_ptr<graph_algorithm::NetlistGraph>> {
auto res = graph_algorithm::get_subgraph(graph, subgraph_vertices);
if (res.is_ok())
{
return res.get();
}
else
{
log_error("python_context", "error encountered while computing subgraph:\n{}", res.get_error().get());
return std::nullopt;
}
},
py::arg("graph"),
py::arg("subgraph_vertices"),
R"(
Compute the subgraph induced by the specified vertices, including all edges between these vertices.
:param graph_algorithm.NetlistGraph graph: The netlist graph.
:param list[int] subgraph_vertices: A list of vertices that make up the subgraph.
:returns: The subgraph as a new netlist graph on success, ``None`` otherwise.
:rtype: graph_algorithm.NetlistGraph or None
)");

// .def("get_communities", &GraphAlgorithmPlugin::get_communities, py::arg("netlist"), R"(
// Get a dict of community IDs to communities. Each community is represented by a set of gates.

Expand Down
134 changes: 134 additions & 0 deletions plugins/graph_algorithm/src/algorithms/subgraph.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "graph_algorithm/algorithms/subgraph.h"

#include "graph_algorithm/netlist_graph.h"
#include "hal_core/netlist/gate.h"

namespace hal
{
namespace graph_algorithm
{
Result<std::unique_ptr<NetlistGraph>> get_subgraph(NetlistGraph* graph, const std::vector<Gate*>& subgraph_gates)
{
if (graph == nullptr)
{
return ERR("graph is a nullptr");
}

if (subgraph_gates.empty())
{
return ERR("no subgraph gates provided");
}

igraph_vector_int_t i_gates;
if (auto res = graph->get_vertices_from_gates_igraph(subgraph_gates); res.is_ok())
{
i_gates = std::move(res.get());
}
else
{
return ERR(res.get_error());
}

auto res = get_subgraph_igraph(graph, &i_gates);

igraph_vector_int_destroy(&i_gates);

if (res.is_error())
{
return ERR(res.get_error());
}

return res;
}

Result<std::unique_ptr<NetlistGraph>> get_subgraph(NetlistGraph* graph, const std::vector<u32>& subgraph_vertices)
{
if (graph == nullptr)
{
return ERR("graph is a nullptr");
}

if (subgraph_vertices.empty())
{
return ERR("no subgraph vertices provided");
}

igraph_vector_int_t i_gates;
if (auto res = igraph_vector_int_init(&i_gates, subgraph_vertices.size()); res != IGRAPH_SUCCESS)
{
return ERR(igraph_strerror(res));
}

for (u32 i = 0; i < subgraph_vertices.size(); i++)
{
VECTOR(i_gates)[i] = subgraph_vertices.at(i);
}

auto res = get_subgraph_igraph(graph, &i_gates);

igraph_vector_int_destroy(&i_gates);

if (res.is_error())
{
return ERR(res.get_error());
}

return res;
}

Result<std::unique_ptr<NetlistGraph>> get_subgraph_igraph(NetlistGraph* graph, const igraph_vector_int_t* subgraph_vertices)
{
if (graph == nullptr)
{
return ERR("graph is a nullptr");
}

igraph_vs_t v_sel;
if (auto res = igraph_vs_vector(&v_sel, subgraph_vertices); res != IGRAPH_SUCCESS)
{
return ERR(igraph_strerror(res));
}

u32 subgraph_size = igraph_vector_int_size(subgraph_vertices);

igraph_vector_int_t i_vertex_map;
if (auto res = igraph_vector_int_init(&i_vertex_map, subgraph_size); res != IGRAPH_SUCCESS)
{
igraph_vs_destroy(&v_sel);
return ERR(igraph_strerror(res));
}

igraph_t i_subg;
if (const auto res = igraph_induced_subgraph_map(graph->get_graph(), &i_subg, v_sel, IGRAPH_SUBGRAPH_AUTO, nullptr, &i_vertex_map); res != IGRAPH_SUCCESS)
{
igraph_vs_destroy(&v_sel);
igraph_vector_int_destroy(&i_vertex_map);
return ERR(igraph_strerror(res));
}

std::unordered_map<u32, Gate*> nodes_to_gates;
if (const auto res = graph->get_gates_from_vertices_igraph(&i_vertex_map); res.is_ok())
{
std::vector<Gate*> gates = res.get();
for (u32 i = 0; i < gates.size(); i++)
{
nodes_to_gates[i] = gates.at(i);
}
}
else
{
igraph_destroy(&i_subg);
igraph_vs_destroy(&v_sel);
igraph_vector_int_destroy(&i_vertex_map);
return ERR(res.get_error());
}

auto subgraph = std::unique_ptr<NetlistGraph>(new NetlistGraph(graph->get_netlist(), std::move(i_subg), std::move(nodes_to_gates)));

igraph_vs_destroy(&v_sel);
igraph_vector_int_destroy(&i_vertex_map);

return OK(std::move(subgraph));
}
} // namespace graph_algorithm
} // namespace hal

0 comments on commit 0324065

Please sign in to comment.