Skip to content

Commit 41ded70

Browse files
committed
feat: conversion of vertex and edge set lists is now supported
1 parent 4b33f39 commit 41ded70

File tree

8 files changed

+850
-64
lines changed

8 files changed

+850
-64
lines changed

src/codegen/internal_functions.py.in

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import numpy.typing as npt
22

3-
from typing import Any, Iterable, Optional, Tuple
3+
from typing import Any, Iterable, List, Optional, Tuple
44

55
from .conversion import * # noqa
66
from .enums import * # noqa
@@ -17,7 +17,15 @@ from .types import (
1717
np_type_of_igraph_integer_t,
1818
np_type_of_igraph_real_t,
1919
)
20-
from .wrappers import _Graph, _Matrix, _MatrixInt, _Vector, _VectorBool, _VectorInt
20+
from .wrappers import (
21+
_Graph,
22+
_Matrix,
23+
_MatrixInt,
24+
_Vector,
25+
_VectorBool,
26+
_VectorInt,
27+
_VectorIntList
28+
)
2129

2230
# fmt: off
2331
# flake8: noqa: E743

src/codegen/internal_lib.py.in

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,50 @@ igraph_matrix_int_e_ptr = _lib.igraph_matrix_int_e_ptr
260260
igraph_matrix_int_e_ptr.restype = POINTER(igraph_integer_t)
261261
igraph_matrix_int_e_ptr.argtypes = [POINTER(igraph_matrix_int_t), igraph_integer_t, igraph_integer_t]
262262

263+
# List of vectors type
264+
265+
igraph_vector_list_init = _lib.igraph_vector_list_init
266+
igraph_vector_list_init.restype = handle_igraph_error_t
267+
igraph_vector_list_init.argtypes = [POINTER(igraph_vector_list_t), igraph_integer_t]
268+
269+
igraph_vector_list_destroy = _lib.igraph_vector_list_destroy
270+
igraph_vector_list_destroy.restype = None
271+
igraph_vector_list_destroy.argtypes = [c_void_p]
272+
273+
igraph_vector_list_get_ptr = _lib.igraph_vector_list_get_ptr
274+
igraph_vector_list_get_ptr.restype = POINTER(igraph_vector_t)
275+
igraph_vector_list_get_ptr.argtypes = [POINTER(igraph_vector_list_t), igraph_integer_t]
276+
277+
igraph_vector_list_push_back = _lib.igraph_vector_list_push_back
278+
igraph_vector_list_push_back.restype = handle_igraph_error_t
279+
igraph_vector_list_push_back.argtypes = [POINTER(igraph_vector_list_t), POINTER(igraph_vector_t)]
280+
281+
igraph_vector_list_size = _lib.igraph_vector_list_size
282+
igraph_vector_list_size.restype = igraph_integer_t
283+
igraph_vector_list_size.argtypes = [POINTER(igraph_vector_list_t)]
284+
285+
# List of integer vectors type
286+
287+
igraph_vector_int_list_init = _lib.igraph_vector_int_list_init
288+
igraph_vector_int_list_init.restype = handle_igraph_error_t
289+
igraph_vector_int_list_init.argtypes = [POINTER(igraph_vector_int_list_t), igraph_integer_t]
290+
291+
igraph_vector_int_list_destroy = _lib.igraph_vector_int_list_destroy
292+
igraph_vector_int_list_destroy.restype = None
293+
igraph_vector_int_list_destroy.argtypes = [c_void_p]
294+
295+
igraph_vector_int_list_get_ptr = _lib.igraph_vector_int_list_get_ptr
296+
igraph_vector_int_list_get_ptr.restype = POINTER(igraph_vector_int_t)
297+
igraph_vector_int_list_get_ptr.argtypes = [POINTER(igraph_vector_int_list_t), igraph_integer_t]
298+
299+
igraph_vector_int_list_push_back = _lib.igraph_vector_int_list_push_back
300+
igraph_vector_int_list_push_back.restype = handle_igraph_error_t
301+
igraph_vector_int_list_push_back.argtypes = [POINTER(igraph_vector_int_list_t), POINTER(igraph_vector_int_t)]
302+
303+
igraph_vector_int_list_size = _lib.igraph_vector_int_list_size
304+
igraph_vector_int_list_size.restype = igraph_integer_t
305+
igraph_vector_int_list_size.argtypes = [POINTER(igraph_vector_int_list_t)]
306+
263307
# Vertex selector type
264308

265309
igraph_vs_none = _lib.igraph_vs_none

src/codegen/types.yaml

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ VERTEX:
109109
IN: "%C% = vertexlike_to_igraph_integer_t(%I%)"
110110
OUT: "%C% = igraph_integer_t(0)"
111111

112-
VERTEX_COLOR:
112+
VERTEX_COLORS:
113113
PY_TYPE: Iterable[int]
114114
PY_RETURN_TYPE: npt.NDArray[np_type_of_igraph_integer_t]
115115
INCONV:
@@ -126,6 +126,14 @@ VERTEX_INDICES:
126126
OUT: "%C% = _VectorInt.create(0)"
127127
OUTCONV: "%I% = igraph_vector_int_t_to_numpy_array(%C%)"
128128

129+
VERTEX_INDICES_LIST:
130+
PY_TYPE: Iterable[Iterable[VertexLike]]
131+
PY_RETURN_TYPE: List[npt.NDArray[np_type_of_igraph_integer_t]]
132+
INCONV:
133+
IN: "%C% = iterable_of_vertex_index_iterable_to_igraph_vector_int_list_t(%I%)"
134+
OUT: "%C% = _VectorIntList.create(0)"
135+
OUTCONV: "%I% = igraph_vector_int_list_t_to_list_of_numpy_array(%C%)"
136+
129137
VERTEX_INDEX_PAIRS:
130138
PY_TYPE: Iterable[VertexPair]
131139
INCONV:
@@ -140,12 +148,12 @@ VERTEX_SELECTOR:
140148
ALL: '"all"'
141149
CALL: "%C%.unwrap()"
142150

143-
VERTEX_QTY:
151+
VERTEX_QTYS:
144152
PY_TYPE: Iterable[float]
145153
PY_RETURN_TYPE: npt.NDArray[np_type_of_igraph_real_t]
146154
INCONV:
147-
IN: "%C% = vertex_qty_to_igraph_vector_t_view(%I%, %I1%)"
148-
INOUT: "%C% = vertex_qty_to_igraph_vector_t(%I%, %I1%)"
155+
IN: "%C% = vertex_qtys_to_igraph_vector_t_view(%I%, %I1%)"
156+
INOUT: "%C% = vertex_qtys_to_igraph_vector_t(%I%, %I1%)"
149157
OUT: "%C% = _Vector.create(0)"
150158
OUTCONV: "%I% = igraph_vector_t_to_numpy_array(%C%)"
151159

@@ -156,7 +164,7 @@ EDGE:
156164
IN: "%C% = edgelike_to_igraph_integer_t(%I%)"
157165
OUT: "%C% = igraph_integer_t(0)"
158166

159-
EDGE_COLOR:
167+
EDGE_COLORS:
160168
PY_TYPE: Iterable[int]
161169
PY_RETURN_TYPE: npt.NDArray[np_type_of_igraph_integer_t]
162170
INCONV:
@@ -173,6 +181,14 @@ EDGE_INDICES:
173181
OUT: "%C% = _VectorInt.create(0)"
174182
OUTCONV: "%I% = igraph_vector_int_t_to_numpy_array(%C%)"
175183

184+
EDGE_INDICES_LIST:
185+
PY_TYPE: Iterable[Iterable[EdgeLike]]
186+
PY_RETURN_TYPE: List[npt.NDArray[np_type_of_igraph_integer_t]]
187+
INCONV:
188+
IN: "%C% = iterable_of_edge_index_iterable_to_igraph_vector_int_list_t(%I%)"
189+
OUT: "%C% = _VectorIntList.create(0)"
190+
OUTCONV: "%I% = igraph_vector_int_list_t_to_list_of_numpy_array(%C%)"
191+
176192
EDGE_SELECTOR:
177193
PY_TYPE: EdgeSelector
178194
INCONV:
@@ -181,7 +197,7 @@ EDGE_SELECTOR:
181197
ALL: '"all"'
182198
CALL: "%C%.unwrap()"
183199

184-
EDGEWEIGHTS:
200+
EDGE_WEIGHTS:
185201
PY_TYPE: Iterable[float]
186202
PY_RETURN_TYPE: npt.NDArray[np_type_of_igraph_real_t]
187203
INCONV:
@@ -190,7 +206,7 @@ EDGEWEIGHTS:
190206
OUT: "%C% = _Vector.create(0)"
191207
OUTCONV: "%I% = igraph_vector_t_to_numpy_array(%C%)"
192208

193-
EDGE_CAPACITY:
209+
EDGE_CAPACITIES:
194210
PY_TYPE: Iterable[float]
195211
PY_RETURN_TYPE: npt.NDArray[np_type_of_igraph_real_t]
196212
INCONV:

src/igraph_ctypes/_internal/conversion.py

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,21 @@
2626
igraph_vector_bool_push_back,
2727
igraph_vector_bool_size,
2828
igraph_vector_bool_view,
29+
igraph_vector_e,
30+
igraph_vector_e_ptr,
31+
igraph_vector_init_array,
2932
igraph_vector_int_e,
3033
igraph_vector_int_e_ptr,
3134
igraph_vector_int_init_array,
35+
igraph_vector_int_list_get_ptr,
36+
igraph_vector_int_list_push_back,
37+
igraph_vector_int_list_size,
3238
igraph_vector_int_push_back,
3339
igraph_vector_int_size,
3440
igraph_vector_int_view,
35-
igraph_vector_e,
36-
igraph_vector_e_ptr,
37-
igraph_vector_init_array,
41+
igraph_vector_list_get_ptr,
42+
igraph_vector_list_push_back,
43+
igraph_vector_list_size,
3844
igraph_vector_push_back,
3945
igraph_vector_size,
4046
igraph_vector_view,
@@ -67,6 +73,8 @@
6773
_Vector,
6874
_VectorBool,
6975
_VectorInt,
76+
_VectorIntList,
77+
_VectorList,
7078
_VertexSelector,
7179
)
7280

@@ -89,7 +97,13 @@
8997
"igraph_vector_t_to_numpy_array",
9098
"igraph_vector_bool_t_to_numpy_array",
9199
"igraph_vector_int_t_to_numpy_array",
100+
"igraph_vector_int_list_t_to_list_of_numpy_array",
101+
"igraph_vector_list_t_to_list_of_numpy_array",
92102
"iterable_edge_indices_to_igraph_vector_int_t",
103+
"iterable_of_edge_index_iterable_to_igraph_vector_int_list_t",
104+
"iterable_of_iterable_to_igraph_vector_int_list_t",
105+
"iterable_of_iterable_to_igraph_vector_list_t",
106+
"iterable_of_vertex_index_iterable_to_igraph_vector_int_list_t",
93107
"iterable_to_igraph_vector_bool_t",
94108
"iterable_to_igraph_vector_bool_t_view",
95109
"iterable_to_igraph_vector_int_t",
@@ -106,8 +120,8 @@
106120
"vertex_selector_to_igraph_vs_t",
107121
"vertex_colors_to_igraph_vector_t",
108122
"vertex_colors_to_igraph_vector_t_view",
109-
"vertex_qty_to_igraph_vector_t",
110-
"vertex_qty_to_igraph_vector_t_view",
123+
"vertex_qtys_to_igraph_vector_t",
124+
"vertex_qtys_to_igraph_vector_t_view",
111125
)
112126

113127

