/
arrays.py
141 lines (106 loc) · 3.65 KB
/
arrays.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from __future__ import absolute_import, division, print_function
from collections import Iterable
from datashape import DataShape
from odo.utils import copydoc
from .expressions import Expr, ndim, symbol
__all__ = 'Transpose', 'TensorDot', 'dot', 'transpose', 'tensordot'
class Transpose(Expr):
""" Transpose dimensions in an N-Dimensional array
Examples
--------
>>> x = symbol('x', '10 * 20 * int32')
>>> x.T
transpose(x)
>>> x.T.shape
(20, 10)
Specify axis ordering with axes keyword argument
>>> x = symbol('x', '10 * 20 * 30 * int32')
>>> x.transpose([2, 0, 1])
transpose(x, axes=[2, 0, 1])
>>> x.transpose([2, 0, 1]).shape
(30, 10, 20)
"""
_arguments = '_child', 'axes'
def _dshape(self):
s = self._child.shape
return DataShape(*(tuple([s[i] for i in self.axes]) +
(self._child.dshape.measure,)))
def __str__(self):
if self.axes == tuple(range(ndim(self)))[::-1]:
return 'transpose(%s)' % self._child
else:
return 'transpose(%s, axes=%s)' % (self._child, list(self.axes))
@copydoc(Transpose)
def transpose(expr, axes=None):
if axes is None:
axes = tuple(range(ndim(expr)))[::-1]
if isinstance(axes, list):
axes = tuple(axes)
return Transpose(expr, axes)
@copydoc(Transpose)
def T(expr):
return transpose(expr)
class TensorDot(Expr):
""" Dot Product: Contract and sum dimensions of two arrays
>>> x = symbol('x', '20 * 20 * int32')
>>> y = symbol('y', '20 * 30 * int32')
>>> x.dot(y)
tensordot(x, y)
>>> tensordot(x, y, axes=[0, 0])
tensordot(x, y, axes=[0, 0])
"""
_arguments = 'lhs', 'rhs', '_left_axes', '_right_axes'
_input_attributes = 'lhs', 'rhs'
def _dshape(self):
# Compute shape
shape = tuple([d for i, d in enumerate(self.lhs.shape)
if i not in self._left_axes] +
[d for i, d in enumerate(self.rhs.shape)
if i not in self._right_axes])
# Compute measure by mimicking a mul and add
l = symbol('l', self.lhs.dshape.measure)
r = symbol('r', self.rhs.dshape.measure)
measure = ((l * r) + (l * r)).dshape.measure
return DataShape(*(shape + (measure,)))
def __str__(self):
if self.isidentical(tensordot(self.lhs, self.rhs)):
return 'tensordot(%s, %s)' % (self.lhs, self.rhs)
else:
la = self._left_axes
if len(la) == 1:
la = la[0]
ra = self._right_axes
if len(ra) == 1:
ra = ra[0]
return 'tensordot(%s, %s, axes=[%s, %s])' % (
self.lhs, self.rhs, str(la), str(ra)
)
@copydoc(TensorDot)
def tensordot(lhs, rhs, axes=None):
if axes is None:
left = ndim(lhs) - 1
right = 0
elif isinstance(axes, Iterable):
left, right = axes
else:
left, right = axes, axes
if isinstance(left, int):
left = (left,)
if isinstance(right, int):
right = (right,)
if isinstance(left, list):
left = tuple(left)
if isinstance(right, list):
right = tuple(right)
return TensorDot(lhs, rhs, left, right)
@copydoc(TensorDot)
def dot(lhs, rhs):
return tensordot(lhs, rhs)
from datashape.predicates import isnumeric, isboolean
from .expressions import dshape_method_list, method_properties
dshape_method_list.extend([
(lambda ds: ndim(ds) > 1, set([transpose])),
(lambda ds: ndim(ds) == 2, set([T])),
(lambda ds: ndim(ds) >= 1 and (isnumeric(ds) or isboolean(ds)), set([dot]))
])
method_properties.add(T)