Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Tiago Peixoto
graph-tool
Commits
477df9b8
Commit
477df9b8
authored
Feb 17, 2017
by
Tiago Peixoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add "array" parameter to {dfs,bfs,dijkstra,astar}_iterator()
parent
f327fcb4
Pipeline
#264
passed with stage
in 364 minutes and 54 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
340 additions
and
95 deletions
+340
-95
src/graph/numpy_bind.hh
src/graph/numpy_bind.hh
+53
-10
src/graph/search/graph_astar.cc
src/graph/search/graph_astar.cc
+57
-0
src/graph/search/graph_bfs.cc
src/graph/search/graph_bfs.cc
+50
-40
src/graph/search/graph_dfs.cc
src/graph/search/graph_dfs.cc
+40
-25
src/graph/search/graph_dijkstra.cc
src/graph/search/graph_dijkstra.cc
+57
-0
src/graph_tool/search/__init__.py
src/graph_tool/search/__init__.py
+83
-20
No files found.
src/graph/numpy_bind.hh
View file @
477df9b8
...
@@ -65,7 +65,7 @@ typedef boost::mpl::map<
...
@@ -65,7 +65,7 @@ typedef boost::mpl::map<
template
<
class
ValueType
>
template
<
class
ValueType
>
boost
::
python
::
object
wrap_vector_owned
(
const
std
::
vector
<
ValueType
>&
vec
)
boost
::
python
::
object
wrap_vector_owned
(
const
std
::
vector
<
ValueType
>&
vec
)
{
{
in
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
size_
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
npy_intp
size
[
1
];
npy_intp
size
[
1
];
size
[
0
]
=
vec
.
size
();
size
[
0
]
=
vec
.
size
();
PyArrayObject
*
ndarray
;
PyArrayObject
*
ndarray
;
...
@@ -91,13 +91,12 @@ template <class ValueType>
...
@@ -91,13 +91,12 @@ template <class ValueType>
boost
::
python
::
object
wrap_vector_not_owned
(
std
::
vector
<
ValueType
>&
vec
)
boost
::
python
::
object
wrap_vector_not_owned
(
std
::
vector
<
ValueType
>&
vec
)
{
{
PyArrayObject
*
ndarray
;
PyArrayObject
*
ndarray
;
in
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
size_
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
npy_intp
size
=
vec
.
size
();
npy_intp
size
=
vec
.
size
();
if
(
vec
.
empty
())
if
(
vec
.
empty
())
return
wrap_vector_owned
(
vec
);
// return an _owned_ array of size one.
return
wrap_vector_owned
(
vec
);
// return an _owned_ array of size one.
else
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
1
,
&
size
,
val_type
,
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
1
,
&
size
,
val_type
,
vec
.
data
());
vec
.
data
());
PyArray_ENABLEFLAGS
(
ndarray
,
NPY_ARRAY_ALIGNED
|
NPY_ARRAY_C_CONTIGUOUS
|
PyArray_ENABLEFLAGS
(
ndarray
,
NPY_ARRAY_ALIGNED
|
NPY_ARRAY_C_CONTIGUOUS
|
NPY_ARRAY_WRITEABLE
);
NPY_ARRAY_WRITEABLE
);
boost
::
python
::
handle
<>
x
((
PyObject
*
)
ndarray
);
boost
::
python
::
handle
<>
x
((
PyObject
*
)
ndarray
);
...
@@ -105,16 +104,60 @@ boost::python::object wrap_vector_not_owned(std::vector<ValueType>& vec)
...
@@ -105,16 +104,60 @@ boost::python::object wrap_vector_not_owned(std::vector<ValueType>& vec)
return
o
;
return
o
;
}
}
template
<
class
ValueType
,
size_t
Dim
>
boost
::
python
::
object
wrap_vector_owned
(
const
std
::
vector
<
std
::
array
<
ValueType
,
Dim
>>&
vec
)
{
size_t
n
=
vec
.
size
()
*
Dim
;
size_t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
PyArrayObject
*
ndarray
;
if
(
n
==
0
)
{
npy_intp
size
[
1
];
size
[
0
]
=
vec
.
size
();
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNew
(
1
,
size
,
val_type
);
}
else
{
ValueType
*
new_data
=
new
ValueType
[
n
];
memcpy
(
new_data
,
vec
.
data
(),
n
*
sizeof
(
ValueType
));
npy_intp
shape
[
2
]
=
{
int
(
vec
.
size
()),
int
(
Dim
)};
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
shape
,
val_type
,
new_data
);
}
PyArray_ENABLEFLAGS
(
ndarray
,
NPY_ARRAY_ALIGNED
|
NPY_ARRAY_F_CONTIGUOUS
|
NPY_ARRAY_OWNDATA
|
NPY_ARRAY_WRITEABLE
);
boost
::
python
::
handle
<>
x
((
PyObject
*
)
ndarray
);
boost
::
python
::
object
o
(
x
);
return
o
;
}
template
<
class
ValueType
,
size_t
Dim
>
boost
::
python
::
object
wrap_vector_not_owned
(
const
std
::
vector
<
std
::
array
<
ValueType
,
Dim
>>&
vec
)
{
size_t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
if
(
vec
.
empty
())
return
wrap_vector_owned
(
vec
);
// return an _owned_ array of size one.
npy_intp
shape
[
2
]
=
{
int
(
vec
.
size
()),
int
(
Dim
)};
PyArrayObject
*
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
shape
,
val_type
,
vec
.
data
());
PyArray_ENABLEFLAGS
(
ndarray
,
NPY_ARRAY_ALIGNED
|
NPY_ARRAY_F_CONTIGUOUS
|
NPY_ARRAY_WRITEABLE
);
boost
::
python
::
handle
<>
x
((
PyObject
*
)
ndarray
);
boost
::
python
::
object
o
(
x
);
return
o
;
}
template
<
class
ValueType
,
in
t
Dim
>
template
<
class
ValueType
,
size_
t
Dim
>
boost
::
python
::
object
boost
::
python
::
object
wrap_multi_array_owned
(
const
boost
::
multi_array
<
ValueType
,
Dim
>&
array
)
wrap_multi_array_owned
(
const
boost
::
multi_array
<
ValueType
,
Dim
>&
array
)
{
{
ValueType
*
new_data
=
new
ValueType
[
array
.
num_elements
()];
ValueType
*
new_data
=
new
ValueType
[
array
.
num_elements
()];
memcpy
(
new_data
,
array
.
data
(),
array
.
num_elements
()
*
sizeof
(
ValueType
));
memcpy
(
new_data
,
array
.
data
(),
array
.
num_elements
()
*
sizeof
(
ValueType
));
in
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
size_
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
npy_intp
shape
[
Dim
];
npy_intp
shape
[
Dim
];
for
(
in
t
i
=
0
;
i
<
Dim
;
++
i
)
for
(
size_
t
i
=
0
;
i
<
Dim
;
++
i
)
shape
[
i
]
=
array
.
shape
()[
i
];
shape
[
i
]
=
array
.
shape
()[
i
];
PyArrayObject
*
ndarray
=
PyArrayObject
*
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
shape
,
val_type
,
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
shape
,
val_type
,
...
@@ -126,11 +169,11 @@ wrap_multi_array_owned(const boost::multi_array<ValueType,Dim>& array)
...
@@ -126,11 +169,11 @@ wrap_multi_array_owned(const boost::multi_array<ValueType,Dim>& array)
return
o
;
return
o
;
}
}
template
<
class
ValueType
,
in
t
Dim
>
template
<
class
ValueType
,
size_
t
Dim
>
boost
::
python
::
object
boost
::
python
::
object
wrap_multi_array_not_owned
(
boost
::
multi_array
<
ValueType
,
Dim
>&
array
)
wrap_multi_array_not_owned
(
boost
::
multi_array
<
ValueType
,
Dim
>&
array
)
{
{
in
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
size_
t
val_type
=
boost
::
mpl
::
at
<
numpy_types
,
ValueType
>::
type
::
value
;
PyArrayObject
*
ndarray
=
PyArrayObject
*
ndarray
=
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
array
.
shape
(),
val_type
,
(
PyArrayObject
*
)
PyArray_SimpleNewFromData
(
Dim
,
array
.
shape
(),
val_type
,
array
.
origin
());
array
.
origin
());
...
...
src/graph/search/graph_astar.cc
View file @
477df9b8
...
@@ -177,6 +177,61 @@ boost::python::object astar_search_generator_fast(GraphInterface& g,
...
@@ -177,6 +177,61 @@ boost::python::object astar_search_generator_fast(GraphInterface& g,
#endif
#endif
}
}
class
AStarArrayVisitor
:
public
astar_visitor
<>
{
public:
AStarArrayVisitor
(
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
edges
)
:
_edges
(
edges
)
{}
template
<
class
Edge
,
class
Graph
>
void
edge_relaxed
(
const
Edge
&
e
,
Graph
&
g
)
{
_edges
.
push_back
({
source
(
e
,
g
),
target
(
e
,
g
)});
}
private:
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
_edges
;
};
boost
::
python
::
object
astar_search_array
(
GraphInterface
&
g
,
size_t
source
,
boost
::
any
dist_map
,
boost
::
any
weight
,
python
::
object
cmp
,
python
::
object
cmb
,
python
::
object
zero
,
python
::
object
inf
,
python
::
object
h
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
AStarArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
std
::
bind
(
do_astar_search
(),
std
::
placeholders
::
_1
,
source
,
std
::
placeholders
::
_2
,
dummy_property_map
(),
weight
,
vis
,
make_pair
(
AStarCmp
(
cmp
),
AStarCmb
(
cmb
)),
make_pair
(
zero
,
inf
),
h
,
std
::
ref
(
g
)),
writable_vertex_properties
())(
dist_map
);
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
boost
::
python
::
object
astar_search_array_fast
(
GraphInterface
&
g
,
size_t
source
,
boost
::
any
dist_map
,
boost
::
any
weight
,
python
::
object
zero
,
python
::
object
inf
,
python
::
object
h
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
AStarArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
std
::
bind
(
do_astar_search_fast
(),
std
::
placeholders
::
_1
,
source
,
std
::
placeholders
::
_2
,
std
::
placeholders
::
_3
,
vis
,
make_pair
(
zero
,
inf
),
h
,
std
::
ref
(
g
)),
writable_vertex_scalar_properties
(),
edge_scalar_properties
())(
dist_map
,
weight
);
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
void
export_astar
()
void
export_astar
()
{
{
...
@@ -184,4 +239,6 @@ void export_astar()
...
@@ -184,4 +239,6 @@ void export_astar()
def
(
"astar_search"
,
&
a_star_search
);
def
(
"astar_search"
,
&
a_star_search
);
def
(
"astar_generator"
,
&
astar_search_generator
);
def
(
"astar_generator"
,
&
astar_search_generator
);
def
(
"astar_generator_fast"
,
&
astar_search_generator_fast
);
def
(
"astar_generator_fast"
,
&
astar_search_generator_fast
);
def
(
"astar_array"
,
&
astar_search_array
);
def
(
"astar_array_fast"
,
&
astar_search_array_fast
);
}
}
src/graph/search/graph_bfs.cc
View file @
477df9b8
...
@@ -106,28 +106,32 @@ private:
...
@@ -106,28 +106,32 @@ private:
boost
::
python
::
object
_vis
;
boost
::
python
::
object
_vis
;
};
};
template
<
class
Graph
,
class
Visitor
>
void
do_bfs
(
Graph
&
g
,
size_t
s
,
Visitor
&&
vis
)
{
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
Graph
>::
null_vertex
())
{
for
(
auto
u
:
vertices_range
(
g
))
{
if
(
color
[
u
]
==
color_traits
<
default_color_type
>::
black
())
continue
;
breadth_first_visit
(
g
,
u
,
visitor
(
vis
).
color_map
(
color
));
}
}
else
{
breadth_first_visit
(
g
,
v
,
visitor
(
vis
).
color_map
(
color
));
}
}
void
bfs_search
(
GraphInterface
&
gi
,
size_t
s
,
python
::
object
vis
)
void
bfs_search
(
GraphInterface
&
gi
,
size_t
s
,
python
::
object
vis
)
{
{
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
gi
,
(
gi
,
[
&
](
auto
&
g
){
do_bfs
(
g
,
s
,
BFSVisitorWrapper
(
gi
,
vis
));
})();
[
&
](
auto
&
g
)
{
typedef
typename
std
::
remove_reference
<
decltype
(
g
)
>::
type
g_t
;
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
visw
=
BFSVisitorWrapper
(
gi
,
vis
);
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
g_t
>::
null_vertex
())
{
for
(
auto
u
:
vertices_range
(
g
))
breadth_first_search
(
g
,
u
,
visitor
(
visw
).
color_map
(
color
));
}
else
{
breadth_first_visit
(
g
,
v
,
visitor
(
visw
).
color_map
(
color
));
}
})();
}
}
#ifdef HAVE_BOOST_COROUTINE
#ifdef HAVE_BOOST_COROUTINE
...
@@ -160,28 +164,7 @@ boost::python::object bfs_search_generator(GraphInterface& g, size_t s)
...
@@ -160,28 +164,7 @@ boost::python::object bfs_search_generator(GraphInterface& g, size_t s)
{
{
BFSGeneratorVisitor
vis
(
g
,
yield
);
BFSGeneratorVisitor
vis
(
g
,
yield
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
(
g
,
[
&
](
auto
&
g
){
do_bfs
(
g
,
s
,
vis
);
})();
[
&
](
auto
&
g
)
{
typedef
typename
std
::
remove_reference
<
decltype
(
g
)
>::
type
g_t
;
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
g_t
>::
null_vertex
())
{
for
(
auto
u
:
vertices_range
(
g
))
{
if
(
color
[
u
]
==
color_traits
<
default_color_type
>::
black
())
continue
;
breadth_first_visit
(
g
,
u
,
visitor
(
vis
).
color_map
(
color
));
}
}
else
{
breadth_first_visit
(
g
,
v
,
visitor
(
vis
).
color_map
(
color
));
}
})();
};
};
return
boost
::
python
::
object
(
CoroGenerator
(
dispatch
));
return
boost
::
python
::
object
(
CoroGenerator
(
dispatch
));
#else
#else
...
@@ -189,9 +172,36 @@ boost::python::object bfs_search_generator(GraphInterface& g, size_t s)
...
@@ -189,9 +172,36 @@ boost::python::object bfs_search_generator(GraphInterface& g, size_t s)
#endif
#endif
}
}
class
BFSArrayVisitor
:
public
bfs_visitor
<>
{
public:
BFSArrayVisitor
(
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
edges
)
:
_edges
(
edges
)
{}
template
<
class
Edge
,
class
Graph
>
void
tree_edge
(
const
Edge
&
e
,
Graph
&
g
)
{
_edges
.
push_back
({
source
(
e
,
g
),
target
(
e
,
g
)});
}
private:
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
_edges
;
};
boost
::
python
::
object
bfs_search_array
(
GraphInterface
&
g
,
size_t
s
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
BFSArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
[
&
](
auto
&
g
){
do_bfs
(
g
,
s
,
vis
);
})();
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
void
export_bfs
()
void
export_bfs
()
{
{
using
namespace
boost
::
python
;
using
namespace
boost
::
python
;
def
(
"bfs_search"
,
&
bfs_search
);
def
(
"bfs_search"
,
&
bfs_search
);
def
(
"bfs_search_generator"
,
&
bfs_search_generator
);
def
(
"bfs_search_generator"
,
&
bfs_search_generator
);
def
(
"bfs_search_array"
,
&
bfs_search_array
);
}
}
src/graph/search/graph_dfs.cc
View file @
477df9b8
...
@@ -90,22 +90,22 @@ private:
...
@@ -90,22 +90,22 @@ private:
python
::
object
_vis
;
python
::
object
_vis
;
};
};
template
<
class
Graph
,
class
Visitor
>
void
do_dfs
(
Graph
&
g
,
size_t
s
,
Visitor
&&
vis
)
{
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
Graph
>::
null_vertex
())
depth_first_search
(
g
,
vis
,
color
);
else
depth_first_visit
(
g
,
v
,
vis
,
color
);
}
void
dfs_search
(
GraphInterface
&
gi
,
size_t
s
,
python
::
object
vis
)
void
dfs_search
(
GraphInterface
&
gi
,
size_t
s
,
python
::
object
vis
)
{
{
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
gi
,
(
gi
,
[
&
](
auto
&
g
)
{
do_dfs
(
g
,
s
,
DFSVisitorWrapper
(
gi
,
vis
));})();
[
&
](
auto
&
g
)
{
typedef
typename
std
::
remove_reference
<
decltype
(
g
)
>::
type
g_t
;
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
visw
=
DFSVisitorWrapper
(
gi
,
vis
);
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
g_t
>::
null_vertex
())
depth_first_search
(
g
,
visw
,
color
);
else
depth_first_visit
(
g
,
v
,
visw
,
color
);
})();
}
}
#ifdef HAVE_BOOST_COROUTINE
#ifdef HAVE_BOOST_COROUTINE
...
@@ -139,18 +139,7 @@ boost::python::object dfs_search_generator(GraphInterface& g, size_t s)
...
@@ -139,18 +139,7 @@ boost::python::object dfs_search_generator(GraphInterface& g, size_t s)
{
{
DFSGeneratorVisitor
vis
(
g
,
yield
);
DFSGeneratorVisitor
vis
(
g
,
yield
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
(
g
,
[
&
](
auto
&
g
)
{
do_dfs
(
g
,
s
,
vis
);})();
[
&
](
auto
&
g
)
{
typedef
typename
std
::
remove_reference
<
decltype
(
g
)
>::
type
g_t
;
typename
vprop_map_t
<
default_color_type
>::
type
color
(
get
(
vertex_index_t
(),
g
));
auto
v
=
vertex
(
s
,
g
);
if
(
v
==
graph_traits
<
g_t
>::
null_vertex
())
depth_first_search
(
g
,
vis
,
color
);
else
depth_first_visit
(
g
,
v
,
vis
,
color
);
})();
};
};
return
boost
::
python
::
object
(
CoroGenerator
(
dispatch
));
return
boost
::
python
::
object
(
CoroGenerator
(
dispatch
));
#else
#else
...
@@ -158,9 +147,35 @@ boost::python::object dfs_search_generator(GraphInterface& g, size_t s)
...
@@ -158,9 +147,35 @@ boost::python::object dfs_search_generator(GraphInterface& g, size_t s)
#endif
#endif
}
}
class
DFSArrayVisitor
:
public
dfs_visitor
<>
{
public:
DFSArrayVisitor
(
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
edges
)
:
_edges
(
edges
)
{}
template
<
class
Edge
,
class
Graph
>
void
tree_edge
(
const
Edge
&
e
,
Graph
&
g
)
{
_edges
.
push_back
({
source
(
e
,
g
),
target
(
e
,
g
)});
}
private:
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
_edges
;
};
boost
::
python
::
object
dfs_search_array
(
GraphInterface
&
g
,
size_t
s
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
DFSArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
[
&
](
auto
&
g
){
do_dfs
(
g
,
s
,
vis
);
})();
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
void
export_dfs
()
void
export_dfs
()
{
{
using
namespace
boost
::
python
;
using
namespace
boost
::
python
;
def
(
"dfs_search"
,
&
dfs_search
);
def
(
"dfs_search"
,
&
dfs_search
);
def
(
"dfs_search_generator"
,
&
dfs_search_generator
);
def
(
"dfs_search_generator"
,
&
dfs_search_generator
);
def
(
"dfs_search_array"
,
&
dfs_search_array
);
}
}
src/graph/search/graph_dijkstra.cc
View file @
477df9b8
...
@@ -297,10 +297,67 @@ boost::python::object dijkstra_search_generator_fast(GraphInterface& g,
...
@@ -297,10 +297,67 @@ boost::python::object dijkstra_search_generator_fast(GraphInterface& g,
#endif
#endif
}
}
class
DJKArrayVisitor
:
public
dijkstra_visitor
<>
{
public:
DJKArrayVisitor
(
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
edges
)
:
_edges
(
edges
)
{}
template
<
class
Edge
,
class
Graph
>
void
edge_relaxed
(
const
Edge
&
e
,
Graph
&
g
)
{
_edges
.
push_back
({
source
(
e
,
g
),
target
(
e
,
g
)});
}
private:
std
::
vector
<
std
::
array
<
size_t
,
2
>>&
_edges
;
};
boost
::
python
::
object
dijkstra_search_array
(
GraphInterface
&
g
,
size_t
source
,
boost
::
any
dist_map
,
boost
::
any
weight
,
python
::
object
cmp
,
python
::
object
cmb
,
python
::
object
zero
,
python
::
object
inf
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
DJKArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
std
::
bind
(
do_djk_search
(),
std
::
placeholders
::
_1
,
source
,
std
::
placeholders
::
_2
,
dummy_property_map
(),
weight
,
vis
,
DJKCmp
(
cmp
),
DJKCmb
(
cmb
),
make_pair
(
zero
,
inf
)),
writable_vertex_properties
())(
dist_map
);
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
boost
::
python
::
object
dijkstra_search_array_fast
(
GraphInterface
&
g
,
size_t
source
,
boost
::
any
dist_map
,
boost
::
any
weight
,
python
::
object
zero
,
python
::
object
inf
)
{
std
::
vector
<
std
::
array
<
size_t
,
2
>>
edges
;
DJKArrayVisitor
vis
(
edges
);
run_action
<
graph_tool
::
all_graph_views
,
mpl
::
true_
>
()
(
g
,
std
::
bind
(
do_djk_search_fast
(),
std
::
placeholders
::
_1
,
source
,
std
::
placeholders
::
_2
,
std
::
placeholders
::
_3
,
vis
,
make_pair
(
zero
,
inf
)),
writable_vertex_scalar_properties
(),
edge_scalar_properties
())(
dist_map
,
weight
);
return
wrap_vector_owned
<
size_t
,
2
>
(
edges
);
}
void
export_dijkstra
()
void
export_dijkstra
()
{
{
using
namespace
boost
::
python
;
using
namespace
boost
::
python
;
def
(
"dijkstra_search"
,
&
dijkstra_search
);
def
(
"dijkstra_search"
,
&
dijkstra_search
);
def
(
"dijkstra_generator"
,
&
dijkstra_search_generator
);
def
(
"dijkstra_generator"
,
&
dijkstra_search_generator
);
def
(
"dijkstra_generator_fast"
,
&
dijkstra_search_generator_fast
);
def
(
"dijkstra_generator_fast"
,
&
dijkstra_search_generator_fast
);
def
(
"dijkstra_array"
,
&
dijkstra_search_array
);
def
(
"dijkstra_array_fast"
,
&
dijkstra_search_array_fast
);
}
}
src/graph_tool/search/__init__.py
View file @
477df9b8
...
@@ -295,7 +295,7 @@ def bfs_search(g, source=None, visitor=BFSVisitor()):
...
@@ -295,7 +295,7 @@ def bfs_search(g, source=None, visitor=BFSVisitor()):
except
StopSearch
:
except
StopSearch
:
pass
pass
def
bfs_iterator
(
g
,
source
=
None
):
def
bfs_iterator
(
g
,
source
=
None
,
array
=
False
):
r
"""Return an iterator of the edges corresponding to a breath-first traversal of
r
"""Return an iterator of the edges corresponding to a breath-first traversal of
the graph.
the graph.
...
@@ -307,10 +307,16 @@ def bfs_iterator(g, source=None):
...
@@ -307,10 +307,16 @@ def bfs_iterator(g, source=None):
Source vertex. If unspecified, all vertices will be traversed, by
Source vertex. If unspecified, all vertices will be traversed, by
iterating over starting vertices according to their index in increasing
iterating over starting vertices according to their index in increasing
order.
order.
array : ``bool`` (optional, default: ``False``)
If ``True``, a :class:`numpy.ndarray` will the edge endpoints be
returned instead.
Returns
Returns
-------
-------
bfs_iterator : An iterator over the edges in breath-first order.
bfs_iterator : Iterator or :class:`numpy.ndarray`
An iterator over the edges in breath-first order. If ``array == True``,
this will be a :class:`numpy.ndarray` instead, of shape ``(E,2)``,
containing the edge endpoints.
See Also
See Also
--------
--------
...
@@ -348,12 +354,16 @@ def bfs_iterator(g, source=None):
...
@@ -348,12 +354,16 @@ def bfs_iterator(g, source=None):
Symposium on the Theory of Switching, 1959
Symposium on the Theory of Switching, 1959
.. [bfs-bgl] http://www.boost.org/doc/libs/release/libs/graph/doc/breadth_first_search.html
.. [bfs-bgl] http://www.boost.org/doc/libs/release/libs/graph/doc/breadth_first_search.html
.. [bfs-wikipedia] http://en.wikipedia.org/wiki/Breadth-first_search
.. [bfs-wikipedia] http://en.wikipedia.org/wiki/Breadth-first_search
"""
"""
if
source
is
None
:
if
source
is
None
:
source
=
_get_null_vertex
()
source
=
_get_null_vertex
()
else
:
else
:
source
=
int
(
source
)
source
=
int
(
source
)
return
libgraph_tool_search
.
bfs_search_generator
(
g
.
_Graph__graph
,
source
)
if
not
array
:
return
libgraph_tool_search
.
bfs_search_generator
(
g
.
_Graph__graph
,
source
)
else
:
return
libgraph_tool_search
.
bfs_search_array
(
g
.
_Graph__graph
,
source
)
class
DFSVisitor
(
object
):
class
DFSVisitor
(
object
):
...
@@ -589,7 +599,7 @@ def dfs_search(g, source=None, visitor=DFSVisitor()):
...
@@ -589,7 +599,7 @@ def dfs_search(g, source=None, visitor=DFSVisitor()):
except
StopSearch
:
except
StopSearch
:
pass
pass