Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tiago Peixoto
graph-tool
Commits
f4a24fcb
Commit
f4a24fcb
authored
Sep 21, 2017
by
Tiago Peixoto
Browse files
Reorganize graph/inference source tree
parent
aeea89f7
Pipeline
#357
failed with stage
in 410 minutes and 49 seconds
Changes
77
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
f4a24fcb
...
...
@@ -19,7 +19,7 @@ AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([foreign])
AM_INIT_AUTOMAKE([foreign
subdir-objects
])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AM_PROG_CC_C_O
AC_CONFIG_HEADERS([config.h])
...
...
src/graph/inference/Makefile.am
View file @
f4a24fcb
...
...
@@ -15,76 +15,83 @@ libgraph_tool_inference_la_LIBADD = $(MOD_LIBADD)
libgraph_tool_inference_la_LDFLAGS
=
$(MOD_LDFLAGS)
libgraph_tool_inference_la_SOURCES
=
\
cache.cc
\
graph_blockmodel.cc
\
graph_blockmodel_imp.cc
\
graph_blockmodel_imp2.cc
\
graph_blockmodel_em.cc
\
graph_blockmodel_exhaustive.cc
\
graph_blockmodel_gibbs.cc
\
graph_blockmodel_layers.cc
\
graph_blockmodel_layers_imp.cc
\
graph_blockmodel_layers_exhaustive.cc
\
graph_blockmodel_layers_gibbs.cc
\
graph_blockmodel_layers_mcmc.cc
\
graph_blockmodel_layers_merge.cc
\
graph_blockmodel_layers_multicanonical.cc
\
graph_blockmodel_layers_multicanonical_multiflip.cc
\
graph_blockmodel_layers_multiflip_mcmc.cc
\
graph_blockmodel_layers_overlap.cc
\
graph_blockmodel_layers_overlap_exhaustive.cc
\
graph_blockmodel_layers_overlap_mcmc.cc
\
graph_blockmodel_layers_overlap_mcmc_bundled.cc
\
graph_blockmodel_layers_overlap_multiflip_mcmc.cc
\
graph_blockmodel_layers_overlap_gibbs.cc
\
graph_blockmodel_layers_overlap_multicanonical.cc
\
graph_blockmodel_layers_overlap_multicanonical_multiflip.cc
\
graph_blockmodel_layers_overlap_vacate.cc
\
graph_blockmodel_marginals.cc
\
graph_blockmodel_mcmc.cc
\
graph_blockmodel_multicanonical.cc
\
graph_blockmodel_multicanonical_multiflip.cc
\
graph_blockmodel_multiflip_mcmc.cc
\
graph_blockmodel_merge.cc
\
graph_blockmodel_overlap.cc
\
graph_blockmodel_overlap_exhaustive.cc
\
graph_blockmodel_overlap_gibbs.cc
\
graph_blockmodel_overlap_mcmc.cc
\
graph_blockmodel_overlap_mcmc_bundled.cc
\
graph_blockmodel_overlap_multicanonical.cc
\
graph_blockmodel_overlap_multicanonical_multiflip.cc
\
graph_blockmodel_overlap_multiflip_mcmc.cc
\
graph_blockmodel_overlap_vacate.cc
\
graph_modularity.cc
\
blockmodel/graph_blockmodel.cc
\
blockmodel/graph_blockmodel_em.cc
\
blockmodel/graph_blockmodel_exhaustive.cc
\
blockmodel/graph_blockmodel_gibbs.cc
\
blockmodel/graph_blockmodel_imp.cc
\
blockmodel/graph_blockmodel_imp2.cc
\
blockmodel/graph_blockmodel_marginals.cc
\
blockmodel/graph_blockmodel_mcmc.cc
\
blockmodel/graph_blockmodel_merge.cc
\
blockmodel/graph_blockmodel_multicanonical.cc
\
blockmodel/graph_blockmodel_multicanonical_multiflip.cc
\
blockmodel/graph_blockmodel_multiflip_mcmc.cc
\
overlap/graph_blockmodel_overlap.cc
\
overlap/graph_blockmodel_overlap_exhaustive.cc
\
overlap/graph_blockmodel_overlap_gibbs.cc
\
overlap/graph_blockmodel_overlap_mcmc.cc
\
overlap/graph_blockmodel_overlap_mcmc_bundled.cc
\
overlap/graph_blockmodel_overlap_multicanonical.cc
\
overlap/graph_blockmodel_overlap_multicanonical_multiflip.cc
\
overlap/graph_blockmodel_overlap_multiflip_mcmc.cc
\
overlap/graph_blockmodel_overlap_vacate.cc
\
layers/graph_blockmodel_layers.cc
\
layers/graph_blockmodel_layers_exhaustive.cc
\
layers/graph_blockmodel_layers_gibbs.cc
\
layers/graph_blockmodel_layers_imp.cc
\
layers/graph_blockmodel_layers_mcmc.cc
\
layers/graph_blockmodel_layers_merge.cc
\
layers/graph_blockmodel_layers_multicanonical.cc
\
layers/graph_blockmodel_layers_multicanonical_multiflip.cc
\
layers/graph_blockmodel_layers_multiflip_mcmc.cc
\
layers/graph_blockmodel_layers_overlap.cc
\
layers/graph_blockmodel_layers_overlap_exhaustive.cc
\
layers/graph_blockmodel_layers_overlap_gibbs.cc
\
layers/graph_blockmodel_layers_overlap_mcmc.cc
\
layers/graph_blockmodel_layers_overlap_mcmc_bundled.cc
\
layers/graph_blockmodel_layers_overlap_multicanonical.cc
\
layers/graph_blockmodel_layers_overlap_multicanonical_multiflip.cc
\
layers/graph_blockmodel_layers_overlap_multiflip_mcmc.cc
\
layers/graph_blockmodel_layers_overlap_vacate.cc
\
support/cache.cc
\
support/int_part.cc
\
support/spence.cc
\
graph_inference.cc
\
int_part.cc
\
spence.cc
graph_modularity.cc
libgraph_tool_inference_la_include_HEADERS
=
\
bundled_vacate_loop.hh
\
cache.hh
\
exhaustive_loop.hh
\
gibbs_loop.hh
\
graph_blockmodel.hh
\
graph_blockmodel_em.hh
\
graph_blockmodel_exhaustive.hh
\
graph_blockmodel_gibbs.hh
\
graph_blockmodel_layers.hh
\
graph_blockmodel_layers_util.hh
\
graph_blockmodel_mcmc.hh
\
graph_blockmodel_merge.hh
\
graph_blockmodel_multicanonical.hh
\
graph_blockmodel_multiflip_mcmc.hh
\
graph_blockmodel_overlap.hh
\
graph_blockmodel_overlap_mcmc_bundled.hh
\
graph_blockmodel_overlap_util.hh
\
graph_blockmodel_overlap_vacate.hh
\
graph_blockmodel_util.hh
\
blockmodel/graph_blockmodel.hh
\
blockmodel/graph_blockmodel_em.hh
\
blockmodel/graph_blockmodel_emat.hh
\
blockmodel/graph_blockmodel_elist.hh
\
blockmodel/graph_blockmodel_entries.hh
\
blockmodel/graph_blockmodel_entropy.hh
\
blockmodel/graph_blockmodel_exhaustive.hh
\
blockmodel/graph_blockmodel_gibbs.hh
\
blockmodel/graph_blockmodel_mcmc.hh
\
blockmodel/graph_blockmodel_merge.hh
\
blockmodel/graph_blockmodel_multicanonical.hh
\
blockmodel/graph_blockmodel_multiflip_mcmc.hh
\
blockmodel/graph_blockmodel_partition.hh
\
blockmodel/graph_blockmodel_util.hh
\
blockmodel/graph_blockmodel_weights.hh
\
graph_modularity.hh
\
graph_neighbour_sampler.hh
\
graph_state.hh
\
mcmc_loop.hh
\
merge_loop.hh
\
parallel_rng.hh
\
int_part.hh
\
util.hh
layers/graph_blockmodel_layers.hh
\
layers/graph_blockmodel_layers_util.hh
\
loops/bundled_vacate_loop.hh
\
loops/exhaustive_loop.hh
\
loops/gibbs_loop.hh
\
loops/mcmc_loop.hh
\
loops/merge_loop.hh
\
overlap/graph_blockmodel_overlap.hh
\
overlap/graph_blockmodel_overlap_mcmc_bundled.hh
\
overlap/graph_blockmodel_overlap_util.hh
\
overlap/graph_blockmodel_overlap_vacate.hh
\
overlap/graph_blockmodel_overlap_partition.hh
\
support/cache.hh
\
support/graph_neighbour_sampler.hh
\
support/graph_state.hh
\
support/int_part.hh
\
support/parallel_rng.hh
\
support/util.hh
src/graph/inference/graph_blockmodel.cc
→
src/graph/inference/
blockmodel/
graph_blockmodel.cc
View file @
f4a24fcb
...
...
@@ -22,7 +22,6 @@
#include
"graph_blockmodel_util.hh"
#include
"graph_blockmodel.hh"
#include
"graph_state.hh"
using
namespace
boost
;
using
namespace
graph_tool
;
...
...
src/graph/inference/graph_blockmodel.hh
→
src/graph/inference/
blockmodel/
graph_blockmodel.hh
View file @
f4a24fcb
...
...
@@ -22,7 +22,7 @@
#include
<vector>
#include
"graph_state.hh"
#include
"
../support/
graph_state.hh"
#include
"graph_blockmodel_util.hh"
#include
"openmp_lock.hh"
...
...
@@ -54,23 +54,10 @@ inline simple_degs_t uncheck(boost::any& amap, simple_degs_t*)
return
any_cast
<
simple_degs_t
>
(
amap
);
}
typedef
mpl
::
vector2
<
std
::
true_type
,
std
::
false_type
>
bool_tr
;
typedef
mpl
::
vector2
<
vcmap_t
,
vmap_t
>
vweight_tr
;
typedef
mpl
::
vector2
<
ecmap_t
,
emap_t
>
eweight_tr
;
enum
weight_type
{
NONE
,
COUNT
,
REAL_EXPONENTIAL
,
REAL_NORMAL
,
DISCRETE_GEOMETRIC
,
DISCRETE_POISSON
,
DISCRETE_BINOMIAL
,
DELTA_T
};
#define BLOCK_STATE_params \
((g, &, all_graph_views, 1)) \
((is_weighted,, bool_tr, 1)) \
...
...
@@ -573,16 +560,6 @@ public:
}
}
size_t
get_B_E
()
{
return
_B_E
;
}
size_t
get_B_E_D
()
{
return
_B_E_D
;
}
void
remove_partition_node
(
size_t
v
,
size_t
r
)
{
assert
(
size_t
(
_b
[
v
])
==
r
);
...
...
@@ -2422,6 +2399,16 @@ public:
_emat
.
sync
(
_bg
);
}
size_t
get_B_E
()
{
return
_B_E
;
}
size_t
get_B_E_D
()
{
return
_B_E_D
;
}
size_t
get_N
()
{
size_t
N
=
0
;
...
...
src/graph/inference/blockmodel/graph_blockmodel_elist.hh
0 → 100644
View file @
f4a24fcb
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2017 Tiago de Paula Peixoto <tiago@skewed.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_BLOCKMODEL_ELIST_HH
#define GRAPH_BLOCKMODEL_ELIST_HH
#include
"../generation/sampler.hh"
#include
"../generation/dynamic_sampler.hh"
namespace
graph_tool
{
// ====================================
// Construct and manage half-edge lists
// ====================================
//the following guarantees a stable (source, target) ordering even for
//undirected graphs
template
<
class
Edge
,
class
Graph
>
inline
typename
graph_traits
<
Graph
>::
vertex_descriptor
get_source
(
const
Edge
&
e
,
const
Graph
&
g
)
{
if
(
is_directed
::
apply
<
Graph
>::
type
::
value
)
return
source
(
e
,
g
);
return
std
::
min
(
source
(
e
,
g
),
target
(
e
,
g
));
}
template
<
class
Edge
,
class
Graph
>
inline
typename
graph_traits
<
Graph
>::
vertex_descriptor
get_target
(
const
Edge
&
e
,
const
Graph
&
g
)
{
if
(
is_directed
::
apply
<
Graph
>::
type
::
value
)
return
target
(
e
,
g
);
return
std
::
max
(
source
(
e
,
g
),
target
(
e
,
g
));
}
template
<
class
Graph
,
class
Weighted
>
class
EGroups
{
public:
template
<
class
Vprop
,
class
Eprop
,
class
BGraph
>
void
init
(
Vprop
b
,
Eprop
eweight
,
Graph
&
g
,
BGraph
&
bg
)
{
_egroups
.
clear
();
_egroups
.
resize
(
num_vertices
(
bg
));
for
(
auto
e
:
edges_range
(
g
))
{
_epos
[
e
]
=
make_pair
(
numeric_limits
<
size_t
>::
max
(),
numeric_limits
<
size_t
>::
max
());
insert_edge
(
e
,
eweight
[
e
],
b
,
g
);
}
}
void
clear
()
{
_egroups
.
clear
();
}
bool
empty
()
{
return
_egroups
.
empty
();
}
template
<
class
Vprop
>
bool
check
(
Vprop
b
,
Graph
&
g
)
{
for
(
size_t
r
=
0
;
r
<
_egroups
.
size
();
++
r
)
{
auto
&
edges
=
_egroups
[
r
];
for
(
size_t
i
=
0
;
i
<
edges
.
size
();
++
i
)
{
const
auto
&
e
=
edges
[
i
];
if
(
!
is_valid
(
i
,
edges
))
continue
;
if
(
size_t
(
b
[
source
(
get
<
0
>
(
e
),
g
)])
!=
r
&&
size_t
(
b
[
target
(
get
<
0
>
(
e
),
g
)])
!=
r
)
{
assert
(
false
);
return
false
;
}
}
}
return
true
;
}
template
<
class
Edge
>
bool
is_valid
(
size_t
i
,
DynamicSampler
<
Edge
>&
elist
)
{
return
elist
.
is_valid
(
i
);
}
template
<
class
Edge
>
bool
is_valid
(
size_t
,
vector
<
Edge
>&
)
{
return
true
;
}
template
<
class
Edge
,
class
Vprop
>
void
insert_edge
(
const
Edge
&
e
,
size_t
weight
,
Vprop
&
b
,
Graph
&
g
)
{
size_t
r
=
b
[
get_source
(
e
,
g
)];
auto
&
r_elist
=
_egroups
[
r
];
insert_edge
(
std
::
make_tuple
(
e
,
true
),
r_elist
,
weight
,
_epos
[
e
].
first
);
size_t
s
=
b
[
get_target
(
e
,
g
)];
auto
&
s_elist
=
_egroups
[
s
];
insert_edge
(
std
::
make_tuple
(
e
,
false
),
s_elist
,
weight
,
_epos
[
e
].
second
);
}
template
<
class
Edge
,
class
EV
>
void
insert_edge
(
const
Edge
&
e
,
EV
&
elist
,
size_t
,
size_t
&
pos
)
{
if
(
pos
<
elist
.
size
()
&&
elist
[
pos
]
==
e
)
return
;
assert
(
pos
>=
elist
.
size
()
||
elist
[
pos
]
!=
e
);
elist
.
push_back
(
e
);
pos
=
elist
.
size
()
-
1
;
}
template
<
class
Edge
>
void
insert_edge
(
const
Edge
&
e
,
DynamicSampler
<
Edge
>&
elist
,
size_t
weight
,
size_t
&
pos
)
{
if
((
pos
<
elist
.
size
()
&&
elist
.
is_valid
(
pos
)
&&
elist
[
pos
]
==
e
)
||
weight
==
0
)
return
;
assert
(
pos
>=
elist
.
size
()
||
!
elist
.
is_valid
(
pos
)
||
elist
[
pos
]
!=
e
);
pos
=
elist
.
insert
(
e
,
weight
);
}
template
<
class
Edge
,
class
Vprop
>
void
remove_edge
(
const
Edge
&
e
,
Vprop
&
b
,
Graph
&
g
)
{
auto
&
pos
=
_epos
[
e
];
size_t
r
=
b
[
get_source
(
e
,
g
)];
remove_edge
(
make_tuple
(
e
,
true
),
pos
.
first
,
_egroups
[
r
]);
size_t
s
=
b
[
get_target
(
e
,
g
)];
remove_edge
(
make_tuple
(
e
,
false
),
pos
.
second
,
_egroups
[
s
]);
}
template
<
class
Edge
>
void
remove_edge
(
const
Edge
&
e
,
size_t
pos
,
vector
<
Edge
>&
elist
)
{
if
(
pos
>=
elist
.
size
()
||
elist
[
pos
]
!=
e
)
return
;
if
(
get
<
1
>
(
elist
.
back
()))
_epos
[
get
<
0
>
(
elist
.
back
())].
first
=
pos
;
else
_epos
[
get
<
0
>
(
elist
.
back
())].
second
=
pos
;
if
(
get
<
1
>
(
elist
[
pos
]))
_epos
[
get
<
0
>
(
elist
[
pos
])].
first
=
numeric_limits
<
size_t
>::
max
();
else
_epos
[
get
<
0
>
(
elist
[
pos
])].
second
=
numeric_limits
<
size_t
>::
max
();
elist
[
pos
]
=
elist
.
back
();
elist
.
pop_back
();
}
template
<
class
Edge
>
void
remove_edge
(
const
Edge
&
e
,
size_t
pos
,
DynamicSampler
<
Edge
>&
elist
)
{
if
(
pos
>=
elist
.
size
()
||
elist
[
pos
]
!=
e
)
return
;
if
(
get
<
1
>
(
elist
[
pos
]))
_epos
[
get
<
0
>
(
elist
[
pos
])].
first
=
numeric_limits
<
size_t
>::
max
();
else
_epos
[
get
<
0
>
(
elist
[
pos
])].
second
=
numeric_limits
<
size_t
>::
max
();
elist
.
remove
(
pos
);
}
template
<
class
Vertex
,
class
VProp
>
void
remove_vertex
(
Vertex
v
,
VProp
&
b
,
Graph
&
g
)
{
if
(
_egroups
.
empty
())
return
;
// update the half-edge lists
for
(
auto
e
:
out_edges_range
(
v
,
g
))
remove_edge
(
e
,
b
,
g
);
for
(
auto
e
:
in_edges_range
(
v
,
g
))
remove_edge
(
e
,
b
,
g
);
}
template
<
class
Vertex
,
class
Vprop
,
class
Eprop
>
void
add_vertex
(
Vertex
v
,
Vprop
&
b
,
Eprop
&
eweight
,
Graph
&
g
)
{
if
(
_egroups
.
empty
())
return
;
//update the half-edge lists
for
(
auto
e
:
out_edges_range
(
v
,
g
))
insert_edge
(
e
,
eweight
[
e
],
b
,
g
);
for
(
auto
e
:
in_edges_range
(
v
,
g
))
insert_edge
(
e
,
eweight
[
e
],
b
,
g
);
}
template
<
class
Edge
,
class
RNG
>
const
auto
&
sample_edge
(
const
DynamicSampler
<
Edge
>&
elist
,
RNG
&
rng
)
{
return
get
<
0
>
(
elist
.
sample
(
rng
));
}
template
<
class
Edge
,
class
RNG
>
const
auto
&
sample_edge
(
const
vector
<
Edge
>&
elist
,
RNG
&
rng
)
{
return
get
<
0
>
(
uniform_sample
(
elist
,
rng
));
}
template
<
class
Vertex
,
class
RNG
>
const
auto
&
sample_edge
(
Vertex
r
,
RNG
&
rng
)
{
return
sample_edge
(
_egroups
[
r
],
rng
);
}
private:
typedef
typename
std
::
conditional
<
Weighted
::
value
,
DynamicSampler
<
std
::
tuple
<
typename
graph_traits
<
Graph
>::
edge_descriptor
,
bool
>>
,
vector
<
std
::
tuple
<
typename
graph_traits
<
Graph
>::
edge_descriptor
,
bool
>>>::
type
sampler_t
;
vector
<
sampler_t
>
_egroups
;
typedef
typename
eprop_map_t
<
pair
<
size_t
,
size_t
>>::
type
epos_t
;
epos_t
_epos
;
};
}
// namespace graph_tool
#endif //GRAPH_BLOCKMODEL_ELIST_HH
src/graph/inference/graph_blockmodel_em.cc
→
src/graph/inference/
blockmodel/
graph_blockmodel_em.cc
View file @
f4a24fcb
...
...
@@ -21,7 +21,7 @@
#include
<boost/python.hpp>
#include
"graph_blockmodel_em.hh"
#include
"graph_state.hh"
#include
"
../support/
graph_state.hh"
using
namespace
boost
;
using
namespace
graph_tool
;
...
...
src/graph/inference/graph_blockmodel_em.hh
→
src/graph/inference/
blockmodel/
graph_blockmodel_em.hh
View file @
f4a24fcb
...
...
@@ -22,7 +22,7 @@
#include
<vector>
#include
"graph_state.hh"
#include
"
../support/
graph_state.hh"
namespace
graph_tool
{
...
...
src/graph/inference/blockmodel/graph_blockmodel_emat.hh
0 → 100644
View file @
f4a24fcb
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2017 Tiago de Paula Peixoto <tiago@skewed.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_BLOCKMODEL_EMAT_HH
#define GRAPH_BLOCKMODEL_EMAT_HH
#include
<boost/multi_array.hpp>
#include
"hash_map_wrap.hh"
namespace
graph_tool
{
// this structure speeds up the access to the edges between given blocks, by
// using a simple adjacency matrix
template
<
class
BGraph
>
class
EMat
{
public:
template
<
class
RNG
>
EMat
(
BGraph
&
bg
,
RNG
&
)
{
sync
(
bg
);
}
void
sync
(
BGraph
&
bg
)
{
size_t
B
=
num_vertices
(
bg
);
_mat
.
resize
(
boost
::
extents
[
B
][
B
]);
std
::
fill
(
_mat
.
data
(),
_mat
.
data
()
+
_mat
.
num_elements
(),
_null_edge
);
for
(
auto
e
:
edges_range
(
bg
))
{
assert
(
get_me
(
source
(
e
,
bg
),
target
(
e
,
bg
))
==
_null_edge
);
_mat
[
source
(
e
,
bg
)][
target
(
e
,
bg
)]
=
e
;
if
(
!
is_directed
::
apply
<
BGraph
>::
type
::
value
)
_mat
[
target
(
e
,
bg
)][
source
(
e
,
bg
)]
=
e
;
}
}
typedef
typename
graph_traits
<
BGraph
>::
vertex_descriptor
vertex_t
;
typedef
typename
graph_traits
<
BGraph
>::
edge_descriptor
edge_t
;
const
auto
&
get_me
(
vertex_t
r
,
vertex_t
s
)
const
{
return
_mat
[
r
][
s
];
}
void
put_me
(
vertex_t
r
,
vertex_t
s
,
const
edge_t
&
e
)
{
_mat
[
r
][
s
]
=
e
;
if
(
!
is_directed
::
apply
<
BGraph
>::
type
::
value
&&
r
!=
s
)
_mat
[
s
][
r
]
=
e
;
}
void
remove_me
(
const
edge_t
&
me
,
BGraph
&
bg
)
{
auto
r
=
source
(
me
,
bg
);
auto
s
=
target
(
me
,
bg
);
_mat
[
r
][
s
]
=
_null_edge
;
if
(
!
is_directed
::
apply
<
BGraph
>::
type
::
value
)
_mat
[
s
][
r
]
=
_null_edge
;
remove_edge
(
me
,
bg
);
}
const
auto
&
get_null_edge
()
const
{
return
_null_edge
;
}
private:
multi_array
<
edge_t
,
2
>
_mat
;
static
const
edge_t
_null_edge
;
};
template
<
class
BGraph
>
const
typename
EMat
<
BGraph
>::
edge_t
EMat
<
BGraph
>::
_null_edge
;
template
<
class
Key
>
class
perfect_hash_t
{
public: