提交 a384448e authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #3160 from harlouci/props_tensor

Props tensor
...@@ -22,7 +22,6 @@ from theano.tensor.type_other import NoneConst ...@@ -22,7 +22,6 @@ from theano.tensor.type_other import NoneConst
from theano import scalar as scal from theano import scalar as scal
from functools import partial from functools import partial
from six import integer_types from six import integer_types
from theano.gof.utils import hashtype
from theano import compile, printing from theano import compile, printing
from theano.printing import pprint, min_informative_str from theano.printing import pprint, min_informative_str
# For history # For history
...@@ -1002,6 +1001,9 @@ _scal_elemwise = _scal_elemwise_with_nfunc(None, None, None) ...@@ -1002,6 +1001,9 @@ _scal_elemwise = _scal_elemwise_with_nfunc(None, None, None)
######################### #########################
class TensorFromScalar(Op): class TensorFromScalar(Op):
__props__ = ()
def make_node(self, s): def make_node(self, s):
assert isinstance(s.type, scal.Scalar) assert isinstance(s.type, scal.Scalar)
return Apply(self, return Apply(self,
...@@ -1033,18 +1035,12 @@ class TensorFromScalar(Op): ...@@ -1033,18 +1035,12 @@ class TensorFromScalar(Op):
raise NotImplementedError("grad not implemented for complex dtypes") raise NotImplementedError("grad not implemented for complex dtypes")
def __str__(self):
return self.__class__.__name__
tensor_from_scalar = TensorFromScalar() tensor_from_scalar = TensorFromScalar()
class ScalarFromTensor(Op): class ScalarFromTensor(Op):
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self): __props__ = ()
return hash(type(self))
def make_node(self, t): def make_node(self, t):
assert isinstance(t.type, TensorType) assert isinstance(t.type, TensorType)
...@@ -1072,9 +1068,6 @@ class ScalarFromTensor(Op): ...@@ -1072,9 +1068,6 @@ class ScalarFromTensor(Op):
return [None] return [None]
return self.make_node(*eval_points).outputs return self.make_node(*eval_points).outputs
def __str__(self):
return self.__class__.__name__
def c_code(self, node, name, inputs, outputs, sub): def c_code(self, node, name, inputs, outputs, sub):
x, = inputs x, = inputs
z, = outputs z, = outputs
...@@ -1197,12 +1190,7 @@ class MaxAndArgmax(Op): ...@@ -1197,12 +1190,7 @@ class MaxAndArgmax(Op):
nin = 2 # tensor, axis nin = 2 # tensor, axis
nout = 2 # max val, max idx nout = 2 # max val, max idx
E_axis = 'invalid axis' E_axis = 'invalid axis'
__props__ = ()
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def make_node(self, x, axis=None): def make_node(self, x, axis=None):
x = _as_tensor_variable(x) x = _as_tensor_variable(x)
...@@ -1424,10 +1412,6 @@ class MaxAndArgmax(Op): ...@@ -1424,10 +1412,6 @@ class MaxAndArgmax(Op):
g_x = eq(xmax_pad, x) * g_max_pad g_x = eq(xmax_pad, x) * g_max_pad
return g_x, axis_grad return g_x, axis_grad
def __str__(self):
return self.__class__.__name__
_max_and_argmax = MaxAndArgmax() _max_and_argmax = MaxAndArgmax()
...@@ -2330,6 +2314,9 @@ def nonzero_values(a): ...@@ -2330,6 +2314,9 @@ def nonzero_values(a):
class Tri(gof.Op): class Tri(gof.Op):
__props__ = ("dtype",)
def __init__(self, dtype=None): def __init__(self, dtype=None):
if dtype is None: if dtype is None:
dtype = config.floatX dtype = config.floatX
...@@ -2356,12 +2343,6 @@ class Tri(gof.Op): ...@@ -2356,12 +2343,6 @@ class Tri(gof.Op):
def grad(self, inp, grads): def grad(self, inp, grads):
return [grad_undefined(self, i, inp[i]) for i in xrange(3)] return [grad_undefined(self, i, inp[i]) for i in xrange(3)]
def __eq__(self, other):
return type(self) == type(other) and self.dtype == other.dtype
def __hash__(self):
return hash(self.dtype) ^ hash(type(self))
def tri(N, M=None, k=0, dtype=None): def tri(N, M=None, k=0, dtype=None):
""" """
...@@ -2438,6 +2419,9 @@ def triu(m, k=0): ...@@ -2438,6 +2419,9 @@ def triu(m, k=0):
class Eye(gof.Op): class Eye(gof.Op):
__props__ = ("dtype", )
def __init__(self, dtype=None): def __init__(self, dtype=None):
if dtype is None: if dtype is None:
dtype = config.floatX dtype = config.floatX
...@@ -2467,12 +2451,6 @@ class Eye(gof.Op): ...@@ -2467,12 +2451,6 @@ class Eye(gof.Op):
def grad(self, inp, grads): def grad(self, inp, grads):
return [grad_undefined(self, i, inp[i]) for i in xrange(3)] return [grad_undefined(self, i, inp[i]) for i in xrange(3)]
def __eq__(self, other):
return type(self) == type(other) and self.dtype == other.dtype
def __hash__(self):
return hash(self.dtype) ^ hash(type(self))
def eye(n, m=None, k=0, dtype=None): def eye(n, m=None, k=0, dtype=None):
"""Return a 2-D array with ones on the diagonal and zeros elsewhere. """Return a 2-D array with ones on the diagonal and zeros elsewhere.
...@@ -2990,6 +2968,7 @@ class Default(gof.Op): ...@@ -2990,6 +2968,7 @@ class Default(gof.Op):
have exactly the same type. have exactly the same type.
""" """
view_map = {0: [0]} view_map = {0: [0]}
__props__ = ()
def make_node(self, x, default): def make_node(self, x, default):
x, default = as_tensor_variable(x), as_tensor_variable(default) x, default = as_tensor_variable(x), as_tensor_variable(default)
...@@ -3283,20 +3262,14 @@ class Split(Op): ...@@ -3283,20 +3262,14 @@ class Split(Op):
"""A Split instance will have this many outputs, and require that """A Split instance will have this many outputs, and require that
the splits argument to `perform` have exactly this many elements. the splits argument to `perform` have exactly this many elements.
""" """
__props__ = ("len_splits",)
def __init__(self, len_splits): def __init__(self, len_splits):
self.len_splits = int(len_splits) self.len_splits = int(len_splits)
def __eq__(self, other):
return (type(self) == type(other) and
self.len_splits == other.len_splits)
def __str__(self): def __str__(self):
return self.__class__.__name__ + "{%s}" % self.len_splits return self.__class__.__name__ + "{%s}" % self.len_splits
def __hash__(self):
return hash(Split) ^ self.len_splits
def make_node(self, x, axis, splits): def make_node(self, x, axis, splits):
"""WRITEME""" """WRITEME"""
x = as_tensor_variable(x) x = as_tensor_variable(x)
...@@ -3510,15 +3483,7 @@ class Join(Op): ...@@ -3510,15 +3483,7 @@ class Join(Op):
join(0, x, u) # WRONG: joined tensors must have the same rank join(0, x, u) # WRONG: joined tensors must have the same rank
""" """
check_input = False check_input = False
__props__ = ()
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def __str__(self):
return '%s' % (self.__class__.__name__)
def make_node(self, *axis_and_tensors): def make_node(self, *axis_and_tensors):
""" """
...@@ -3979,19 +3944,13 @@ class Reshape(Op): ...@@ -3979,19 +3944,13 @@ class Reshape(Op):
_f16_ok = True _f16_ok = True
check_input = False check_input = False
__props__ = ("ndim",)
# name does not participate because it doesn't affect computations
def __init__(self, ndim, name=None): def __init__(self, ndim, name=None):
self.ndim = ndim self.ndim = ndim
self.name = name self.name = name
def __eq__(self, other):
# .name does not participate because it doesn't affect computations
return (type(other) is type(self)) and (other.ndim == self.ndim)
def __hash__(self):
# .name does not participate because it doesn't affect computations
return hash(type(self)) ^ hash(self.ndim)
def __str__(self): def __str__(self):
return '%s{%s}' % (self.__class__.__name__, self.ndim) return '%s{%s}' % (self.__class__.__name__, self.ndim)
...@@ -4180,16 +4139,11 @@ class Flatten(Op): ...@@ -4180,16 +4139,11 @@ class Flatten(Op):
view_map = {0: [0]} view_map = {0: [0]}
check_input = False check_input = False
__props__ = ("outdim",)
def __init__(self, outdim=1): def __init__(self, outdim=1):
self.outdim = int(outdim) self.outdim = int(outdim)
def __eq__(self, other):
return type(self) == type(other) and self.outdim == other.outdim
def __hash__(self):
return hashtype(self) ^ hash(self.outdim)
def __str__(self): def __str__(self):
return '%s{%s}' % (self.__class__.__name__, self.outdim) return '%s{%s}' % (self.__class__.__name__, self.outdim)
...@@ -4364,15 +4318,11 @@ class Tile(Op): ...@@ -4364,15 +4318,11 @@ class Tile(Op):
:see: `numpy.tile :see: `numpy.tile
<http://docs.scipy.org/doc/numpy/reference/generated/numpy.tile.html>`_ <http://docs.scipy.org/doc/numpy/reference/generated/numpy.tile.html>`_
""" """
__props__ = ("ndim",)
def __init__(self, ndim): def __init__(self, ndim):
self.ndim = ndim self.ndim = ndim
def __eq__(self, other):
return (type(other) is Tile) and (other.ndim == self.ndim)
def __hash__(self):
return hash(Tile) ^ hash(self.ndim)
def __str__(self): def __str__(self):
return self.__class__.__name__ + "{ndim=%d}" % self.ndim return self.__class__.__name__ + "{ndim=%d}" % self.ndim
...@@ -4473,19 +4423,11 @@ class ARange(Op): ...@@ -4473,19 +4423,11 @@ class ARange(Op):
Parameters and behaviour are the same as numpy.arange(). Parameters and behaviour are the same as numpy.arange().
""" """
__props__ = ("dtype",)
def __init__(self, dtype): def __init__(self, dtype):
self.dtype = dtype self.dtype = dtype
def __eq__(self, other):
return type(self) == type(other) and self.dtype == other.dtype
def __hash__(self):
return hash(self.dtype)
def __str__(self):
return self.__class__.__name__
def make_node(self, start, stop, step): def make_node(self, start, stop, step):
start, stop, step = map(as_tensor_variable, (start, stop, step)) start, stop, step = map(as_tensor_variable, (start, stop, step))
assert start.ndim == 0 assert start.ndim == 0
...@@ -4641,6 +4583,7 @@ class _nd_grid(object): ...@@ -4641,6 +4583,7 @@ class _nd_grid(object):
>>> b[1].eval() >>> b[1].eval()
array([[0, 1, 2, 3]], dtype=int8) array([[0, 1, 2, 3]], dtype=int8)
""" """
def __init__(self, sparse=False): def __init__(self, sparse=False):
self.sparse = sparse self.sparse = sparse
...@@ -4701,6 +4644,7 @@ class PermuteRowElements(Op): ...@@ -4701,6 +4644,7 @@ class PermuteRowElements(Op):
If the "inverse" argument is True, the Op will perform the inverse If the "inverse" argument is True, the Op will perform the inverse
permutation instead. permutation instead.
""" """
__props__ = ()
def make_node(self, x, y, inverse): def make_node(self, x, y, inverse):
x = as_tensor_variable(x) x = as_tensor_variable(x)
...@@ -4908,12 +4852,7 @@ class Dot(Op): ...@@ -4908,12 +4852,7 @@ class Dot(Op):
tensor.blas) tensor.blas)
""" """
__props__ = ()
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
# the rationale for Dot22 is related to getting GEMM Ops into the # the rationale for Dot22 is related to getting GEMM Ops into the
# graph. See Dot22 in tensor.blas for details. # graph. See Dot22 in tensor.blas for details.
...@@ -5377,6 +5316,7 @@ class Diagonal(Op): ...@@ -5377,6 +5316,7 @@ class Diagonal(Op):
:return: A vector representing the diagonal elements. :return: A vector representing the diagonal elements.
""" """
__props__ = ("offset", "axis1", "axis2")
def __init__(self, offset=0, axis1=0, axis2=1): def __init__(self, offset=0, axis1=0, axis2=1):
if numpy_diagonal_return_view: if numpy_diagonal_return_view:
...@@ -5385,16 +5325,6 @@ class Diagonal(Op): ...@@ -5385,16 +5325,6 @@ class Diagonal(Op):
self.axis1 = axis1 self.axis1 = axis1
self.axis2 = axis2 self.axis2 = axis2
def __eq__(self, other):
return (type(self) == type(other) and
self.offset == other.offset and
self.axis1 == other.axis1 and
self.axis2 == other.axis2)
def __hash__(self):
return (hash(type(self)) ^ hash(self.offset) ^
hash(self.axis1) ^ hash(self.axis2))
def make_node(self, x): def make_node(self, x):
x = as_tensor_variable(x) x = as_tensor_variable(x)
assert x.ndim >= 2 assert x.ndim >= 2
...@@ -5428,9 +5358,6 @@ class Diagonal(Op): ...@@ -5428,9 +5358,6 @@ class Diagonal(Op):
out_shape.append(diag_size) out_shape.append(diag_size)
return [tuple(out_shape)] return [tuple(out_shape)]
def __str__(self):
return self.__class__.__name__
def diagonal(a, offset=0, axis1=0, axis2=1): def diagonal(a, offset=0, axis1=0, axis2=1):
if (offset, axis1, axis2) == (0, 0, 1): if (offset, axis1, axis2) == (0, 0, 1):
...@@ -5440,11 +5367,7 @@ def diagonal(a, offset=0, axis1=0, axis2=1): ...@@ -5440,11 +5367,7 @@ def diagonal(a, offset=0, axis1=0, axis2=1):
class Diag(Op): class Diag(Op):
def __eq__(self, other): __props__ = ()
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def make_node(self, diag): def make_node(self, diag):
diag = as_tensor_variable(diag) diag = as_tensor_variable(diag)
...@@ -5464,9 +5387,6 @@ class Diag(Op): ...@@ -5464,9 +5387,6 @@ class Diag(Op):
def infer_shape(self, nodes, shapes): def infer_shape(self, nodes, shapes):
return [(shapes[0][0],) * 2] return [(shapes[0][0],) * 2]
def __str__(self):
return self.__class__.__name__
def diag(v, k=0): def diag(v, k=0):
if v.ndim == 1: if v.ndim == 1:
......
...@@ -360,23 +360,19 @@ class Gemv(Op): ...@@ -360,23 +360,19 @@ class Gemv(Op):
alpha, beta are scalars alpha, beta are scalars
output is a vector that can be inplace on y output is a vector that can be inplace on y
""" """
__props__ = ("inplace",)
def __init__(self, inplace): def __init__(self, inplace):
self.inplace = inplace self.inplace = inplace
if inplace: if inplace:
self.destroy_map = {0: [0]} self.destroy_map = {0: [0]}
def __eq__(self, other):
return type(self) == type(other) and self.inplace == other.inplace
def __str__(self): def __str__(self):
if self.inplace: if self.inplace:
return '%s{inplace}' % self.__class__.__name__ return '%s{inplace}' % self.__class__.__name__
else: else:
return '%s{no_inplace}' % self.__class__.__name__ return '%s{no_inplace}' % self.__class__.__name__
def __hash__(self):
return hash(type(self)) ^ hash(self.inplace)
def make_node(self, y, alpha, A, x, beta): def make_node(self, y, alpha, A, x, beta):
y = T.as_tensor_variable(y) y = T.as_tensor_variable(y)
x = T.as_tensor_variable(x) x = T.as_tensor_variable(x)
...@@ -453,18 +449,13 @@ class Ger(Op): ...@@ -453,18 +449,13 @@ class Ger(Op):
:TODO: Create better classes ScipyGer and CGer that inherit from this class :TODO: Create better classes ScipyGer and CGer that inherit from this class
and override the make_thunk() method to use Scipy and C respectively. and override the make_thunk() method to use Scipy and C respectively.
""" """
__props__ = ("destructive",)
def __init__(self, destructive): def __init__(self, destructive):
self.destructive = destructive self.destructive = destructive
if destructive: if destructive:
self.destroy_map = {0: [0]} self.destroy_map = {0: [0]}
def __eq__(self, other):
return (type(self) == type(other) and
self.destructive == other.destructive)
def __hash__(self):
return hash(type(self)) ^ hash(self.destructive)
def __str__(self): def __str__(self):
if self.destructive: if self.destructive:
return '%s{destructive}' % self.__class__.__name__ return '%s{destructive}' % self.__class__.__name__
...@@ -611,14 +602,7 @@ class GemmRelated(Op): ...@@ -611,14 +602,7 @@ class GemmRelated(Op):
This class provides a kind of templated gemm Op. This class provides a kind of templated gemm Op.
""" """
def __eq__(self, other): __props__ = ()
return (type(self) == type(other))
def __hash__(self):
return hash(type(self))
def __str__(self):
return self.__class__.__name__
def c_support_code(self): def c_support_code(self):
# return cblas_header_text() # return cblas_header_text()
......
...@@ -98,7 +98,6 @@ class DimShuffle(Op): ...@@ -98,7 +98,6 @@ class DimShuffle(Op):
Adding, subtracting dimensions can be done with reshape. Adding, subtracting dimensions can be done with reshape.
""" """
_f16_ok = True _f16_ok = True
check_input = False check_input = False
def __init__(self, input_broadcastable, new_order, inplace=False): def __init__(self, input_broadcastable, new_order, inplace=False):
......
...@@ -65,6 +65,7 @@ cpu_contiguous = CpuContiguous() ...@@ -65,6 +65,7 @@ cpu_contiguous = CpuContiguous()
class CumsumOp(theano.Op): class CumsumOp(theano.Op):
# See function cumsum for docstring # See function cumsum for docstring
__props__ = ("axis",) __props__ = ("axis",)
def __init__(self, axis=None): def __init__(self, axis=None):
...@@ -182,6 +183,7 @@ def cumsum(x, axis=None): ...@@ -182,6 +183,7 @@ def cumsum(x, axis=None):
class CumprodOp(theano.Op): class CumprodOp(theano.Op):
# See function cumprod for docstring # See function cumprod for docstring
__props__ = ("axis",) __props__ = ("axis",)
def __init__(self, axis=None): def __init__(self, axis=None):
...@@ -344,9 +346,6 @@ class DiffOp(theano.Op): ...@@ -344,9 +346,6 @@ class DiffOp(theano.Op):
out_shape[self.axis] = out_shape[self.axis] - self.n out_shape[self.axis] = out_shape[self.axis] - self.n
return [out_shape] return [out_shape]
def __str__(self):
return self.__class__.__name__
def diff(x, n=1, axis=-1): def diff(x, n=1, axis=-1):
"""Calculate the n-th order discrete difference along given axis. """Calculate the n-th order discrete difference along given axis.
...@@ -462,9 +461,6 @@ class BinCountOp(theano.Op): ...@@ -462,9 +461,6 @@ class BinCountOp(theano.Op):
m = basic.maximum(m, self.minlength) m = basic.maximum(m, self.minlength)
return [[m]] return [[m]]
def __str__(self):
return self.__class__.__name__
def bincount(x, weights=None, minlength=None, assert_nonneg=False): def bincount(x, weights=None, minlength=None, assert_nonneg=False):
"""Count number of occurrences of each value in array of ints. """Count number of occurrences of each value in array of ints.
...@@ -670,9 +666,6 @@ class RepeatOp(theano.Op): ...@@ -670,9 +666,6 @@ class RepeatOp(theano.Op):
out_shape[self.axis] = theano.tensor.sum(repeats, dtype=dtype) out_shape[self.axis] = theano.tensor.sum(repeats, dtype=dtype)
return [out_shape] return [out_shape]
def __str__(self):
return self.__class__.__name__
def repeat(x, repeats, axis=None): def repeat(x, repeats, axis=None):
"""Repeat elements of an array. """Repeat elements of an array.
...@@ -739,9 +732,6 @@ class Bartlett(gof.Op): ...@@ -739,9 +732,6 @@ class Bartlett(gof.Op):
# See function bartlett for docstring # See function bartlett for docstring
__props__ = () __props__ = ()
def __str__(self):
return self.__class__.__name__
def make_node(self, M): def make_node(self, M):
M = tensor.as_tensor_variable(M) M = tensor.as_tensor_variable(M)
if M.ndim != 0: if M.ndim != 0:
...@@ -797,9 +787,6 @@ class FillDiagonal(gof.Op): ...@@ -797,9 +787,6 @@ class FillDiagonal(gof.Op):
# See function fill_diagonal for docstring # See function fill_diagonal for docstring
__props__ = () __props__ = ()
def __str__(self):
return self.__class__.__name__
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
return [in_shapes[0]] return [in_shapes[0]]
...@@ -881,9 +868,6 @@ class FillDiagonalOffset(gof.Op): ...@@ -881,9 +868,6 @@ class FillDiagonalOffset(gof.Op):
# See function fill_diagonal_offset for docstring # See function fill_diagonal_offset for docstring
__props__ = () __props__ = ()
def __str__(self):
return self.__class__.__name__
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
return [in_shapes[0]] return [in_shapes[0]]
......
...@@ -34,15 +34,7 @@ class Fourier(gof.Op): ...@@ -34,15 +34,7 @@ class Fourier(gof.Op):
input points, A[(n-1)/2] contains the largest positive frequency, while input points, A[(n-1)/2] contains the largest positive frequency, while
A[(n+1)/2] contains the largest negative frequency. A[(n+1)/2] contains the largest negative frequency.
""" """
__props__ = ()
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(self.__class__)
def __str__(self):
return self.__class__.__name__
def make_node(self, a, n, axis): def make_node(self, a, n, axis):
a = tensor.as_tensor_variable(a) a = tensor.as_tensor_variable(a)
......
...@@ -18,6 +18,8 @@ class LoadFromDisk(Op): ...@@ -18,6 +18,8 @@ class LoadFromDisk(Op):
@note: Non-differentiable. @note: Non-differentiable.
""" """
__props__ = ("dtype", "broadcastable", "mmap_mode")
def __init__(self, dtype, broadcastable, mmap_mode=None): def __init__(self, dtype, broadcastable, mmap_mode=None):
self.dtype = numpy.dtype(dtype) # turn "float64" into numpy.float64 self.dtype = numpy.dtype(dtype) # turn "float64" into numpy.float64
self.broadcastable = broadcastable self.broadcastable = broadcastable
...@@ -25,13 +27,6 @@ class LoadFromDisk(Op): ...@@ -25,13 +27,6 @@ class LoadFromDisk(Op):
raise ValueError("The only supported values for mmap_mode " raise ValueError("The only supported values for mmap_mode "
"are None and 'c', got %s" % mmap_mode) "are None and 'c', got %s" % mmap_mode)
self.mmap_mode = mmap_mode self.mmap_mode = mmap_mode
self._info = (dtype, broadcastable, mmap_mode)
def __eq__(self, other):
return (type(self) == type(other) and self._info == other._info)
def __hash__(self):
return hash((type(self),) + self._info)
def make_node(self, path): def make_node(self, path):
if isinstance(path, str): if isinstance(path, str):
...@@ -50,7 +45,8 @@ class LoadFromDisk(Op): ...@@ -50,7 +45,8 @@ class LoadFromDisk(Op):
out[0][0] = result out[0][0] = result
def __str__(self): def __str__(self):
return "Load{dtype: %s, broadcastable: %s, mmep: %s}" % self._info return ("Load{dtype: %s, broadcastable: %s, mmep: %s}" %
(self.dtype, self.broadcastable, self.mmap_mode))
def load(path, dtype, broadcastable, mmap_mode=None): def load(path, dtype, broadcastable, mmap_mode=None):
...@@ -103,6 +99,7 @@ class MPIRecv(Op): ...@@ -103,6 +99,7 @@ class MPIRecv(Op):
@note: Non-differentiable. @note: Non-differentiable.
""" """
__props__ = ("source", "tag", "shape", "dtype")
def __init__(self, source, tag, shape, dtype): def __init__(self, source, tag, shape, dtype):
self.source = source self.source = source
...@@ -110,13 +107,6 @@ class MPIRecv(Op): ...@@ -110,13 +107,6 @@ class MPIRecv(Op):
self.shape = shape self.shape = shape
self.dtype = numpy.dtype(dtype) # turn "float64" into numpy.float64 self.dtype = numpy.dtype(dtype) # turn "float64" into numpy.float64
self.broadcastable = (False,) * len(shape) self.broadcastable = (False,) * len(shape)
self._info = (source, tag, shape, dtype)
def __eq__(self, other):
return (type(self) == type(other) and self._info == other._info)
def __hash__(self):
return hash((type(self),) + self._info)
def make_node(self): def make_node(self):
return gof.Apply(self, [], [theano.Variable(Generic()), return gof.Apply(self, [], [theano.Variable(Generic()),
...@@ -132,7 +122,8 @@ class MPIRecv(Op): ...@@ -132,7 +122,8 @@ class MPIRecv(Op):
out[1][0] = data out[1][0] = data
def __str__(self): def __str__(self):
return "MPIRecv{source: %d, tag: %d, shape: %s, dtype: %s}" % self._info return ("MPIRecv{source: %d, tag: %d, shape: %s, dtype: %s}" %
(self.source, self.tag, self.shape, self.dtype))
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
return [None, self.shape] return [None, self.shape]
...@@ -150,16 +141,11 @@ class MPIRecvWait(Op): ...@@ -150,16 +141,11 @@ class MPIRecvWait(Op):
@note: Non-differentiable. @note: Non-differentiable.
""" """
__props__ = ("tag",)
def __init__(self, tag): def __init__(self, tag):
self.tag = tag self.tag = tag
def __eq__(self, other):
return type(self) == type(other) and self.tag == other.tag
def __hash__(self):
return hash((type(self), self.tag))
def make_node(self, request, data): def make_node(self, request, data):
return gof.Apply(self, [request, data], return gof.Apply(self, [request, data],
[tensor(data.dtype, [tensor(data.dtype,
...@@ -174,9 +160,6 @@ class MPIRecvWait(Op): ...@@ -174,9 +160,6 @@ class MPIRecvWait(Op):
out[0][0] = data out[0][0] = data
def __str__(self):
return "MPIRecvWait"
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
return [shapes[1]] return [shapes[1]]
...@@ -193,17 +176,11 @@ class MPISend(Op): ...@@ -193,17 +176,11 @@ class MPISend(Op):
@note: Non-differentiable. @note: Non-differentiable.
""" """
__props__ = ("dest", "tag")
def __init__(self, dest, tag): def __init__(self, dest, tag):
self.dest = dest self.dest = dest
self.tag = tag self.tag = tag
self._info = (dest, tag)
def __eq__(self, other):
return (type(self) == type(other) and self._info == other._info)
def __hash__(self):
return hash((type(self),) + self._info)
def make_node(self, data): def make_node(self, data):
return gof.Apply(self, [data], return gof.Apply(self, [data],
...@@ -220,7 +197,7 @@ class MPISend(Op): ...@@ -220,7 +197,7 @@ class MPISend(Op):
out[1][0] = data out[1][0] = data
def __str__(self): def __str__(self):
return "MPISend{dest: %d, tag: %d}" % self._info return "MPISend{dest: %d, tag: %d}" % (self.dest, self.tag)
class MPISendWait(Op): class MPISendWait(Op):
...@@ -233,15 +210,11 @@ class MPISendWait(Op): ...@@ -233,15 +210,11 @@ class MPISendWait(Op):
@note: Non-differentiable. @note: Non-differentiable.
""" """
__props__ = ("tag",)
def __init__(self, tag): def __init__(self, tag):
self.tag = tag self.tag = tag
def __eq__(self, other):
return type(self) == type(other) and self.tag == other.tag
def __hash__(self):
return hash((type(self), self.tag))
def make_node(self, request, data): def make_node(self, request, data):
return gof.Apply(self, [request, data], return gof.Apply(self, [request, data],
[theano.Variable(Generic())]) [theano.Variable(Generic())])
...@@ -251,9 +224,6 @@ class MPISendWait(Op): ...@@ -251,9 +224,6 @@ class MPISendWait(Op):
request.wait() request.wait()
out[0][0] = True out[0][0] = True
def __str__(self):
return "MPISendWait"
def isend(var, dest, tag): def isend(var, dest, tag):
""" """
......
...@@ -136,11 +136,8 @@ class AllocDiag(Op): ...@@ -136,11 +136,8 @@ class AllocDiag(Op):
""" """
Allocates a square matrix with the given vector as its diagonal. Allocates a square matrix with the given vector as its diagonal.
""" """
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self): __props__ = ()
return hash(type(self))
def make_node(self, _x): def make_node(self, _x):
x = as_tensor_variable(_x) x = as_tensor_variable(_x)
...@@ -170,17 +167,13 @@ class ExtractDiag(Op): ...@@ -170,17 +167,13 @@ class ExtractDiag(Op):
:note: work on the GPU. :note: work on the GPU.
""" """
__props__ = ("view",)
def __init__(self, view=False): def __init__(self, view=False):
self.view = view self.view = view
if self.view: if self.view:
self.view_map = {0: [0]} self.view_map = {0: [0]}
def __eq__(self, other):
return type(self) == type(other) and self.view == other.view
def __hash__(self):
return hash(type(self)) ^ hash(self.view)
def make_node(self, _x): def make_node(self, _x):
if not isinstance(_x, theano.Variable): if not isinstance(_x, theano.Variable):
x = as_tensor_variable(_x) x = as_tensor_variable(_x)
...@@ -262,6 +255,9 @@ class Det(Op): ...@@ -262,6 +255,9 @@ class Det(Op):
"""Matrix determinant """Matrix determinant
Input should be a square matrix Input should be a square matrix
""" """
__props__ = ()
def make_node(self, x): def make_node(self, x):
x = as_tensor_variable(x) x = as_tensor_variable(x)
assert x.ndim == 2 assert x.ndim == 2
...@@ -640,14 +636,8 @@ def svd(a, full_matrices=1, compute_uv=1): ...@@ -640,14 +636,8 @@ def svd(a, full_matrices=1, compute_uv=1):
class lstsq(Op): class lstsq(Op):
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def __str__(self): __props__ = ()
return self.__class__.__name__
def make_node(self, x, y, rcond): def make_node(self, x, y, rcond):
x = theano.tensor.as_tensor_variable(x) x = theano.tensor.as_tensor_variable(x)
......
...@@ -651,14 +651,11 @@ class MakeVector(T.Op): ...@@ -651,14 +651,11 @@ class MakeVector(T.Op):
into the graph. Should work with 0 inputs. The constant_folding into the graph. Should work with 0 inputs. The constant_folding
optimization will remove it. optimization will remove it.
""" """
def __init__(self, dtype='int64'):
self.dtype = dtype
def __eq__(self, other): __props__ = ("dtype",)
return type(self) == type(other) and self.dtype == other.dtype
def __hash__(self): def __init__(self, dtype='int64'):
return hash(type(self)) ^ hash(self.dtype) self.dtype = dtype
def make_node(self, *inputs): def make_node(self, *inputs):
inputs = list(map(T.as_tensor_variable, inputs)) inputs = list(map(T.as_tensor_variable, inputs))
...@@ -688,9 +685,6 @@ class MakeVector(T.Op): ...@@ -688,9 +685,6 @@ class MakeVector(T.Op):
otype = T.TensorType(broadcastable=(bcastable,), dtype=dtype) otype = T.TensorType(broadcastable=(bcastable,), dtype=dtype)
return T.Apply(self, inputs, [otype()]) return T.Apply(self, inputs, [otype()])
def __str__(self):
return self.__class__.__name__
def perform(self, node, inputs, out_): def perform(self, node, inputs, out_):
out, = out_ out, = out_
# not calling theano._asarray as optimization # not calling theano._asarray as optimization
......
...@@ -102,6 +102,7 @@ class RandomFunction(gof.Op): ...@@ -102,6 +102,7 @@ class RandomFunction(gof.Op):
"""Op that draws random numbers from a numpy.random.RandomState object """Op that draws random numbers from a numpy.random.RandomState object
""" """
__props__ = ("fn", "outtype", "inplace", "ndim_added")
def __init__(self, fn, outtype, inplace=False, ndim_added=0): def __init__(self, fn, outtype, inplace=False, ndim_added=0):
""" """
...@@ -129,17 +130,6 @@ class RandomFunction(gof.Op): ...@@ -129,17 +130,6 @@ class RandomFunction(gof.Op):
""" """
self.__setstate__([fn, outtype, inplace, ndim_added]) self.__setstate__([fn, outtype, inplace, ndim_added])
def __eq__(self, other):
return type(self) == type(other) \
and self.fn == other.fn\
and self.outtype == other.outtype\
and self.inplace == other.inplace\
and self.ndim_added == other.ndim_added
def __hash__(self):
return (hash(type(self)) ^ hash(self.fn) ^ hash(self.outtype) ^
hash(self.inplace) ^ hash(self.ndim_added))
def __getstate__(self): def __getstate__(self):
return self.state return self.state
......
...@@ -339,6 +339,8 @@ class Expm(Op): ...@@ -339,6 +339,8 @@ class Expm(Op):
"""Compute the matrix exponential of a square array """Compute the matrix exponential of a square array
""" """
__props__ = ()
def make_node(self, A): def make_node(self, A):
assert imported_scipy, ( assert imported_scipy, (
"Scipy not available. Scipy is needed for the Expm op") "Scipy not available. Scipy is needed for the Expm op")
...@@ -366,6 +368,8 @@ class ExpmGrad(Op): ...@@ -366,6 +368,8 @@ class ExpmGrad(Op):
"""Gradient of the matrix exponential of a square array. """Gradient of the matrix exponential of a square array.
""" """
__props__ = ()
def make_node(self, A, gw): def make_node(self, A, gw):
assert imported_scipy, ( assert imported_scipy, (
"Scipy not available. Scipy is needed for the Expm op") "Scipy not available. Scipy is needed for the Expm op")
......
...@@ -7,17 +7,13 @@ class SortOp(theano.Op): ...@@ -7,17 +7,13 @@ class SortOp(theano.Op):
""" """
This class is a wrapper for numpy sort function This class is a wrapper for numpy sort function
""" """
__props__ = ("kind", "order")
def __init__(self, kind, order=None): def __init__(self, kind, order=None):
self.kind = kind self.kind = kind
self.order = order self.order = order
def __eq__(self, other):
return (type(self) == type(other) and self.order == other.order and
self.kind == other.kind)
def __hash__(self):
return hash(type(self)) ^ hash(self.order) ^ hash(self.kind)
def __str__(self): def __str__(self):
return self.__class__.__name__ + "{%s, %s}" % (self.kind, return self.__class__.__name__ + "{%s, %s}" % (self.kind,
str(self.order)) str(self.order))
...@@ -132,18 +128,13 @@ class ArgSortOp(theano.Op): ...@@ -132,18 +128,13 @@ class ArgSortOp(theano.Op):
""" """
This class is a wrapper for numpy argsort function This class is a wrapper for numpy argsort function
""" """
__props__ = ("kind", "order")
def __init__(self, kind, order=None): def __init__(self, kind, order=None):
self.kind = kind self.kind = kind
self.order = order self.order = order
def __eq__(self, other):
return (type(self) == type(other) and
self.order == other.order and
self.kind == other.kind)
def __hash__(self):
return hash(type(self)) ^ hash(self.order) ^ hash(self.kind)
def __str__(self): def __str__(self):
return (self.__class__.__name__ + return (self.__class__.__name__ +
"{%s, %s}" % (self.kind, str(self.order))) "{%s, %s}" % (self.kind, str(self.order)))
......
...@@ -292,6 +292,7 @@ class Subtensor(Op): ...@@ -292,6 +292,7 @@ class Subtensor(Op):
check_input = False check_input = False
view_map = {0: [0]} view_map = {0: [0]}
_f16_ok = True _f16_ok = True
__props__ = ("idx_list",)
@staticmethod @staticmethod
def collapse(idxs, cond): def collapse(idxs, cond):
...@@ -567,9 +568,6 @@ class Subtensor(Op): ...@@ -567,9 +568,6 @@ class Subtensor(Op):
return rval return rval
def __eq__(self, other):
return type(self) == type(other) and self.idx_list == other.idx_list
def __hash__(self): def __hash__(self):
# TODO: optimize by cache this hash value # TODO: optimize by cache this hash value
msg = [] msg = []
...@@ -1174,6 +1172,7 @@ class IncSubtensor(Op): ...@@ -1174,6 +1172,7 @@ class IncSubtensor(Op):
""" """
check_input = False check_input = False
__props__ = ("idx_list", "inplace", "set_instead_of_inc")
def __init__(self, idx_list, inplace=False, set_instead_of_inc=False, def __init__(self, idx_list, inplace=False, set_instead_of_inc=False,
destroyhandler_tolerate_aliased=None): destroyhandler_tolerate_aliased=None):
...@@ -1187,12 +1186,6 @@ class IncSubtensor(Op): ...@@ -1187,12 +1186,6 @@ class IncSubtensor(Op):
destroyhandler_tolerate_aliased) destroyhandler_tolerate_aliased)
self.set_instead_of_inc = set_instead_of_inc self.set_instead_of_inc = set_instead_of_inc
def __eq__(self, other):
return (type(self) == type(other) and
self.idx_list == other.idx_list and
self.inplace == other.inplace and
self.set_instead_of_inc == other.set_instead_of_inc)
def __hash__(self): def __hash__(self):
msg = [] msg = []
for entry in self.idx_list: for entry in self.idx_list:
...@@ -2033,15 +2026,7 @@ class AdvancedSubtensor(Op): ...@@ -2033,15 +2026,7 @@ class AdvancedSubtensor(Op):
# Should be used by __getitem__ and __getslice__, as follow: # Should be used by __getitem__ and __getslice__, as follow:
# AdvancedSubtensor()(self, *args), # AdvancedSubtensor()(self, *args),
# if args contains and advanced indexing pattern # if args contains and advanced indexing pattern
__props__ = ()
def __eq__(self, other):
return self.__class__ == other.__class__
def __hash__(self):
return hash(self.__class__)
def __str__(self):
return self.__class__.__name__
def make_node(self, x, *index): def make_node(self, x, *index):
x = theano.tensor.as_tensor_variable(x) x = theano.tensor.as_tensor_variable(x)
...@@ -2116,6 +2101,7 @@ class AdvancedIncSubtensor(Op): ...@@ -2116,6 +2101,7 @@ class AdvancedIncSubtensor(Op):
op. op.
""" """
__props__ = ("inplace", "set_instead_of_inc")
def __init__(self, inplace=False, set_instead_of_inc=False): def __init__(self, inplace=False, set_instead_of_inc=False):
self.inplace = inplace self.inplace = inplace
...@@ -2129,14 +2115,6 @@ class AdvancedIncSubtensor(Op): ...@@ -2129,14 +2115,6 @@ class AdvancedIncSubtensor(Op):
self.allow_legacy_perform = False self.allow_legacy_perform = False
def __hash__(self):
return hash((type(self), self.inplace, self.set_instead_of_inc))
def __eq__(self, other):
return (type(self) == type(other) and
self.inplace == other.inplace and
self.set_instead_of_inc == other.set_instead_of_inc)
def __str__(self): def __str__(self):
return "%s{%s, %s}" % (self.__class__.__name__, return "%s{%s, %s}" % (self.__class__.__name__,
"inplace=" + str(self.inplace), "inplace=" + str(self.inplace),
......
...@@ -21,6 +21,9 @@ def as_int_none_variable(x): ...@@ -21,6 +21,9 @@ def as_int_none_variable(x):
class MakeSlice(Op): class MakeSlice(Op):
__props__ = ()
def make_node(self, slc, stop=None, step=None): def make_node(self, slc, stop=None, step=None):
# We need to accept and handle in make_node inputs the node # We need to accept and handle in make_node inputs the node
# inputs to allow redoing a new op elsewhere in the graph by # inputs to allow redoing a new op elsewhere in the graph by
...@@ -39,15 +42,6 @@ class MakeSlice(Op): ...@@ -39,15 +42,6 @@ class MakeSlice(Op):
out, = out_ out, = out_
out[0] = slice(*inp) out[0] = slice(*inp)
def __str__(self):
return self.__class__.__name__
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def grad(self, inputs, grads): def grad(self, inputs, grads):
return [DisconnectedType()() for i in inputs] return [DisconnectedType()() for i in inputs]
......
...@@ -342,7 +342,7 @@ def test_scan_debugprint2(): ...@@ -342,7 +342,7 @@ def test_scan_debugprint2():
| |Subtensor{int64} [@J] '' | |Subtensor{int64} [@J] ''
| |Shape [@K] '' | |Shape [@K] ''
| | |Subtensor{int64::} [@L] '' | | |Subtensor{int64::} [@L] ''
| | |ARange [@M] '' | | |ARange{dtype='int16'} [@M] ''
| | | |TensorConstant{0} [@N] | | | |TensorConstant{0} [@N]
| | | |TensorConstant{10000} [@O] | | | |TensorConstant{10000} [@O]
| | | |TensorConstant{1} [@P] | | | |TensorConstant{1} [@P]
...@@ -425,7 +425,7 @@ def test_scan_debugprint3(): ...@@ -425,7 +425,7 @@ def test_scan_debugprint3():
| |Subtensor{int64} [@J] '' | |Subtensor{int64} [@J] ''
| |Shape [@K] '' | |Shape [@K] ''
| | |Subtensor{int64::} [@L] '' | | |Subtensor{int64::} [@L] ''
| | |ARange [@M] '' | | |ARange{dtype='int8'} [@M] ''
| | | |TensorConstant{0} [@N] | | | |TensorConstant{0} [@N]
| | | |TensorConstant{10} [@O] | | | |TensorConstant{10} [@O]
| | | |TensorConstant{1} [@P] | | | |TensorConstant{1} [@P]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论