hdlib 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hdlib/__init__.py +16 -0
- hdlib/arithmetic/__init__.py +265 -0
- hdlib/arithmetic/quantum.py +1257 -0
- hdlib/model/__init__.py +12 -0
- hdlib/model/classification.py +1719 -0
- hdlib/model/clustering.py +172 -0
- hdlib/model/graph.py +764 -0
- hdlib/model/regression.py +306 -0
- hdlib/space.py +864 -0
- hdlib/vector.py +608 -0
- hdlib-2.1.0.data/scripts/chopin2.py +473 -0
- hdlib-2.1.0.dist-info/METADATA +137 -0
- hdlib-2.1.0.dist-info/RECORD +16 -0
- hdlib-2.1.0.dist-info/WHEEL +5 -0
- hdlib-2.1.0.dist-info/licenses/LICENSE +21 -0
- hdlib-2.1.0.dist-info/top_level.txt +1 -0
hdlib/vector.py
ADDED
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"""Implementation of hyperdimensional Vector.
|
|
2
|
+
|
|
3
|
+
__hdlib__ provides the _Vector_ class under _hdlib.vector_ for building the abstract representation of hyperdimensional vectors."""
|
|
4
|
+
|
|
5
|
+
import errno
|
|
6
|
+
import os
|
|
7
|
+
import pickle
|
|
8
|
+
import uuid
|
|
9
|
+
from typing import Optional, Set, Union
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
from hdlib import __version__
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Vector(object):
|
|
17
|
+
"""Vector object."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
name: Optional[str]=None,
|
|
22
|
+
size: int=10000,
|
|
23
|
+
vector: Optional[np.ndarray]=None,
|
|
24
|
+
vtype: str="bipolar",
|
|
25
|
+
tags: Optional[Set[Union[str, int, float]]]=None,
|
|
26
|
+
seed: Optional[int]=None,
|
|
27
|
+
warning: bool=False,
|
|
28
|
+
from_file: Optional[os.path.abspath]=None,
|
|
29
|
+
) -> "Vector":
|
|
30
|
+
"""Initialize a Vector object.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
name : str, optional
|
|
35
|
+
The unique identifier of the Vector object. A random UUID v4 is generated if not specified.
|
|
36
|
+
size : int, optional, default 10000
|
|
37
|
+
The size of the vector. It is 10,000 by default.
|
|
38
|
+
vector : numpy.ndarray, optional, default None
|
|
39
|
+
The actual vector. A random vector is created if not specified.
|
|
40
|
+
vtype : {'binary', 'bipolar'}, default 'bipolar'
|
|
41
|
+
The vector type.
|
|
42
|
+
tags : set, default None
|
|
43
|
+
An optional set of vector tags. Tags can be str, int, and float.
|
|
44
|
+
seed : int, default None
|
|
45
|
+
An optional seed for reproducibly generating the vector numpy.ndarray randomly.
|
|
46
|
+
warning : bool, default False
|
|
47
|
+
Print warning messages if True.
|
|
48
|
+
from_file : str, default None
|
|
49
|
+
Path to a pickle file. Used to load a Vector object from file.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
Vector
|
|
54
|
+
A new Vector object.
|
|
55
|
+
|
|
56
|
+
Raises
|
|
57
|
+
------
|
|
58
|
+
Exception
|
|
59
|
+
If the pickle object in `from_file` is not instance of Vector.
|
|
60
|
+
FileNotFoundError
|
|
61
|
+
If `from_file` is not None but the file does not exist.
|
|
62
|
+
TypeError
|
|
63
|
+
- if the vector name is not instance of a primitive;
|
|
64
|
+
- if `tags` is not an instance of set;
|
|
65
|
+
- if `vector` is not an instance of numpy.ndarray;
|
|
66
|
+
- if `size` is not an integer number.
|
|
67
|
+
ValueError
|
|
68
|
+
If `vtype` is different than 'binary' or 'bipolar'.
|
|
69
|
+
|
|
70
|
+
Examples
|
|
71
|
+
--------
|
|
72
|
+
>>> from hdlib.vector import Vector
|
|
73
|
+
>>> vector = Vector()
|
|
74
|
+
>>> type(vector)
|
|
75
|
+
<class 'hdlib.vector.Vector'>
|
|
76
|
+
|
|
77
|
+
A new bipolar vector with a size of 1,000 is created by default.
|
|
78
|
+
|
|
79
|
+
>>> vector1 = Vector()
|
|
80
|
+
>>> vector1.dump(to_file='~/my_vector.pkl')
|
|
81
|
+
>>> vector2 = Vector(from_file='~/my_vector.pkl')
|
|
82
|
+
>>> type(vector2)
|
|
83
|
+
<class 'hdlib.vector.Vector'>
|
|
84
|
+
|
|
85
|
+
This creates a random bipolar vector `vector1`, dumps the object to a pickle file under the home directory,
|
|
86
|
+
and finally create a new vector object `vector2` from the pickle file.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
# Conditions on vector name or ID
|
|
90
|
+
# Vector name is casted to string. For this reason, only Python primitives are allowed
|
|
91
|
+
# A random name is assigned if not specified
|
|
92
|
+
try:
|
|
93
|
+
if name is None:
|
|
94
|
+
name = str(uuid.uuid4())
|
|
95
|
+
|
|
96
|
+
else:
|
|
97
|
+
name = str(name)
|
|
98
|
+
|
|
99
|
+
self.name = name
|
|
100
|
+
|
|
101
|
+
except:
|
|
102
|
+
raise TypeError("Vector name must be instance of a primitive")
|
|
103
|
+
|
|
104
|
+
# Register random seed for reproducibility
|
|
105
|
+
self.seed = seed
|
|
106
|
+
|
|
107
|
+
# Take track of the hdlib version
|
|
108
|
+
self.version = __version__
|
|
109
|
+
|
|
110
|
+
if tags and not isinstance(tags, set):
|
|
111
|
+
raise TypeError("Tags must be a set")
|
|
112
|
+
|
|
113
|
+
# Add tags
|
|
114
|
+
self.tags = tags if tags else set()
|
|
115
|
+
|
|
116
|
+
# Add links
|
|
117
|
+
# Used to link Vectors by their names or IDs
|
|
118
|
+
self.parents = set()
|
|
119
|
+
self.children = set()
|
|
120
|
+
|
|
121
|
+
# Conditions on vector
|
|
122
|
+
# It must be a numpy.ndarray
|
|
123
|
+
# A random vector is generated if not specified
|
|
124
|
+
if vector is not None:
|
|
125
|
+
if not isinstance(vector, np.ndarray):
|
|
126
|
+
raise TypeError("Vector must be instance of numpy.ndarray")
|
|
127
|
+
|
|
128
|
+
self.vector = vector
|
|
129
|
+
|
|
130
|
+
self.size = len(self.vector)
|
|
131
|
+
|
|
132
|
+
self.vtype = vtype
|
|
133
|
+
|
|
134
|
+
elif from_file:
|
|
135
|
+
if not os.path.isfile(from_file):
|
|
136
|
+
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), from_file)
|
|
137
|
+
|
|
138
|
+
else:
|
|
139
|
+
# Load vector from pickle file
|
|
140
|
+
with open(from_file, "rb") as pkl:
|
|
141
|
+
from_file_obj = pickle.load(pkl)
|
|
142
|
+
|
|
143
|
+
if not isinstance(from_file_obj, type(self)):
|
|
144
|
+
raise Exception("Pickle object is not instance of {}".format(type(self)))
|
|
145
|
+
|
|
146
|
+
self.__dict__.update(from_file_obj.__dict__)
|
|
147
|
+
|
|
148
|
+
if self.version != __version__:
|
|
149
|
+
print("Warning: the specified Vector has been created with a different version of hdlib")
|
|
150
|
+
|
|
151
|
+
else:
|
|
152
|
+
if not isinstance(size, int):
|
|
153
|
+
raise TypeError("Vector size must be an integer number")
|
|
154
|
+
|
|
155
|
+
self.size = size
|
|
156
|
+
|
|
157
|
+
if vtype not in ("bipolar", "binary"):
|
|
158
|
+
raise ValueError("Vector type can be binary or bipolar only")
|
|
159
|
+
|
|
160
|
+
# Add vector type
|
|
161
|
+
self.vtype = vtype.lower()
|
|
162
|
+
|
|
163
|
+
if seed is None:
|
|
164
|
+
rand = np.random.default_rng()
|
|
165
|
+
|
|
166
|
+
else:
|
|
167
|
+
# Conditions on random seed for reproducibility
|
|
168
|
+
# numpy allows integers as random seeds
|
|
169
|
+
if not isinstance(seed, int):
|
|
170
|
+
raise TypeError("Seed must be an integer number")
|
|
171
|
+
|
|
172
|
+
rand = np.random.default_rng(seed=self.seed)
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
# Use the following instructions to generate random vectors with real numbers
|
|
176
|
+
self.vector = rand.uniform(low=-1.0, high=1.0, size=(self.size,))
|
|
177
|
+
self.vector /= np.linalg.norm(self.vector)
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
# Build a random binary vector
|
|
181
|
+
self.vector = rand.integers(2, size=size)
|
|
182
|
+
|
|
183
|
+
if vtype == "bipolar":
|
|
184
|
+
# Build a random bipolar vector
|
|
185
|
+
self.vector = 2 * self.vector - 1
|
|
186
|
+
|
|
187
|
+
def __len__(self) -> int:
|
|
188
|
+
"""Get the vector size.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
int
|
|
193
|
+
The vector size.
|
|
194
|
+
|
|
195
|
+
Examples
|
|
196
|
+
--------
|
|
197
|
+
>>> from hdlib.vector import Vector
|
|
198
|
+
>>> vector = Vector()
|
|
199
|
+
>>> len(vector)
|
|
200
|
+
10000
|
|
201
|
+
|
|
202
|
+
Return the vector size, which is 10,000 by default here
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
return self.size
|
|
206
|
+
|
|
207
|
+
def __str__(self) -> str:
|
|
208
|
+
"""Print the Vector object properties.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
str
|
|
213
|
+
A description of the Vector object. It reports the name, seed, size,
|
|
214
|
+
vector type, tags, and the actual vector.
|
|
215
|
+
|
|
216
|
+
Examples
|
|
217
|
+
--------
|
|
218
|
+
>>> from hdlib.vector import Vector
|
|
219
|
+
>>> vector = Vector()
|
|
220
|
+
>>> print(vector)
|
|
221
|
+
|
|
222
|
+
Class: hdlib.vector.Vector
|
|
223
|
+
Version: 0.1.17
|
|
224
|
+
Name: 89ea628b-3d29-47e1-9d10-34bdbfce8d40
|
|
225
|
+
Seed: None
|
|
226
|
+
Size: 10000
|
|
227
|
+
Type: bipolar
|
|
228
|
+
Tags:
|
|
229
|
+
|
|
230
|
+
[]
|
|
231
|
+
|
|
232
|
+
Vector:
|
|
233
|
+
|
|
234
|
+
[ 1 -1 -1 ... -1 1 -1]
|
|
235
|
+
|
|
236
|
+
Print the Vector object properties. The name has been generated as a UUID v4, while
|
|
237
|
+
the vector size and type are 10,000 and 'bipolar' by default. No tags have been specified.
|
|
238
|
+
Thus, the set of vector tags is empty.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
return f"""
|
|
242
|
+
Class: hdlib.vector.Vector
|
|
243
|
+
Version: {self.version}
|
|
244
|
+
Name: {self.name}
|
|
245
|
+
Seed: {self.seed}
|
|
246
|
+
Size: {self.size}
|
|
247
|
+
Type: {self.vtype}
|
|
248
|
+
Tags:
|
|
249
|
+
|
|
250
|
+
{np.array(list(self.tags))}
|
|
251
|
+
|
|
252
|
+
Vector:
|
|
253
|
+
|
|
254
|
+
{self.vector}
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
def __add__(self, vector: "Vector") -> "Vector":
|
|
258
|
+
"""Implement the addition operator between two Vector objects as bundle.
|
|
259
|
+
|
|
260
|
+
Returns
|
|
261
|
+
-------
|
|
262
|
+
Vector
|
|
263
|
+
A new vector object as the result of the bundle operator on the two input vectors.
|
|
264
|
+
|
|
265
|
+
Raises
|
|
266
|
+
------
|
|
267
|
+
TypeError
|
|
268
|
+
If the input `vector` is not instance of the Vector class.
|
|
269
|
+
|
|
270
|
+
Examples
|
|
271
|
+
--------
|
|
272
|
+
>>> from hdlib.vector import Vector
|
|
273
|
+
>>> vector1 = Vector()
|
|
274
|
+
>>> vector2 = Vector()
|
|
275
|
+
>>> vector3 = vector1 + vector2
|
|
276
|
+
>>> type(vector3)
|
|
277
|
+
<class 'hdlib.vector.Vector'>
|
|
278
|
+
|
|
279
|
+
The bundle function returns a new Vector object whose content is computed as the element-wise sum
|
|
280
|
+
of the two input vectors.
|
|
281
|
+
"""
|
|
282
|
+
|
|
283
|
+
if not isinstance(vector, type(self)):
|
|
284
|
+
raise TypeError("Cannot apply the bundle operator to non-Vector objects")
|
|
285
|
+
|
|
286
|
+
# Import arithmetic.bundle here to avoid circular imports
|
|
287
|
+
from hdlib.arithmetic import bundle as bundle_operator
|
|
288
|
+
|
|
289
|
+
return bundle_operator(self, vector)
|
|
290
|
+
|
|
291
|
+
def __sub__(self, vector: "Vector") -> "Vector":
|
|
292
|
+
"""Implement the subtraction operator between two Vector objects.
|
|
293
|
+
|
|
294
|
+
Returns
|
|
295
|
+
-------
|
|
296
|
+
Vector
|
|
297
|
+
A new vector object as the result of the subtraction operator on the two input vectors.
|
|
298
|
+
|
|
299
|
+
Raises
|
|
300
|
+
------
|
|
301
|
+
TypeError
|
|
302
|
+
If the input `vector` is not instance of the Vector class.
|
|
303
|
+
|
|
304
|
+
Examples
|
|
305
|
+
--------
|
|
306
|
+
>>> from hdlib.vector import Vector
|
|
307
|
+
>>> vector1 = Vector()
|
|
308
|
+
>>> vector2 = Vector()
|
|
309
|
+
>>> vector3 = vector1 - vector2
|
|
310
|
+
>>> type(vector3)
|
|
311
|
+
<class 'hdlib.vector.Vector'>
|
|
312
|
+
|
|
313
|
+
The subtraction operation returns a new Vector object whose content is computed as the element-wise
|
|
314
|
+
subtraction of the two input vectors.
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
if not isinstance(vector, type(self)):
|
|
318
|
+
raise TypeError("Cannot apply the subtraction operator to non-Vector objects")
|
|
319
|
+
|
|
320
|
+
# Import arithmetic.bind here to avoid circular imports
|
|
321
|
+
from hdlib.arithmetic import subtraction as subtraction_operator
|
|
322
|
+
|
|
323
|
+
return subtraction_operator(self, vector)
|
|
324
|
+
|
|
325
|
+
def __mul__(self, vector: "Vector") -> "Vector":
|
|
326
|
+
"""Implement the multiplication operator between two Vector objects as bind.
|
|
327
|
+
|
|
328
|
+
Returns
|
|
329
|
+
-------
|
|
330
|
+
Vector
|
|
331
|
+
A new vector object as the result of the bind operator on the two input vectors.
|
|
332
|
+
|
|
333
|
+
Raises
|
|
334
|
+
------
|
|
335
|
+
TypeError
|
|
336
|
+
If the input `vector` is not instance of the Vector class.
|
|
337
|
+
|
|
338
|
+
Examples
|
|
339
|
+
--------
|
|
340
|
+
>>> from hdlib.vector import Vector
|
|
341
|
+
>>> vector1 = Vector()
|
|
342
|
+
>>> vector2 = Vector()
|
|
343
|
+
>>> vector3 = vector1 * vector2
|
|
344
|
+
>>> type(vector3)
|
|
345
|
+
<class 'hdlib.vector.Vector'>
|
|
346
|
+
|
|
347
|
+
The bind function returns a new Vector object whose content is computed as the element-wise
|
|
348
|
+
multiplication of the two input vectors.
|
|
349
|
+
"""
|
|
350
|
+
|
|
351
|
+
if not isinstance(vector, type(self)):
|
|
352
|
+
raise TypeError("Cannot apply the bind operator to non-Vector objects")
|
|
353
|
+
|
|
354
|
+
# Import arithmetic.bind here to avoid circular imports
|
|
355
|
+
from hdlib.arithmetic import bind as bind_operator
|
|
356
|
+
|
|
357
|
+
return bind_operator(self, vector)
|
|
358
|
+
|
|
359
|
+
def dist(self, vector: "Vector", method: str="cosine") -> float:
|
|
360
|
+
"""Compute distance between vectors.
|
|
361
|
+
|
|
362
|
+
Parameters
|
|
363
|
+
----------
|
|
364
|
+
vector : Vector
|
|
365
|
+
A Vector object from which the distance must be computed.
|
|
366
|
+
method : {'cosine', 'euclidean', 'hamming'}, optional, default 'cosine'
|
|
367
|
+
The distance method.
|
|
368
|
+
|
|
369
|
+
Returns
|
|
370
|
+
-------
|
|
371
|
+
float
|
|
372
|
+
The distance between the current Vector object and the input `vector`.
|
|
373
|
+
|
|
374
|
+
Raises
|
|
375
|
+
------
|
|
376
|
+
Exception
|
|
377
|
+
If the current vector has a different size or vector type than the input vector.
|
|
378
|
+
|
|
379
|
+
Examples
|
|
380
|
+
--------
|
|
381
|
+
>>> from hdlib.vector import Vector
|
|
382
|
+
>>> vector1 = Vector(seed=1)
|
|
383
|
+
>>> vector2 = Vector(seed=2)
|
|
384
|
+
>>> vector1.dist(vector2, method='cosine')
|
|
385
|
+
0.996
|
|
386
|
+
|
|
387
|
+
Generate two random bipolar vectors and compute the distance between them.
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
if self.size != vector.size:
|
|
391
|
+
raise Exception("Vectors must have the same size")
|
|
392
|
+
|
|
393
|
+
if self.vtype != vector.vtype:
|
|
394
|
+
raise Exception("Vectors must be of the same type")
|
|
395
|
+
|
|
396
|
+
if method.lower() == "cosine":
|
|
397
|
+
return 1 - np.dot(self.vector, vector.vector) / (np.linalg.norm(self.vector) * np.linalg.norm(vector.vector))
|
|
398
|
+
|
|
399
|
+
elif method.lower() == "hamming":
|
|
400
|
+
return np.count_nonzero(self.vector != vector.vector)
|
|
401
|
+
|
|
402
|
+
elif method.lower() == "euclidean":
|
|
403
|
+
return np.linalg.norm(self.vector - vector.vector)
|
|
404
|
+
|
|
405
|
+
else:
|
|
406
|
+
raise ValueError("Distance method \"{}\" is not supported".format(method))
|
|
407
|
+
|
|
408
|
+
def normalize(self) -> None:
|
|
409
|
+
"""Normalize a vector after a binding or bundling with another vector.
|
|
410
|
+
|
|
411
|
+
Raises
|
|
412
|
+
------
|
|
413
|
+
ValueError
|
|
414
|
+
If the vector type is not supported (i.e., is different from binary and bipolar).
|
|
415
|
+
|
|
416
|
+
Examples
|
|
417
|
+
--------
|
|
418
|
+
>>> from hdlib.vector import Vector
|
|
419
|
+
>>> from hdlib.arithmetic import bind
|
|
420
|
+
>>> vector1 = Vector()
|
|
421
|
+
>>> vector2 = Vector()
|
|
422
|
+
>>> vector3 = bind(vector1, vector2)
|
|
423
|
+
>>> vector3.normalize()
|
|
424
|
+
>>> ((vector3.vector == -1) | (vector3.vector == 1)).all()
|
|
425
|
+
True
|
|
426
|
+
|
|
427
|
+
Binding or bundling two vectors can produce a new vector whose vtype is different from the
|
|
428
|
+
one of the two input vector. This function normalizes the vector content in accordance to
|
|
429
|
+
its vector type.
|
|
430
|
+
"""
|
|
431
|
+
|
|
432
|
+
if self.vtype == "bipolar":
|
|
433
|
+
# np.sign returns -1, 0, or 1
|
|
434
|
+
self.vector = np.sign(self.vector)
|
|
435
|
+
|
|
436
|
+
# Force 0 -> 1
|
|
437
|
+
self.vector[self.vector == 0] = 1
|
|
438
|
+
|
|
439
|
+
elif self.vtype == "binary":
|
|
440
|
+
# Find the scale (max value)
|
|
441
|
+
max_val = np.max(self.vector)
|
|
442
|
+
|
|
443
|
+
if max_val > 0:
|
|
444
|
+
# Normalize (element / max) and threshold at 0.5
|
|
445
|
+
# Equivalent to: element > max_val * 0.5
|
|
446
|
+
self.vector = np.where((self.vector / max_val) > 0.5, 1, 0)
|
|
447
|
+
|
|
448
|
+
else:
|
|
449
|
+
# If max is 0 (empty, null vector), ensure it stays 0
|
|
450
|
+
self.vector[:] = 0
|
|
451
|
+
|
|
452
|
+
else:
|
|
453
|
+
raise ValueError(f"Vector type '{self.vtype}' is not supported")
|
|
454
|
+
|
|
455
|
+
# Ensure the array remains integers
|
|
456
|
+
self.vector = self.vector.astype(int)
|
|
457
|
+
|
|
458
|
+
def bind(self, vector: "Vector") -> None:
|
|
459
|
+
"""Bind the current vector with another vector object inplace.
|
|
460
|
+
|
|
461
|
+
Parameters
|
|
462
|
+
----------
|
|
463
|
+
vector : Vector
|
|
464
|
+
The input Vector object.
|
|
465
|
+
|
|
466
|
+
Examples
|
|
467
|
+
--------
|
|
468
|
+
>>> from hdlib.vector import Vector
|
|
469
|
+
>>> vector1 = Vector()
|
|
470
|
+
>>> vector2 = Vector()
|
|
471
|
+
>>> vector1.bind(vector2)
|
|
472
|
+
|
|
473
|
+
It overrides the actual vector content of `vector1` with the result of the binding with `vector2`.
|
|
474
|
+
Refers to hdlib.arithmetic.bind for additional information.
|
|
475
|
+
"""
|
|
476
|
+
|
|
477
|
+
# Import arithmetic.bind here to avoid circular imports
|
|
478
|
+
from hdlib.arithmetic import bind as bind_operator
|
|
479
|
+
|
|
480
|
+
self.__override_object(bind_operator(self, vector))
|
|
481
|
+
|
|
482
|
+
def bundle(self, vector: "Vector") -> None:
|
|
483
|
+
"""Bundle the current vector with another vector object inplace.
|
|
484
|
+
|
|
485
|
+
Parameters
|
|
486
|
+
----------
|
|
487
|
+
vector : Vector
|
|
488
|
+
The input Vector object.
|
|
489
|
+
|
|
490
|
+
Examples
|
|
491
|
+
--------
|
|
492
|
+
>>> from hdlib.vector import Vector
|
|
493
|
+
>>> vector1 = Vector()
|
|
494
|
+
>>> vector2 = Vector()
|
|
495
|
+
>>> vector1.bundle(vector2)
|
|
496
|
+
|
|
497
|
+
It overrides the actual vector content of `vector1` with the result of the bundling with `vector2`.
|
|
498
|
+
Refers to hdlib.arithmetic.bundle for additional information.
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
# Import arithmetic.bundle here to avoid circular imports
|
|
502
|
+
from hdlib.arithmetic import bundle as bundle_operator
|
|
503
|
+
|
|
504
|
+
self.__override_object(bundle_operator(self, vector))
|
|
505
|
+
|
|
506
|
+
def subtraction(self, vector: "Vector") -> None:
|
|
507
|
+
"""Subtract a vector from the current vector object inplace.
|
|
508
|
+
|
|
509
|
+
Parameters
|
|
510
|
+
----------
|
|
511
|
+
vector : Vector
|
|
512
|
+
The input Vector object.
|
|
513
|
+
|
|
514
|
+
Examples
|
|
515
|
+
--------
|
|
516
|
+
>>> from hdlib.vector import Vector
|
|
517
|
+
>>> vector1 = Vector()
|
|
518
|
+
>>> vector2 = Vector()
|
|
519
|
+
>>> vector1.subtract(vector2)
|
|
520
|
+
|
|
521
|
+
It overrides the actual vector content of `vector1` with the result of the subtraction with `vector2`.
|
|
522
|
+
Refers to hdlib.arithmetic.subtraction for additional information.
|
|
523
|
+
"""
|
|
524
|
+
|
|
525
|
+
# Import arithmetic.subtraction here to avoid circular imports
|
|
526
|
+
from hdlib.arithmetic import subtraction as subtraction_operator
|
|
527
|
+
|
|
528
|
+
self.__override_object(subtraction_operator(self, vector))
|
|
529
|
+
|
|
530
|
+
def permute(self, rotate_by: int=1) -> None:
|
|
531
|
+
"""Permute the current vector inplace.
|
|
532
|
+
|
|
533
|
+
Parameters
|
|
534
|
+
----------
|
|
535
|
+
rotate_by : int
|
|
536
|
+
Rotate the input vector by `rotate_by` positions (the default is 1).
|
|
537
|
+
|
|
538
|
+
Examples
|
|
539
|
+
--------
|
|
540
|
+
>>> from hdlib.vector import Vector
|
|
541
|
+
>>> vector = Vector()
|
|
542
|
+
>>> vector.permute(rotate_by=2)
|
|
543
|
+
|
|
544
|
+
It overrides the actual vector content of `vector` with the result of applying the permute function inplace.
|
|
545
|
+
Refers to hdlib.arithmetic.permute for additional information.
|
|
546
|
+
"""
|
|
547
|
+
|
|
548
|
+
# Import arithmetic.permute here to avoid circular imports
|
|
549
|
+
from hdlib.arithmetic import permute as permute_operator
|
|
550
|
+
|
|
551
|
+
self.__override_object(permute_operator(self, rotate_by=rotate_by))
|
|
552
|
+
|
|
553
|
+
def __override_object(self, vector: "Vector") -> None:
|
|
554
|
+
"""Override the Vector object with another Vector object. This is a private method.
|
|
555
|
+
|
|
556
|
+
Parameters
|
|
557
|
+
----------
|
|
558
|
+
vector : Vector
|
|
559
|
+
The input vector from which properties are inherited to the current vector.
|
|
560
|
+
"""
|
|
561
|
+
|
|
562
|
+
self.name = vector.name
|
|
563
|
+
self.size = vector.size
|
|
564
|
+
self.seed = vector.seed
|
|
565
|
+
self.tags = vector.tags
|
|
566
|
+
|
|
567
|
+
self.parents = vector.parents
|
|
568
|
+
self.children = vector.children
|
|
569
|
+
|
|
570
|
+
self.vtype = vector.vtype
|
|
571
|
+
self.vector = vector.vector
|
|
572
|
+
|
|
573
|
+
self.version = vector.version
|
|
574
|
+
|
|
575
|
+
def dump(self, to_file: Optional[os.path.abspath]=None) -> None:
|
|
576
|
+
"""Dump the Vector object to a pickle file.
|
|
577
|
+
|
|
578
|
+
Parameters
|
|
579
|
+
----------
|
|
580
|
+
to_file
|
|
581
|
+
Path to the file used to dump the Vector object to.
|
|
582
|
+
|
|
583
|
+
Raises
|
|
584
|
+
------
|
|
585
|
+
Exception
|
|
586
|
+
If the `to_file` file already exists.
|
|
587
|
+
|
|
588
|
+
Examples
|
|
589
|
+
--------
|
|
590
|
+
>>> import os
|
|
591
|
+
>>> from hdlib.vector import Vector
|
|
592
|
+
>>> vector = Vector()
|
|
593
|
+
>>> vector.dump(to_file='~/my_vector.pkl')
|
|
594
|
+
>>> os.path.isfile('~/my_vector.pkl')
|
|
595
|
+
True
|
|
596
|
+
|
|
597
|
+
Create a Vector object and dump it to a pickle file under the home directory.
|
|
598
|
+
"""
|
|
599
|
+
|
|
600
|
+
if not to_file:
|
|
601
|
+
# Dump the vector to a pickle file in the current working directory if not file path is provided
|
|
602
|
+
to_file = os.path.join(os.getcwd(), "{}.pkl".format(self.name))
|
|
603
|
+
|
|
604
|
+
if os.path.isfile(to_file):
|
|
605
|
+
raise Exception("The output file already exists!\n{}".format(to_file))
|
|
606
|
+
|
|
607
|
+
with open(to_file, "wb") as pkl:
|
|
608
|
+
pickle.dump(self, pkl)
|