Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
graph-tool
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
43
Issues
43
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tiago Peixoto
graph-tool
Commits
e17f7aaa
Commit
e17f7aaa
authored
Aug 06, 2020
by
Tiago Peixoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
spectral: implement more efficient linear operator interface
parent
fe602358
Pipeline
#697
passed with stage
in 72 minutes and 38 seconds
Changes
13
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1581 additions
and
91 deletions
+1581
-91
src/graph/spectral/graph_adjacency.cc
src/graph/spectral/graph_adjacency.cc
+56
-0
src/graph/spectral/graph_adjacency.hh
src/graph/spectral/graph_adjacency.hh
+52
-0
src/graph/spectral/graph_incidence.cc
src/graph/spectral/graph_incidence.cc
+36
-0
src/graph/spectral/graph_incidence.hh
src/graph/spectral/graph_incidence.hh
+101
-2
src/graph/spectral/graph_laplacian.cc
src/graph/spectral/graph_laplacian.cc
+62
-0
src/graph/spectral/graph_laplacian.hh
src/graph/spectral/graph_laplacian.hh
+159
-19
src/graph/spectral/graph_matrix.cc
src/graph/spectral/graph_matrix.cc
+60
-0
src/graph/spectral/graph_nonbacktracking.cc
src/graph/spectral/graph_nonbacktracking.cc
+88
-0
src/graph/spectral/graph_nonbacktracking.hh
src/graph/spectral/graph_nonbacktracking.hh
+181
-0
src/graph/spectral/graph_norm_laplacian.cc
src/graph/spectral/graph_norm_laplacian.cc
+64
-0
src/graph/spectral/graph_transition.cc
src/graph/spectral/graph_transition.cc
+70
-0
src/graph/spectral/graph_transition.hh
src/graph/spectral/graph_transition.hh
+87
-0
src/graph_tool/spectral/__init__.py
src/graph_tool/spectral/__init__.py
+565
-70
No files found.
src/graph/spectral/graph_adjacency.cc
View file @
e17f7aaa
...
...
@@ -61,3 +61,59 @@ void adjacency(GraphInterface& g, boost::any index, boost::any weight,
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
void
adjacency_matvec
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
python
::
object
ov
,
python
::
object
oret
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
index
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
typedef
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>
weight_map_t
;
typedef
mpl
::
push_back
<
edge_scalar_properties
,
weight_map_t
>::
type
weight_props_t
;
if
(
!
weight
.
empty
()
&&
!
belongs
<
edge_scalar_properties
>
()(
weight
))
throw
ValueException
(
"weight edge property must have a scalar value type"
);
if
(
weight
.
empty
())
weight
=
weight_map_t
();
multi_array_ref
<
double
,
1
>
v
=
get_array
<
double
,
1
>
(
ov
);
multi_array_ref
<
double
,
1
>
ret
=
get_array
<
double
,
1
>
(
oret
);
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
w
)
{
return
adj_matvec
(
graph
,
vi
,
w
,
v
,
ret
);
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
void
adjacency_matmat
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
python
::
object
ov
,
python
::
object
oret
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
index
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
typedef
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>
weight_map_t
;
typedef
mpl
::
push_back
<
edge_scalar_properties
,
weight_map_t
>::
type
weight_props_t
;
if
(
!
weight
.
empty
()
&&
!
belongs
<
edge_scalar_properties
>
()(
weight
))
throw
ValueException
(
"weight edge property must have a scalar value type"
);
if
(
weight
.
empty
())
weight
=
weight_map_t
();
multi_array_ref
<
double
,
2
>
v
=
get_array
<
double
,
2
>
(
ov
);
multi_array_ref
<
double
,
2
>
ret
=
get_array
<
double
,
2
>
(
oret
);
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
w
)
{
return
adj_matmat
(
graph
,
vi
,
w
,
v
,
ret
);
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
src/graph/spectral/graph_adjacency.hh
View file @
e17f7aaa
...
...
@@ -53,6 +53,58 @@ struct get_adjacency
}
};
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
V
>
void
adj_matvec
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
V
&
x
,
V
&
ret
)
{
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
size_t
i
=
get
(
index
,
v
);
std
::
remove_reference_t
<
decltype
(
ret
[
i
])
>
y
=
0
;
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
y
+=
get
(
w
,
e
)
*
x
[
get
(
index
,
target
(
e
,
g
))];
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
y
+=
x
[
get
(
index
,
u
)];
}
ret
[
i
]
=
y
;
});
}
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
M
>
void
adj_matmat
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
M
&
x
,
M
&
ret
)
{
size_t
k
=
x
.
shape
()[
1
];
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
size_t
i
=
get
(
index
,
v
);
auto
y
=
ret
[
i
];
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
{
auto
w_e
=
get
(
w
,
e
);
for
(
size_t
l
=
0
;
l
<
k
;
++
l
)
y
[
l
]
+=
w_e
*
x
[
get
(
index
,
target
(
e
,
g
))][
l
];
}
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
for
(
size_t
l
=
0
;
l
<
k
;
++
l
)
y
[
l
]
+=
x
[
get
(
index
,
u
)][
l
];
}
});
}
}
// namespace graph_tool
#endif // GRAPH_ADJACENCY_MATRIX_HH
src/graph/spectral/graph_incidence.cc
View file @
e17f7aaa
...
...
@@ -53,3 +53,39 @@ void incidence(GraphInterface& g, boost::any vindex, boost::any eindex,
},
vertex_scalar_properties
(),
edge_scalar_properties
())(
vindex
,
eindex
);
}
void
incidence_matvec
(
GraphInterface
&
g
,
boost
::
any
vindex
,
boost
::
any
eindex
,
python
::
object
ov
,
python
::
object
oret
,
bool
transpose
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
vindex
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
multi_array_ref
<
double
,
1
>
v
=
get_array
<
double
,
1
>
(
ov
);
multi_array_ref
<
double
,
1
>
ret
=
get_array
<
double
,
1
>
(
oret
);
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
ei
)
{
return
inc_matvec
(
graph
,
vi
,
ei
,
v
,
ret
,
transpose
);
},
vertex_scalar_properties
(),
edge_scalar_properties
())(
vindex
,
eindex
);
}
void
incidence_matmat
(
GraphInterface
&
g
,
boost
::
any
vindex
,
boost
::
any
eindex
,
python
::
object
ov
,
python
::
object
oret
,
bool
transpose
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
vindex
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
multi_array_ref
<
double
,
2
>
v
=
get_array
<
double
,
2
>
(
ov
);
multi_array_ref
<
double
,
2
>
ret
=
get_array
<
double
,
2
>
(
oret
);
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
ei
)
{
return
inc_matmat
(
graph
,
vi
,
ei
,
v
,
ret
,
transpose
);
},
vertex_scalar_properties
(),
edge_scalar_properties
())(
vindex
,
eindex
);
}
src/graph/spectral/graph_incidence.hh
View file @
e17f7aaa
...
...
@@ -39,7 +39,7 @@ struct get_incidence
{
for
(
const
auto
&
e
:
out_edges_range
(
v
,
g
))
{
if
(
graph_tool
::
is_directed
(
g
)
)
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
data
[
pos
]
=
-
1
;
else
data
[
pos
]
=
1
;
...
...
@@ -48,7 +48,7 @@ struct get_incidence
++
pos
;
}
if
(
graph_tool
::
is_directed
(
g
)
)
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
{
for
(
const
auto
&
e
:
in_edges_range
(
v
,
g
))
{
...
...
@@ -62,6 +62,105 @@ struct get_incidence
}
};
template
<
class
Graph
,
class
Vindex
,
class
EIndex
,
class
V
>
void
inc_matvec
(
Graph
&
g
,
Vindex
vindex
,
EIndex
eindex
,
V
&
x
,
V
&
ret
,
bool
transpose
)
{
if
(
!
transpose
)
{
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
auto
&
y
=
ret
[
get
(
vindex
,
v
)];
for
(
const
auto
&
e
:
out_edges_range
(
v
,
g
))
{
auto
u
=
eindex
[
e
];
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
y
-=
x
[
u
];
else
y
+=
x
[
u
];
}
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
{
for
(
const
auto
&
e
:
in_edges_range
(
v
,
g
))
{
auto
u
=
eindex
[
e
];
y
+=
x
[
u
];
}
}
});
}
else
{
parallel_edge_loop
(
g
,
[
&
](
const
auto
&
e
)
{
auto
u
=
eindex
[
e
];
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
ret
[
u
]
=
x
[
get
(
vindex
,
target
(
e
,
g
))]
-
x
[
get
(
vindex
,
source
(
e
,
g
))];
else
ret
[
u
]
=
x
[
get
(
vindex
,
target
(
e
,
g
))]
+
x
[
get
(
vindex
,
source
(
e
,
g
))];
});
}
}
template
<
class
Graph
,
class
Vindex
,
class
Eindex
,
class
M
>
void
inc_matmat
(
Graph
&
g
,
Vindex
vindex
,
Eindex
eindex
,
M
&
x
,
M
&
ret
,
bool
transpose
)
{
size_t
k
=
x
.
shape
()[
1
];
if
(
!
transpose
)
{
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
auto
y
=
ret
[
get
(
vindex
,
v
)];
for
(
const
auto
&
e
:
out_edges_range
(
v
,
g
))
{
auto
u
=
eindex
[
e
];
for
(
size_t
i
=
0
;
i
<
k
;
++
i
)
{
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
y
[
i
]
-=
x
[
u
][
i
];
else
y
[
i
]
+=
x
[
u
][
i
];
}
}
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
{
for
(
const
auto
&
e
:
in_edges_range
(
v
,
g
))
{
auto
u
=
eindex
[
e
];
for
(
size_t
i
=
0
;
i
<
k
;
++
i
)
y
[
i
]
+=
x
[
u
][
i
];
}
}
});
}
else
{
parallel_edge_loop
(
g
,
[
&
](
const
auto
&
e
)
{
auto
u
=
eindex
[
e
];
auto
s
=
get
(
vindex
,
source
(
e
,
g
));
auto
t
=
get
(
vindex
,
target
(
e
,
g
));
for
(
size_t
i
=
0
;
i
<
k
;
++
i
)
{
if
constexpr
(
graph_tool
::
is_directed_
::
apply
<
Graph
>::
type
::
value
)
ret
[
u
][
i
]
=
x
[
t
][
i
]
-
x
[
s
][
i
];
else
ret
[
u
][
i
]
=
x
[
t
][
i
]
+
x
[
s
][
i
];
}
});
}
}
}
// namespace graph_tool
#endif // GRAPH_INCIDENCE_HH
src/graph/spectral/graph_laplacian.cc
View file @
e17f7aaa
...
...
@@ -70,3 +70,65 @@ void laplacian(GraphInterface& g, boost::any index, boost::any weight,
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
void
laplacian_matvec
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
boost
::
any
deg
,
python
::
object
ov
,
python
::
object
oret
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
index
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
typedef
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>
weight_map_t
;
typedef
mpl
::
push_back
<
edge_scalar_properties
,
weight_map_t
>::
type
weight_props_t
;
if
(
!
weight
.
empty
()
&&
!
belongs
<
edge_scalar_properties
>
()(
weight
))
throw
ValueException
(
"weight edge property must have a scalar value type"
);
if
(
weight
.
empty
())
weight
=
weight_map_t
();
multi_array_ref
<
double
,
1
>
v
=
get_array
<
double
,
1
>
(
ov
);
multi_array_ref
<
double
,
1
>
ret
=
get_array
<
double
,
1
>
(
oret
);
typedef
typename
vprop_map_t
<
double
>::
type
deg_t
;
deg_t
::
unchecked_t
d
=
any_cast
<
deg_t
>
(
deg
).
get_unchecked
();
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
w
)
{
return
lap_matvec
(
graph
,
vi
,
w
,
d
,
v
,
ret
);
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
void
laplacian_matmat
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
boost
::
any
deg
,
python
::
object
ov
,
python
::
object
oret
)
{
if
(
!
belongs
<
vertex_scalar_properties
>
()(
index
))
throw
ValueException
(
"index vertex property must have a scalar value type"
);
typedef
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>
weight_map_t
;
typedef
mpl
::
push_back
<
edge_scalar_properties
,
weight_map_t
>::
type
weight_props_t
;
if
(
!
weight
.
empty
()
&&
!
belongs
<
edge_scalar_properties
>
()(
weight
))
throw
ValueException
(
"weight edge property must have a scalar value type"
);
if
(
weight
.
empty
())
weight
=
weight_map_t
();
typedef
typename
vprop_map_t
<
double
>::
type
deg_t
;
deg_t
::
unchecked_t
d
=
any_cast
<
deg_t
>
(
deg
).
get_unchecked
();
multi_array_ref
<
double
,
2
>
v
=
get_array
<
double
,
2
>
(
ov
);
multi_array_ref
<
double
,
2
>
ret
=
get_array
<
double
,
2
>
(
oret
);
run_action
<>
()
(
g
,
[
&
](
auto
&&
graph
,
auto
&&
vi
,
auto
&&
w
)
{
return
lap_matmat
(
graph
,
vi
,
w
,
d
,
v
,
ret
);
},
vertex_scalar_properties
(),
weight_props_t
())(
index
,
weight
);
}
src/graph/spectral/graph_laplacian.hh
View file @
e17f7aaa
...
...
@@ -119,6 +119,76 @@ struct get_laplacian
}
};
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
Deg
,
class
V
>
void
lap_matvec
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
Deg
d
,
V
&
x
,
V
&
ret
)
{
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
std
::
remove_reference_t
<
decltype
(
ret
[
v
])
>
y
=
0
;
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
{
auto
u
=
target
(
e
,
g
);
if
(
u
==
v
)
continue
;
auto
w_e
=
get
(
w
,
e
);
y
+=
w_e
*
x
[
get
(
index
,
u
)];
}
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
{
if
(
u
==
v
)
continue
;
y
+=
x
[
get
(
index
,
u
)];
}
}
ret
[
get
(
index
,
v
)]
=
d
[
v
]
*
x
[
get
(
index
,
v
)]
-
y
;
});
}
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
Deg
,
class
Mat
>
void
lap_matmat
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
Deg
d
,
Mat
&
x
,
Mat
&
ret
)
{
size_t
M
=
x
.
shape
()[
1
];
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
auto
vi
=
get
(
index
,
v
);
auto
y
=
ret
[
vi
];
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
{
auto
u
=
target
(
e
,
g
);
if
(
u
==
v
)
continue
;
auto
w_e
=
get
(
w
,
e
);
auto
ui
=
get
(
index
,
u
);
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
y
[
i
]
+=
w_e
*
x
[
ui
][
i
];
}
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
{
if
(
u
==
v
)
continue
;
auto
ui
=
get
(
index
,
u
);
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
y
[
i
]
+=
x
[
ui
][
i
];
}
}
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
ret
[
vi
][
i
]
=
d
[
v
]
*
x
[
vi
][
i
]
-
y
[
i
];
});
}
struct
get_norm_laplacian
...
...
@@ -130,41 +200,34 @@ struct get_norm_laplacian
multi_array_ref
<
int32_t
,
1
>&
j
)
const
{
int
pos
=
0
;
std
::
vector
<
double
>
degs
(
num_vertices
(
g
));
for
(
auto
v
:
vertices_range
(
g
))
{
double
k
s
=
0
;
double
k
=
0
;
switch
(
deg
)
{
case
OUT_DEG
:
k
s
=
sum_degree
(
g
,
v
,
weight
,
out_edge_iteratorS
<
Graph
>
());
k
=
sum_degree
(
g
,
v
,
weight
,
out_edge_iteratorS
<
Graph
>
());
break
;
case
IN_DEG
:
k
s
=
sum_degree
(
g
,
v
,
weight
,
in_edge_iteratorS
<
Graph
>
());
k
=
sum_degree
(
g
,
v
,
weight
,
in_edge_iteratorS
<
Graph
>
());
break
;
case
TOTAL_DEG
:
k
s
=
sum_degree
(
g
,
v
,
weight
,
all_edges_iteratorS
<
Graph
>
());
k
=
sum_degree
(
g
,
v
,
weight
,
all_edges_iteratorS
<
Graph
>
());
}
degs
[
v
]
=
sqrt
(
k
);
}
for
(
auto
v
:
vertices_range
(
g
))
{
double
ks
=
degs
[
v
];
for
(
const
auto
&
e
:
out_edges_range
(
v
,
g
))
{
if
(
source
(
e
,
g
)
==
target
(
e
,
g
))
continue
;
double
kt
=
0
;
switch
(
deg
)
{
case
OUT_DEG
:
kt
=
sum_degree
(
g
,
target
(
e
,
g
),
weight
,
out_edge_iteratorS
<
Graph
>
());
break
;
case
IN_DEG
:
kt
=
sum_degree
(
g
,
target
(
e
,
g
),
weight
,
in_edge_iteratorS
<
Graph
>
());
break
;
case
TOTAL_DEG
:
kt
=
sum_degree
(
g
,
target
(
e
,
g
),
weight
,
all_edges_iteratorS
<
Graph
>
());
}
double
kt
=
degs
[
target
(
e
,
g
)];
if
(
ks
*
kt
>
0
)
data
[
pos
]
=
-
get
(
weight
,
e
)
/
sqrt
(
ks
*
kt
);
data
[
pos
]
=
-
get
(
weight
,
e
)
/
(
ks
*
kt
);
i
[
pos
]
=
get
(
index
,
target
(
e
,
g
));
j
[
pos
]
=
get
(
index
,
source
(
e
,
g
));
...
...
@@ -180,6 +243,83 @@ struct get_norm_laplacian
}
};
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
Deg
,
class
V
>
void
nlap_matvec
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
Deg
id
,
V
&
x
,
V
&
ret
)
{
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
auto
vi
=
get
(
index
,
v
);
std
::
remove_reference_t
<
decltype
(
ret
[
v
])
>
y
=
0
;
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
{
auto
u
=
target
(
e
,
g
);
if
(
u
==
v
)
continue
;
auto
w_e
=
get
(
w
,
e
);
y
+=
w_e
*
x
[
get
(
index
,
u
)]
*
id
[
u
];
}
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
{
if
(
u
==
v
)
continue
;
y
+=
x
[
get
(
index
,
u
)]
*
id
[
u
];
}
}
if
(
id
[
v
]
>
0
)
ret
[
vi
]
=
x
[
vi
]
-
y
*
id
[
v
];
});
}
template
<
class
Graph
,
class
Vindex
,
class
Weight
,
class
Deg
,
class
Mat
>
void
nlap_matmat
(
Graph
&
g
,
Vindex
index
,
Weight
w
,
Deg
id
,
Mat
&
x
,
Mat
&
ret
)
{
size_t
M
=
x
.
shape
()[
1
];
parallel_vertex_loop
(
g
,
[
&
](
auto
v
)
{
auto
vi
=
get
(
index
,
v
);
auto
y
=
ret
[
vi
];
if
constexpr
(
!
std
::
is_same_v
<
Weight
,
UnityPropertyMap
<
double
,
GraphInterface
::
edge_t
>>
)
{
for
(
auto
e
:
in_or_out_edges_range
(
v
,
g
))
{
auto
u
=
target
(
e
,
g
);
if
(
u
==
v
)
continue
;
auto
w_e
=
get
(
w
,
e
);
auto
ui
=
get
(
index
,
u
);
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
y
[
i
]
+=
w_e
*
x
[
ui
][
i
]
*
id
[
u
];
}
}
else
{
for
(
auto
u
:
in_or_out_neighbors_range
(
v
,
g
))
{
if
(
u
==
v
)
continue
;
auto
ui
=
get
(
index
,
u
);
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
y
[
i
]
+=
x
[
ui
][
i
]
*
id
[
u
];
}
}
if
(
id
[
v
]
>
0
)
{
for
(
size_t
i
=
0
;
i
<
M
;
++
i
)
y
[
i
]
=
x
[
vi
][
i
]
-
y
[
i
]
*
id
[
v
];
}
});
}
}
// namespace graph_tool
...
...
src/graph/spectral/graph_matrix.cc
View file @
e17f7aaa
...
...
@@ -26,41 +26,101 @@ void adjacency(GraphInterface& g, boost::any index, boost::any weight,
python
::
object
odata
,
python
::
object
oi
,
python
::
object
oj
);
void
adjacency_matvec
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
python
::
object
ov
,
python
::
object
oret
);
void
adjacency_matmat
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
python
::
object
ov
,
python
::
object
oret
);
void
laplacian
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
string
sdeg
,
python
::
object
odata
,
python
::
object
oi
,
python
::
object
oj
);
void
laplacian_matvec
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,
boost
::
any
deg
,
python
::
object
ov
,
python
::
object
oret
);
void
laplacian_matmat
(
GraphInterface
&
g
,
boost
::
any
index
,
boost
::
any
weight
,