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
78d42c38
Commit
78d42c38
authored
Jul 22, 2013
by
Tiago Peixoto
Browse files
Faster Graph copying if filter state is identical
parent
27d059c2
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/graph/graph_copy.cc
View file @
78d42c38
...
...
@@ -79,8 +79,169 @@ void copy_property(const Descriptor& src_d, const Descriptor& tgt_d,
throw
ValueException
(
"Cannot find property map type."
);
}
template
<
class
GraphSrc
,
class
GraphTgt
,
class
IndexMap
,
class
SrcIndexMap
,
class
TgtIndexMap
>
struct
copy_vertex_property_dispatch
{
copy_vertex_property_dispatch
(
const
GraphSrc
&
src
,
const
GraphTgt
&
tgt
,
boost
::
any
&
prop_src
,
boost
::
any
&
prop_tgt
,
IndexMap
&
index_map
,
SrcIndexMap
&
src_vertex_index
,
TgtIndexMap
&
tgt_vertex_index
,
bool
&
found
)
:
src
(
src
),
tgt
(
tgt
),
prop_src
(
prop_src
),
prop_tgt
(
prop_tgt
),
index_map
(
index_map
),
src_vertex_index
(
src_vertex_index
),
tgt_vertex_index
(
tgt_vertex_index
),
found
(
found
)
{}
const
GraphSrc
&
src
;
const
GraphTgt
&
tgt
;
boost
::
any
&
prop_src
;
boost
::
any
&
prop_tgt
;
IndexMap
&
index_map
;
SrcIndexMap
&
src_vertex_index
;
TgtIndexMap
&
tgt_vertex_index
;
bool
&
found
;
template
<
class
PropertyMap
>
void
operator
()(
PropertyMap
)
const
{
PropertyMap
*
psrc
=
any_cast
<
PropertyMap
>
(
&
prop_src
);
if
(
psrc
==
NULL
)
return
;
if
(
prop_tgt
.
empty
())
prop_tgt
=
PropertyMap
(
tgt_vertex_index
);
PropertyMap
*
ptgt
=
any_cast
<
PropertyMap
>
(
&
prop_tgt
);
if
(
ptgt
==
NULL
)
return
;
found
=
true
;
typename
PropertyMap
::
unchecked_t
p_src
=
psrc
->
get_unchecked
(
num_vertices
(
src
));
typename
PropertyMap
::
unchecked_t
p_tgt
=
ptgt
->
get_unchecked
(
num_vertices
(
tgt
));
int
i
,
N
=
num_vertices
(
src
);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
for
(
i
=
0
;
i
<
N
;
++
i
)
{
typename
graph_traits
<
GraphSrc
>::
vertex_descriptor
v
=
vertex
(
i
,
src
);
if
(
v
==
graph_traits
<
GraphSrc
>::
null_vertex
())
continue
;
typename
graph_traits
<
GraphTgt
>::
vertex_descriptor
new_v
=
vertex
(
index_map
[
i
],
tgt
);
p_tgt
[
new_v
]
=
p_src
[
v
];
}
}
};
template
<
class
PropertyMaps
,
class
GraphSrc
,
class
GraphTgt
,
class
IndexMap
,
class
SrcIndexMap
,
class
TgtIndexMap
>
void
copy_vertex_property
(
boost
::
any
&
prop_src
,
boost
::
any
&
prop_tgt
,
const
GraphSrc
&
src
,
const
GraphTgt
&
tgt
,
IndexMap
&
index_map
,
SrcIndexMap
&
src_vertex_index
,
TgtIndexMap
&
tgt_vertex_index
)
{
bool
found
=
false
;
mpl
::
for_each
<
PropertyMaps
>
(
copy_vertex_property_dispatch
<
GraphSrc
,
GraphTgt
,
IndexMap
,
SrcIndexMap
,
TgtIndexMap
>
(
src
,
tgt
,
prop_src
,
prop_tgt
,
index_map
,
src_vertex_index
,
tgt_vertex_index
,
found
));
if
(
!
found
)
throw
ValueException
(
"Cannot find property map type."
);
}
template
<
class
GraphSrc
,
class
GraphTgt
,
class
IndexMap
,
class
SrcIndexMap
>
struct
copy_edge_property_dispatch
{
copy_edge_property_dispatch
(
const
GraphSrc
&
src
,
const
GraphTgt
&
tgt
,
boost
::
any
&
prop_src
,
boost
::
any
&
prop_tgt
,
IndexMap
&
index_map
,
SrcIndexMap
&
src_edge_index
,
size_t
max_src_edge_index
,
bool
&
found
)
:
src
(
src
),
tgt
(
tgt
),
prop_src
(
prop_src
),
prop_tgt
(
prop_tgt
),
index_map
(
index_map
),
src_edge_index
(
src_edge_index
),
max_src_edge_index
(
max_src_edge_index
),
found
(
found
)
{}
const
GraphSrc
&
src
;
const
GraphTgt
&
tgt
;
boost
::
any
&
prop_src
;
boost
::
any
&
prop_tgt
;
IndexMap
&
index_map
;
SrcIndexMap
&
src_edge_index
;
size_t
max_src_edge_index
;
bool
&
found
;
template
<
class
PropertyMap
>
void
operator
()(
PropertyMap
)
const
{
PropertyMap
*
psrc
=
any_cast
<
PropertyMap
>
(
&
prop_src
);
if
(
psrc
==
NULL
)
return
;
if
(
prop_tgt
.
empty
())
prop_tgt
=
PropertyMap
(
get
(
edge_index_t
(),
tgt
));
PropertyMap
*
ptgt
=
any_cast
<
PropertyMap
>
(
&
prop_tgt
);
if
(
ptgt
==
NULL
)
return
;
found
=
true
;
typename
PropertyMap
::
unchecked_t
p_src
=
psrc
->
get_unchecked
(
max_src_edge_index
+
1
);
typename
PropertyMap
::
unchecked_t
p_tgt
=
ptgt
->
get_unchecked
(
num_edges
(
tgt
));
int
i
,
N
=
num_vertices
(
src
);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
for
(
i
=
0
;
i
<
N
;
++
i
)
{
typename
graph_traits
<
GraphSrc
>::
vertex_descriptor
v
=
vertex
(
i
,
src
);
if
(
v
==
graph_traits
<
GraphSrc
>::
null_vertex
())
continue
;
typename
graph_traits
<
GraphSrc
>::
out_edge_iterator
e
,
e_end
;
for
(
tie
(
e
,
e_end
)
=
out_edges
(
v
,
src
);
e
!=
e_end
;
++
e
)
{
typename
graph_traits
<
GraphSrc
>::
vertex_descriptor
s
=
source
(
*
e
,
src
);
typename
graph_traits
<
GraphSrc
>::
vertex_descriptor
t
=
target
(
*
e
,
src
);
if
(
!
is_directed
::
apply
<
GraphSrc
>::
type
::
value
&&
s
>
t
)
continue
;
size_t
ei
=
src_edge_index
[
*
e
];
typename
graph_traits
<
GraphTgt
>::
edge_descriptor
new_e
=
index_map
[
ei
];
p_tgt
[
new_e
]
=
p_src
[
*
e
];
}
}
}
};
template
<
class
PropertyMaps
,
class
GraphSrc
,
class
GraphTgt
,
class
IndexMap
,
class
SrcIndexMap
>
void
copy_edge_property
(
boost
::
any
&
prop_src
,
boost
::
any
&
prop_tgt
,
const
GraphSrc
&
src
,
const
GraphTgt
&
tgt
,
IndexMap
&
index_map
,
SrcIndexMap
&
src_vertex_index
,
size_t
max_src_edge_index
)
{
bool
found
=
false
;
mpl
::
for_each
<
PropertyMaps
>
(
copy_edge_property_dispatch
<
GraphSrc
,
GraphTgt
,
IndexMap
,
SrcIndexMap
>
(
src
,
tgt
,
prop_src
,
prop_tgt
,
index_map
,
src_vertex_index
,
max_src_edge_index
,
found
));
if
(
!
found
)
throw
ValueException
(
"Cannot find property map type."
);
}
struct
do_graph_copy
{
do_graph_copy
(
size_t
max_src_edge_index
)
:
max_src_edge_index
(
max_src_edge_index
)
{}
size_t
max_src_edge_index
;
template
<
class
GraphTgt
,
class
GraphSrc
,
class
TgtVertexIndexMap
,
class
SrcVertexIndexMap
,
class
TgtEdgeIndexMap
,
class
SrcEdgeIndexMap
,
class
OrderMap
>
...
...
@@ -88,7 +249,7 @@ struct do_graph_copy
TgtVertexIndexMap
src_vertex_index
,
SrcVertexIndexMap
tgt_vertex_index
,
TgtEdgeIndexMap
,
SrcEdgeIndexMap
tgt
_edge_index
,
SrcEdgeIndexMap
src
_edge_index
,
OrderMap
vertex_order
,
vector
<
pair
<
reference_wrapper
<
boost
::
any
>
,
reference_wrapper
<
boost
::
any
>
>
>&
vprops
,
vector
<
pair
<
reference_wrapper
<
boost
::
any
>
,
reference_wrapper
<
boost
::
any
>
>
>&
eprops
)
const
...
...
@@ -99,17 +260,20 @@ struct do_graph_copy
{
if
(
src_vertex_index
[
*
v
]
>=
index_map
.
size
())
index_map
.
resize
(
src_vertex_index
[
*
v
]
+
1
);
typename
graph_traits
<
GraphTgt
>::
vertex_descriptor
new_v
=
get
(
vertex_order
,
*
v
);
typename
graph_traits
<
GraphTgt
>::
vertex_descriptor
new_v
=
get
(
vertex_order
,
*
v
);
while
(
new_v
>=
num_vertices
(
tgt
))
add_vertex
(
tgt
);
index_map
[
src_vertex_index
[
*
v
]]
=
tgt_vertex_index
[
new_v
];
for
(
size_t
i
=
0
;
i
<
vprops
.
size
();
++
i
)
copy_property
<
writable_vertex_properties
>
(
*
v
,
new_v
,
vprops
[
i
].
first
.
get
(),
vprops
[
i
].
second
.
get
(),
src
,
tgt
,
tgt_vertex_index
);
}
for
(
size_t
i
=
0
;
i
<
vprops
.
size
();
++
i
)
copy_vertex_property
<
writable_vertex_properties
>
(
vprops
[
i
].
first
.
get
(),
vprops
[
i
].
second
.
get
(),
src
,
tgt
,
index_map
,
src_vertex_index
,
tgt_vertex_index
);
vector
<
typename
graph_traits
<
GraphTgt
>::
edge_descriptor
>
edge_map
(
num_edges
(
src
));
typename
graph_traits
<
GraphSrc
>::
edge_iterator
e
,
e_end
;
for
(
tie
(
e
,
e_end
)
=
edges
(
src
);
e
!=
e_end
;
++
e
)
{
...
...
@@ -118,11 +282,18 @@ struct do_graph_copy
typedef
typename
graph_traits
<
GraphTgt
>::
edge_descriptor
edge_t
;
edge_t
new_e
=
add_edge
(
vertex
(
s
,
tgt
),
vertex
(
t
,
tgt
),
tgt
).
first
;
for
(
size_t
i
=
0
;
i
<
eprops
.
size
();
++
i
)
copy_property
<
writable_edge_properties
>
(
edge_t
(
*
e
),
new_e
,
eprops
[
i
].
first
.
get
(),
eprops
[
i
].
second
.
get
(),
src
,
tgt
,
tgt_edge_index
);
size_t
ei
=
src_edge_index
[
*
e
];
if
(
ei
>=
edge_map
.
size
())
edge_map
.
resize
(
ei
+
1
);
edge_map
[
ei
]
=
new_e
;
}
for
(
size_t
i
=
0
;
i
<
eprops
.
size
();
++
i
)
copy_edge_property
<
writable_edge_properties
>
(
eprops
[
i
].
first
.
get
(),
eprops
[
i
].
second
.
get
(),
src
,
tgt
,
edge_map
,
src_edge_index
,
max_src_edge_index
);
}
};
...
...
@@ -145,6 +316,13 @@ GraphInterface::GraphInterface(const GraphInterface& gi, bool keep_ref,
if
(
keep_ref
)
return
;
if
(
vorder
==
python
::
object
())
{
// simple copying
*
_mg
=
*
gi
.
_mg
;
return
;
}
vector
<
pair
<
reference_wrapper
<
boost
::
any
>
,
reference_wrapper
<
boost
::
any
>
>
>
vprops
;
for
(
int
i
=
0
;
i
<
python
::
len
(
ovprops
);
++
i
)
{
...
...
@@ -161,9 +339,9 @@ GraphInterface::GraphInterface(const GraphInterface& gi, bool keep_ref,
boost
::
any
avorder
=
python
::
extract
<
boost
::
any
>
(
vorder
);
run_action
<>
()
(
const_cast
<
GraphInterface
&>
(
gi
),
bind
<
void
>
(
do_graph_copy
(),
_1
,
ref
(
*
_mg
),
gi
.
_vertex_index
,
_vertex_index
,
gi
.
_edge_index
,
_edge_index
,
_2
,
ref
(
vprops
),
ref
(
eprops
)),
vertex_scalar_properties
())(
avorder
);
bind
<
void
>
(
do_graph_copy
(
gi
.
_mg
->
get_last_index
()
),
_1
,
ref
(
*
_mg
),
gi
.
_vertex_index
,
_vertex_index
,
gi
.
_edge_index
,
_edge_index
,
_2
,
ref
(
vprops
),
ref
(
eprops
)),
vertex_scalar_properties
())(
avorder
);
// filters will be copied in python
}
src/graph_tool/__init__.py
View file @
78d42c38
...
...
@@ -1060,66 +1060,90 @@ class Graph(object):
vfilt
=
g
.
get_vertex_filter
()[
0
]
efilt
=
g
.
get_edge_filter
()[
0
]
# Copy all internal properties from original graph.
vprops
=
[]
eprops
=
[]
ef_pos
=
vf_pos
=
None
for
k
,
m
in
gv
.
vertex_properties
.
items
():
if
not
vprune
and
m
is
vfilt
:
if
(
vorder
is
None
and
((
g
.
get_vertex_filter
()[
0
]
is
None
and
g
.
get_edge_filter
()[
0
]
is
None
)
or
(
not
vprune
and
not
eprune
))):
# Do a simpler, faster copy.
self
.
__graph
=
libcore
.
GraphInterface
(
gv
.
__graph
,
False
,
[],
[],
None
)
nvfilt
=
nefilt
=
None
for
k
,
m
in
g
.
properties
.
items
():
nmap
=
self
.
copy_property
(
m
,
g
=
gv
)
self
.
properties
[
k
]
=
nmap
if
m
is
vfilt
:
nvfilt
=
nmap
if
m
is
efilt
:
nefilt
=
nmap
if
vfilt
is
not
None
:
if
nvfilt
is
None
:
nvfilt
=
self
.
copy_property
(
vfilt
,
g
=
gv
)
self
.
set_vertex_filter
(
nvfilt
,
g
.
get_vertex_filter
()[
1
])
if
efilt
is
not
None
:
if
nefilt
is
None
:
nefilt
=
self
.
copy_property
(
efilt
,
g
=
gv
)
self
.
set_edge_filter
(
nefilt
,
g
.
get_edge_filter
()[
1
])
else
:
# Copy all internal properties from original graph.
vprops
=
[]
eprops
=
[]
ef_pos
=
vf_pos
=
None
for
k
,
m
in
gv
.
vertex_properties
.
items
():
if
not
vprune
and
m
is
vfilt
:
vf_pos
=
len
(
vprops
)
vprops
.
append
([
_prop
(
"v"
,
gv
,
m
),
libcore
.
any
()])
for
k
,
m
in
gv
.
edge_properties
.
items
():
if
not
eprune
and
m
is
efilt
:
ef_pos
=
len
(
eprops
)
eprops
.
append
([
_prop
(
"e"
,
gv
,
m
),
libcore
.
any
()])
if
not
vprune
and
vf_pos
is
None
and
vfilt
is
not
None
:
vf_pos
=
len
(
vprops
)
vprops
.
append
([
_prop
(
"v"
,
gv
,
m
),
libcore
.
any
()])
for
k
,
m
in
gv
.
edge_properties
.
items
():
if
not
eprune
and
m
is
efilt
:
vprops
.
append
([
_prop
(
"v"
,
gv
,
vfilt
),
libcore
.
any
()])
if
not
eprune
and
ef_pos
is
None
and
efilt
is
not
None
:
ef_pos
=
len
(
eprops
)
eprops
.
append
([
_prop
(
"e"
,
gv
,
m
),
libcore
.
any
()])
if
not
vprune
and
vf_pos
is
None
and
vfilt
is
not
None
:
vf_pos
=
len
(
vprops
)
vprops
.
append
([
_prop
(
"v"
,
gv
,
vfilt
),
libcore
.
any
()])
if
not
eprune
and
ef_pos
is
None
and
efilt
is
not
None
:
ef_pos
=
len
(
eprops
)
eprops
.
append
([
_prop
(
"e"
,
gv
,
efilt
),
libcore
.
any
()])
# The vertex ordering
if
vorder
is
None
:
vorder
=
gv
.
new_vertex_property
(
"int"
)
vorder
.
fa
=
numpy
.
arange
(
gv
.
num_vertices
())
# The actual copying of the graph and property maps
self
.
__graph
=
libcore
.
GraphInterface
(
gv
.
__graph
,
False
,
vprops
,
eprops
,
_prop
(
"v"
,
gv
,
vorder
))
# Put the copied properties in the internal dictionary
for
i
,
(
k
,
m
)
in
enumerate
(
g
.
vertex_properties
.
items
()):
pmap
=
new_vertex_property
(
m
.
value_type
(),
self
.
__graph
.
GetVertexIndex
(),
vprops
[
i
][
1
])
self
.
vertex_properties
[
k
]
=
PropertyMap
(
pmap
,
self
,
"v"
)
for
i
,
(
k
,
m
)
in
enumerate
(
g
.
edge_properties
.
items
()):
pmap
=
new_edge_property
(
m
.
value_type
(),
self
.
__graph
.
GetEdgeIndex
(),
eprops
[
i
][
1
])
self
.
edge_properties
[
k
]
=
PropertyMap
(
pmap
,
self
,
"e"
)
for
k
,
v
in
g
.
graph_properties
.
items
():
new_p
=
self
.
new_graph_property
(
v
.
value_type
())
new_p
[
self
]
=
v
[
g
]
self
.
graph_properties
[
k
]
=
new_p
if
vf_pos
is
not
None
:
pmap
=
new_vertex_property
(
"bool"
,
self
.
__graph
.
GetVertexIndex
(),
vprops
[
vf_pos
][
1
])
pmap
=
PropertyMap
(
pmap
,
self
,
"v"
)
self
.
set_vertex_filter
(
pmap
,
g
.
get_vertex_filter
()[
1
])
if
ef_pos
is
not
None
:
pmap
=
new_edge_property
(
"bool"
,
self
.
__graph
.
GetEdgeIndex
(),
eprops
[
ef_pos
][
1
])
pmap
=
PropertyMap
(
pmap
,
self
,
"e"
)
self
.
set_edge_filter
(
pmap
,
g
.
get_edge_filter
()[
1
])
eprops
.
append
([
_prop
(
"e"
,
gv
,
efilt
),
libcore
.
any
()])
# The vertex ordering
if
vorder
is
None
:
vorder
=
gv
.
new_vertex_property
(
"int"
)
vorder
.
fa
=
numpy
.
arange
(
gv
.
num_vertices
())
# The actual copying of the graph and property maps
self
.
__graph
=
libcore
.
GraphInterface
(
gv
.
__graph
,
False
,
vprops
,
eprops
,
_prop
(
"v"
,
gv
,
vorder
))
# Put the copied properties in the internal dictionary
for
i
,
(
k
,
m
)
in
enumerate
(
g
.
vertex_properties
.
items
()):
pmap
=
new_vertex_property
(
m
.
value_type
(),
self
.
__graph
.
GetVertexIndex
(),
vprops
[
i
][
1
])
self
.
vertex_properties
[
k
]
=
PropertyMap
(
pmap
,
self
,
"v"
)
for
i
,
(
k
,
m
)
in
enumerate
(
g
.
edge_properties
.
items
()):
pmap
=
new_edge_property
(
m
.
value_type
(),
self
.
__graph
.
GetEdgeIndex
(),
eprops
[
i
][
1
])
self
.
edge_properties
[
k
]
=
PropertyMap
(
pmap
,
self
,
"e"
)
for
k
,
v
in
g
.
graph_properties
.
items
():
new_p
=
self
.
new_graph_property
(
v
.
value_type
())
new_p
[
self
]
=
v
[
g
]
self
.
graph_properties
[
k
]
=
new_p
if
vf_pos
is
not
None
:
pmap
=
new_vertex_property
(
"bool"
,
self
.
__graph
.
GetVertexIndex
(),
vprops
[
vf_pos
][
1
])
pmap
=
PropertyMap
(
pmap
,
self
,
"v"
)
self
.
set_vertex_filter
(
pmap
,
g
.
get_vertex_filter
()[
1
])
if
ef_pos
is
not
None
:
pmap
=
new_edge_property
(
"bool"
,
self
.
__graph
.
GetEdgeIndex
(),
eprops
[
ef_pos
][
1
])
pmap
=
PropertyMap
(
pmap
,
self
,
"e"
)
self
.
set_edge_filter
(
pmap
,
g
.
get_edge_filter
()[
1
])
if
not
rprune
:
self
.
set_reversed
(
g
.
is_reversed
())
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment