- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
此问题类似于 BGL: Example of isomorphism with vertex invariants
我正在研究 Boost.Graph tutorial在两个没有属性的图上调用 boost::is_isomorphism 很容易。但是当顶点现在有了名称时,我无法让它工作。
此代码显示:
下面是我如何创建带有命名顶点的路径图(这并不重要,但为了完成显示):
boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
boost::property<
boost::vertex_name_t, std::string
>
>
create_named_vertices_path_graph(
const std::vector<std::string>& names
) noexcept
{
auto g = create_empty_undirected_named_vertices_graph();
if (names.size() == 0) { return g; }
auto vertex_name_map
= get( //not boost::get
boost::vertex_name,
g
);
auto vd_1 = boost::add_vertex(g);
vertex_name_map[vd_1] = *names.begin();
if (names.size() == 1) return g;
const auto j = std::end(names);
auto i = std::begin(names);
for (++i; i!=j; ++i) //Skip first
{
auto vd_2 = boost::add_vertex(g);
vertex_name_map[vd_2] = *i;
const auto aer = boost::add_edge(vd_1, vd_2, g);
assert(aer.second);
vd_1 = vd_2;
}
return g;
}
这是我的测试:
void is_named_vertices_isomorphic_demo() noexcept
{
const auto g = create_named_vertices_path_graph(
{ "Alpha", "Beta", "Gamma" }
);
const auto h = create_named_vertices_path_graph(
{ "Alpha", "Gamma", "Beta" }
);
assert( is_named_vertices_isomorphic(g,g));
assert(!is_named_vertices_isomorphic(g,h));
}
我想或多或少地编写函数 is_named_vertices_isomorphic
(注意:这将编译,但测试失败,灵感来自 BGL: Example of isomorphism with vertex invariants):
template <typename graph1, typename graph2>
bool is_named_vertices_isomorphic_correct(
const graph1& g,
const graph2& h
) noexcept
{
auto ref_index_map = get(boost::vertex_index, g);
using vd = typename boost::graph_traits<graph1>::vertex_descriptor;
std::vector<vd> iso(boost::num_vertices(g));
return boost::isomorphism(g,h,
boost::isomorphism_map(
make_iterator_property_map(iso.begin(), ref_index_map, iso[0])
)
);
}
看问题BGL: Example of isomorphism with vertex invariants让我想到了这个:
template <typename Graph>
std::string discrete_vertex_invariant(
const typename boost::graph_traits<Graph>::vertex_descriptor& vd,
const Graph &g
)
{
const auto name_map = get(boost::vertex_name,g);
return name_map[vd];
}
template <typename Graph>
class discrete_vertex_invariant_functor
{
using vertex_t = typename boost::graph_traits<Graph>::vertex_descriptor;
const Graph& m_graph;
public:
using result_type = std::string;
using argument_type = vertex_t;
discrete_vertex_invariant_functor(const Graph &g) : m_graph(g) {}
result_type operator()(const vertex_t& vd) const
{
return discrete_vertex_invariant(vd,m_graph);
}
result_type max() const
{
return "";
}
};
//helper function to help with argument deduction
template <typename Graph>
discrete_vertex_invariant_functor<Graph> make_discrete_vertex_invariant(
const Graph &g
)
{
return discrete_vertex_invariant_functor<Graph>(g);
}
template <typename graph1, typename graph2>
bool is_named_vertices_isomorphic_correct(
const graph1& g,
const graph2& h
) noexcept
{
auto ref_index_map = get(boost::vertex_index, g);
using vd = typename boost::graph_traits<graph1>::vertex_descriptor;
std::vector<vd> iso(boost::num_vertices(g));
return boost::isomorphism(
g,
h,
isomorphism_map(
make_iterator_property_map(iso.begin(), ref_index_map, iso[0])
).vertex_invariant1(make_discrete_vertex_invariant(g))
.vertex_invariant2(make_discrete_vertex_invariant(h))
);
}
两种解决方案都失败了。谁能帮帮我?
最佳答案
看来您并不追求同构,至少严格按照定义是这样。
如果您实际上希望比较图而不考虑顶点索引顺序,但严格比较顶点名称,则必须将名称映射到整数类型(因为 max_vertex_invariant
值应为无符号整数)。
这里有一个简单的实现方法:
template <typename graph1, typename graph2>
bool is_named_vertices_isomorphic/*_correct*/(const graph1 &g, const graph2 &h) noexcept {
auto ref_index_map = get(boost::vertex_index, g);
using vd = typename boost::graph_traits<graph1>::vertex_descriptor;
std::vector<vd> iso(boost::num_vertices(g));
VertexInvariant::Map shared_names;
VertexInvariant inv1 { g, shared_names };
VertexInvariant inv2 { h, shared_names };
inv1.collect_names();
inv2.collect_names();
return boost::isomorphism(g, h,
boost::isomorphism_map(make_iterator_property_map(iso.begin(), ref_index_map))
.vertex_invariant1(inv1)
.vertex_invariant2(inv2)
);
}
我还没有让事情变得通用,因为它会分散注意力。
For good form, you'd need to use
boost::property_maps::property_traits<boost::property_map<graph1, boost::vertex_name_t>::const_type>::value_type
or similar, and check that the resultant type is actually compatible for comparison betweengraph1
andgraph1
etc.To be "actually" generic you'd want to pass in a deduced property map instead of
boost::get(boost::vertex_name, g)
and so on.To be honest, I feel that this doesn't make much sense for such semantic-laden things as the iso-morphism invariants. You can obviously make things as generic as you need them to be for your application.
struct VertexInvariant {
using Map = std::map<std::string, size_t>;
Graph const& _graph;
Map& _mappings;
using result_type = size_t;
using argument_type = Graph::vertex_descriptor;
size_t operator()(argument_type u) const {
return _mappings.at(boost::get(boost::vertex_name, _graph, u));
}
size_t max() const { return _mappings.size(); }
void collect_names() {
for (auto vd : boost::make_iterator_range(boost::vertices(_graph))) {
size_t next_id = _mappings.size();
auto ins = _mappings.insert({ boost::get(boost::vertex_name, _graph, vd), next_id});
if (ins.second) {
//std::cout << "Mapped '" << ins.first->first << "' to " << ins.first->second << "\n";
}
}
}
};
helper 在哪里VertexInvariant
定义为:
struct VertexInvariant {
using Map = std::map<std::string, size_t>;
Graph const& _graph;
Map& _mappings;
using result_type = size_t;
using argument_type = Graph::vertex_descriptor;
size_t operator()(argument_type u) const {
return _mappings.at(boost::get(boost::vertex_name, _graph, u));
}
size_t max() const { return _mappings.size(); }
void collect_names() {
for (auto vd : boost::make_iterator_range(boost::vertices(_graph))) {
size_t next_id = _mappings.size();
auto ins = _mappings.insert({ boost::get(boost::vertex_name, _graph, vd), next_id});
if (ins.second) {
//std::cout << "Mapped '" << ins.first->first << "' to " << ins.first->second << "\n";
}
}
}
};
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/isomorphism.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
#include <boost/graph/graph_utility.hpp>
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
boost::property<boost::vertex_name_t, std::string> >;
Graph create_empty_undirected_named_vertices_graph() { return {}; }
Graph create_named_vertices_path_graph(const std::vector<std::string> &names) noexcept {
auto g = create_empty_undirected_named_vertices_graph();
if (names.size() == 0) {
return g;
}
auto vertex_name_map = get(boost::vertex_name, g); // not boost::get
auto vd_1 = boost::add_vertex(g);
vertex_name_map[vd_1] = *names.begin();
if (names.size() == 1)
return g;
const auto j = std::end(names);
auto name_it = std::begin(names);
for (++name_it; name_it != j; ++name_it) // Skip first
{
auto vd_2 = boost::add_vertex(g);
vertex_name_map[vd_2] = *name_it;
const auto aer = boost::add_edge(vd_1, vd_2, g);
assert(aer.second);
vd_1 = vd_2;
}
return g;
}
//////////////////////////////////////// {{{
namespace {
struct VertexInvariant {
using Map = std::map<std::string, size_t>;
Graph const& _graph;
Map& _mappings;
using result_type = size_t;
using argument_type = Graph::vertex_descriptor;
size_t operator()(argument_type u) const {
return _mappings.at(boost::get(boost::vertex_name, _graph, u));
}
size_t max() const { return _mappings.size(); }
void collect_names() {
for (auto vd : boost::make_iterator_range(boost::vertices(_graph))) {
size_t next_id = _mappings.size();
auto ins = _mappings.insert({ boost::get(boost::vertex_name, _graph, vd), next_id});
if (ins.second) {
//std::cout << "Mapped '" << ins.first->first << "' to " << ins.first->second << "\n";
}
}
}
};
}
//////////////////////////////////////// }}}
template <typename graph1, typename graph2>
bool is_named_vertices_isomorphic/*_correct*/(const graph1 &g, const graph2 &h) noexcept {
auto ref_index_map = get(boost::vertex_index, g);
using vd = typename boost::graph_traits<graph1>::vertex_descriptor;
std::vector<vd> iso(boost::num_vertices(g));
VertexInvariant::Map shared_names;
VertexInvariant inv1 { g, shared_names };
VertexInvariant inv2 { h, shared_names };
inv1.collect_names();
inv2.collect_names();
return boost::isomorphism(g, h,
boost::isomorphism_map(make_iterator_property_map(iso.begin(), ref_index_map))
.vertex_invariant1(inv1)
.vertex_invariant2(inv2)
);
}
void is_named_vertices_isomorphic_demo() noexcept {
const auto g = create_named_vertices_path_graph({ "Alpha", "Beta", "Gamma" });
std::cout << "\n==== g:\n"; boost::print_graph(g, boost::get(boost::vertex_name, g));
const auto h = create_named_vertices_path_graph({ "Alpha", "Gamma", "Beta" });
std::cout << "\n==== h:\n"; boost::print_graph(h, boost::get(boost::vertex_name, h));
assert(is_named_vertices_isomorphic(g, g));
assert(!is_named_vertices_isomorphic(g, h));
}
int main() { is_named_vertices_isomorphic_demo(); }
打印:
==== g:
Alpha --> Beta
Beta --> Gamma
Gamma -->
==== h:
Alpha --> Gamma
Gamma --> Beta
Beta -->
关于c++ - Boost.Graph 库:如何使用 boost::is_isomorphism 命名顶点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34501216/
我对这两个概念感到困惑:In-graph replication和 Between-graph replication阅读 Replicated training 时在 tensorflow 的官方
我对这两个概念感到困惑:In-graph replication和 Between-graph replication阅读 Replicated training 时在 tensorflow 的官方
我正在尝试使用 https://graph.windows.net/{teantId}/users/[email protected]/thumbnailPhoto?api-version=1.6 访
我正在尝试使用 Graphs.jl 模块从 Julia 中的图中获取子图。我有图,并将其顶点和边存储到列表中,然后我的算法在该列表中移动并删除不属于新子图的节点和边。到这一部分,一切正常,在整个算法之
我是 Arangodb 的新手。我对使用哪个图形 API 感到困惑。我可以在 http://localhost:8529/ url 看到一张图。官方视频讨论了 Gremlin(我也安装了它)。然后就是
截至今天,文档建议使用 Microsoft Graph 而不是 Azure AD Graph API 来访问 Azure AD/B2C 资源。 之前,通过 Azure AD Graph API,我们可
我们希望将 .NET 应用从使用 Azure AD Graph 迁移到 Microsoft Graph API。目前我们正在使用包 Microsoft.WindowsAzure.Configurati
也许我遗漏了什么,但我不知道为什么 GraphQL 的标题中有 graph。 我猜这与 Graph Theory 有关和 graph并且可以看到某种联系,但如果有人能用简单的术语解释它就太好了。 最佳
我正在尝试使用API使用户的Facebook Pages具有已关联的Instagram企业帐户: https://graph.facebook.com/v2.7/me/accounts?field
如何导出我通过调用 GraphPlot 获得的输出的调整大小版本 (或 TreePlot 如果它们产生不同的输出)到 jpg 文件? 目前,我只是调用 Export[file_name, G]在哪里
如何在使用 gremlin 查询创建边缘之前检查边缘是否已存在?如何更新现有边缘而不是删除并重新创建? 最佳答案 我不确定您是否还在寻找答案;然而,简单的答案是 Cosmos DB 在 Gremlin
我使用的是 Xcode 10.2.1 和 macOS Catalina Developer Beta 2。每当我尝试使用内存图调试器时,我都会收到此错误: Memory Graph Debugger:
我正在设置一个机器人以在Facebook页面上自动发布。但是,当我运行脚本时,图形API会引发以下错误: Graph returned an error: (#200) Requires either
如何制定包含非英语字符(例如日耳曼语Umlauts)的Microsoft Graph /myOrganization/users OData查询? 例子: 我的租户中有一个名为“ThomasMülle
我正在寻找发布目标帖子时可以与Facebook Graph API一起使用的国家/州/城市列表。 我在this页面上找到了一个JSON文件,但是该文件无法正确解析,我也怀疑它是否可以用于发布目标,因为
关于 Graph API,帖子的分享数、帖子见解的分享数和页面上显示的分享数不相同。我假设这些代表相同的计数。我的假设错了吗? 来自帖子: https://graph.facebook.com/XXX
我正在尝试访问作为嵌套子站点一部分的列表的项目,如下所示: https://{mytenant}.sharepoint.com/ vendorSiteCollection/ v
我打算开发一个应用程序,但开发人员告诉我每个 IP 每 600 秒有 600 次调用的限制。该应用程序有很多场景,这还不够。有没有办法以某种方式增加限制?或者 Facebook 是否提供任何高级帐户或
我在 Neo4j 中创建了一张伦敦地铁 map 。站点通过 :CONNECTED_TO 关系连接,时间值表示停止之间需要多长时间(目前这些是我为测试输入的随机值)。位于多条线路上的车站每条线路都有一个
我正在尝试拉回所有用户的列表,我的预期结果将是大约 20,000 个用户。 图表似乎将我限制为 1000。 图调用https://graph.microsoft.com/v1.0/users返回 10
我是一名优秀的程序员,十分优秀!