@@ -289,6 +303,60 @@ def iterable_vertex_indices_to_igraph_vector_int_t(
289303
return result
290304

291305

306+
def iterable_of_iterable_to_igraph_vector_int_list_t(
307+
items: Iterable[Iterable[int]],
308+
) -> _VectorIntList:
309+
result = _VectorIntList.create(0)
310+
311+
# TODO:
312+
#
313+
# - if items is a sequence (i.e. we know its length), we could optimize the
314+
# conversion
315+
# - we could re-use an already-constructed _VectorInt if we had an alternative
316+
# iterable_to_igraph_vector_int_t() that receives a _VectorInt from the
317+
# outside
318+
319+
for item in items:
320+
vec = iterable_to_igraph_vector_int_t(item)
321+
igraph_vector_int_list_push_back(result, vec)
322+
vec.release()
323+
324+
return result
325+
326+
327+
def iterable_of_iterable_to_igraph_vector_list_t(
328+
items: Iterable[Iterable[float]],
329+
) -> _VectorList:
330+
result = _VectorList.create(0)
331+
332+
# TODO:
333+
#
334+
# - if items is a sequence (i.e. we know its length), we could optimize the
335+
# conversion
336+
# - we could re-use an already-constructed _VectorInt if we had an alternative
337+
# iterable_to_igraph_vector_t() that receives a _VectorInt from the
338+
# outside
339+
340+
for item in items:
341+
vec = iterable_to_igraph_vector_t(item)
342+
igraph_vector_list_push_back(result, vec)
343+
vec.release()
344+
345+
return result
346+
347+
348+
def iterable_of_edge_index_iterable_to_igraph_vector_int_list_t(
349+
items: Iterable[Iterable[VertexLike]],
350+
) -> _VectorIntList:
351+
return iterable_of_iterable_to_igraph_vector_int_list_t(items)
352+
353+
354+
def iterable_of_vertex_index_iterable_to_igraph_vector_int_list_t(
355+
items: Iterable[Iterable[VertexLike]],
356+
) -> _VectorIntList:
357+
return iterable_of_iterable_to_igraph_vector_int_list_t(items)
358+
359+
292360
def sequence_to_igraph_matrix_int_t(items: MatrixIntLike) -> _MatrixInt:
293361
"""Converts a sequence of sequences of Python integers to an igraph matrix
294362
of integers. Each sequence in the top-level sequence must have the same
@@ -553,14 +621,14 @@ def vertex_colors_to_igraph_vector_t_view(
553621
return iterable_to_igraph_vector_int_t_view(colors)
554622

555623

556-
def vertex_qty_to_igraph_vector_t(weights: Iterable[float], graph: _Graph) -> _Vector:
624+
def vertex_qtys_to_igraph_vector_t(weights: Iterable[float], graph: _Graph) -> _Vector:
557625
"""Converts a Python iterable of floating-point numbers to a vector of
558626
vertex-related quantities.
559627
"""
560628
return iterable_to_igraph_vector_t(weights)
561629

562630

563-
def vertex_qty_to_igraph_vector_t_view(
631+
def vertex_qtys_to_igraph_vector_t_view(
564632
weights: Optional[Iterable[float]], graph: _Graph
565633
) -> Optional[_Vector]:
566634
"""Converts a Python iterable of floating-point numbers to a vector of
@@ -643,3 +711,39 @@ def igraph_vector_int_t_to_numpy_array(
643711
if n > 0:
644712
memmove(result.ctypes.data, igraph_vector_int_e_ptr(vector, 0), result.nbytes)
645713
return result
714+
715+
716+
def igraph_vector_list_t_to_list_of_numpy_array(
717+
vector_list: _VectorList,
718+
) -> List[npt.NDArray[np_type_of_igraph_real_t]]:
719+
n = igraph_vector_list_size(vector_list)
720+
vec = _Vector()
721+
result = []
722+
723+
for i in range(n):
724+
# We are re-using the same _Vector instance to wrap different
725+
# low-level igraph_vector_t instances because it's only temporary
726+
# until we convert it to a NumPy array
727+
ptr = igraph_vector_list_get_ptr(vector_list, i)
728+
vec._set_wrapped_instance(ptr.contents)
729+
result.append(igraph_vector_t_to_numpy_array(vec))
730+
731+
return result
732+
733+
734+
def igraph_vector_int_list_t_to_list_of_numpy_array(
735+
vector_list: _VectorIntList,
736+
) -> List[npt.NDArray[np_type_of_igraph_integer_t]]:
737+
n = igraph_vector_int_list_size(vector_list)
738+
vec = _VectorInt()
739+
result = []
740+
741+
for i in range(n):
742+
# We are re-using the same _VectorInt instance to wrap different
743+
# low-level igraph_vector_int_t instances because it's only temporary
744+
# until we convert it to a NumPy array
745+
ptr = igraph_vector_int_list_get_ptr(vector_list, i)
746+
vec._set_wrapped_instance(ptr.contents)
747+
result.append(igraph_vector_int_t_to_numpy_array(vec))
748+
749+
return result

0 commit comments

Comments
 (0)