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

Merge pull request #3107 from harlouci/flake8_v3

Flake8 tensor
...@@ -174,3 +174,13 @@ def test_tag_solve_triangular(): ...@@ -174,3 +174,13 @@ def test_tag_solve_triangular():
for node in f.maker.fgraph.toposort(): for node in f.maker.fgraph.toposort():
if isinstance(node.op, Solve): if isinstance(node.op, Solve):
assert node.op.A_structure == 'upper_triangular' assert node.op.A_structure == 'upper_triangular'
def test_matrix_inverse_solve():
if not imported_scipy:
raise SkipTest("Scipy needed for the Solve op.")
A = theano.tensor.dmatrix('A')
b = theano.tensor.dmatrix('b')
node = matrix_inverse(A).dot(b).owner
[out] = inv_as_solve.transform(node)
assert isinstance(out.owner.op, Solve)
...@@ -164,7 +164,7 @@ def default_blas_ldflags(): ...@@ -164,7 +164,7 @@ def default_blas_ldflags():
global numpy global numpy
try: try:
if (hasattr(numpy.distutils, '__config__') and if (hasattr(numpy.distutils, '__config__') and
numpy.distutils.__config__): numpy.distutils.__config__):
# If the old private interface is available use it as it # If the old private interface is available use it as it
# don't print information to the user. # don't print information to the user.
blas_info = numpy.distutils.__config__.blas_opt_info blas_info = numpy.distutils.__config__.blas_opt_info
...@@ -177,7 +177,7 @@ def default_blas_ldflags(): ...@@ -177,7 +177,7 @@ def default_blas_ldflags():
# ignored" # ignored"
# This happen with Python 2.7.3 |EPD 7.3-1 and numpy 1.8.1 # This happen with Python 2.7.3 |EPD 7.3-1 and numpy 1.8.1
import numpy.distutils.system_info # noqa import numpy.distutils.system_info # noqa
# We need to catch warnings as in some cases NumPy print # We need to catch warnings as in some cases NumPy print
# stuff that we don't want the user to see like this: # stuff that we don't want the user to see like this:
...@@ -276,7 +276,7 @@ SOMEPATH/Canopy_64bit/User/lib/python2.7/site-packages/numpy/distutils/system_in ...@@ -276,7 +276,7 @@ SOMEPATH/Canopy_64bit/User/lib/python2.7/site-packages/numpy/distutils/system_in
# Using "conda install mkl" will install both, as well as # Using "conda install mkl" will install both, as well as
# optimized versions of numpy and scipy. # optimized versions of numpy and scipy.
try: try:
import mkl #noqa import mkl # noqa
except ImportError as e: except ImportError as e:
_logger.info('Conda mkl is not available: %s', e) _logger.info('Conda mkl is not available: %s', e)
else: else:
...@@ -319,8 +319,8 @@ SOMEPATH/Canopy_64bit/User/lib/python2.7/site-packages/numpy/distutils/system_in ...@@ -319,8 +319,8 @@ SOMEPATH/Canopy_64bit/User/lib/python2.7/site-packages/numpy/distutils/system_in
AddConfigVar('blas.ldflags', AddConfigVar('blas.ldflags',
"lib[s] to include for [Fortran] level-3 blas implementation", "lib[s] to include for [Fortran] level-3 blas implementation",
StrParam(default_blas_ldflags)) StrParam(default_blas_ldflags))
try: try:
...@@ -333,12 +333,10 @@ try: ...@@ -333,12 +333,10 @@ try:
# `scipy.linalg.blas.fblas` with `scipy.linalg.blas`. # `scipy.linalg.blas.fblas` with `scipy.linalg.blas`.
# See http://github.com/scipy/scipy/pull/358 # See http://github.com/scipy/scipy/pull/358
fblas = scipy.linalg.blas fblas = scipy.linalg.blas
_blas_gemv_fns = { _blas_gemv_fns = {numpy.dtype('float32'): fblas.sgemv,
numpy.dtype('float32'): fblas.sgemv, numpy.dtype('float64'): fblas.dgemv,
numpy.dtype('float64'): fblas.dgemv, numpy.dtype('complex64'): fblas.cgemv,
numpy.dtype('complex64'): fblas.cgemv, numpy.dtype('complex128'): fblas.zgemv}
numpy.dtype('complex128'): fblas.zgemv,
}
except ImportError as e: except ImportError as e:
have_fblas = False have_fblas = False
# This is used in Gemv and ScipyGer. We use CGemv and CGer # This is used in Gemv and ScipyGer. We use CGemv and CGer
...@@ -400,8 +398,8 @@ class Gemv(Op): ...@@ -400,8 +398,8 @@ class Gemv(Op):
# The following is not grounds for error because as long as # The following is not grounds for error because as long as
# sizes are 1 at time of perform() there is no problem # sizes are 1 at time of perform() there is no problem
# if x.broadcastable[0] != A.broadcastable[1]: # if x.broadcastable[0] != A.broadcastable[1]:
# raise TypeError('broadcastable mismatch between x and A', # raise TypeError('broadcastable mismatch between x and A',
#(x.type, A.type)) # (x.type, A.type))
return Apply(self, [y, alpha, A, x, beta], [y.type()]) return Apply(self, [y, alpha, A, x, beta], [y.type()])
def perform(self, node, inputs, out_storage): def perform(self, node, inputs, out_storage):
...@@ -411,9 +409,10 @@ class Gemv(Op): ...@@ -411,9 +409,10 @@ class Gemv(Op):
gemv = _blas_gemv_fns[y.dtype] gemv = _blas_gemv_fns[y.dtype]
if (A.shape[0] != y.shape[0] or A.shape[1] != x.shape[0]): if (A.shape[0] != y.shape[0] or A.shape[1] != x.shape[0]):
raise ValueError('Incompatible shapes for gemv ' raise ValueError(
'(beta * y + alpha * dot(A, x)). y: %s, A: %s, x: %s ' 'Incompatible shapes for gemv '
% (y.shape, A.shape, x.shape)) '(beta * y + alpha * dot(A, x)). y: %s, A: %s, x: %s '
% (y.shape, A.shape, x.shape))
# Here I suppose that A is in c order. If we don't make it # Here I suppose that A is in c order. If we don't make it
# explicitly as fortran order, scipy 0.7.2 seam to create # explicitly as fortran order, scipy 0.7.2 seam to create
...@@ -479,7 +478,7 @@ class Ger(Op): ...@@ -479,7 +478,7 @@ class Ger(Op):
alpha = T.as_tensor_variable(alpha) alpha = T.as_tensor_variable(alpha)
if len(set([A.dtype, alpha.dtype, x.dtype, y.dtype])) != 1: if len(set([A.dtype, alpha.dtype, x.dtype, y.dtype])) != 1:
raise TypeError('ger requires matching dtypes', raise TypeError('ger requires matching dtypes',
(A.dtype, alpha.dtype, x.dtype, y.dtype)) (A.dtype, alpha.dtype, x.dtype, y.dtype))
if alpha.ndim != 0: if alpha.ndim != 0:
raise TypeError('ger requires scalar alpha', alpha.type) raise TypeError('ger requires scalar alpha', alpha.type)
if A.ndim != 2: if A.ndim != 2:
...@@ -567,13 +566,14 @@ def _ldflags(ldflags_str, libs, flags, libs_dir, include_dir): ...@@ -567,13 +566,14 @@ def _ldflags(ldflags_str, libs, flags, libs_dir, include_dir):
for d in dirs: for d in dirs:
for f in os.listdir(d): for f in os.listdir(d):
if (f.endswith('.so') or f.endswith('.dylib') or if (f.endswith('.so') or f.endswith('.dylib') or
f.endswith('.dll')): f.endswith('.dll')):
if any([f.find(ll) >= 0 for ll in l]): if any([f.find(ll) >= 0 for ll in l]):
found_dyn = True found_dyn = True
if not found_dyn and dirs: if not found_dyn and dirs:
_logger.warning("We did not found a dynamic library into the " _logger.warning(
"library_dir of the library we use for blas. If you use " "We did not found a dynamic library into the "
"ATLAS, make sure to compile it with dynamics library.") "library_dir of the library we use for blas. If you use "
"ATLAS, make sure to compile it with dynamics library.")
for t in ldflags_str.split(): for t in ldflags_str.split():
# Remove extra quote. # Remove extra quote.
...@@ -644,7 +644,7 @@ class GemmRelated(Op): ...@@ -644,7 +644,7 @@ class GemmRelated(Op):
return ldflags() return ldflags()
# code_cache_version is built by subclasses from # code_cache_version is built by subclasses from
# build_gemm_version # build_gemm_version
def c_compile_args(self): def c_compile_args(self):
return ldflags(libs=False, flags=True) return ldflags(libs=False, flags=True)
...@@ -673,7 +673,7 @@ class GemmRelated(Op): ...@@ -673,7 +673,7 @@ class GemmRelated(Op):
int sx_0, sx_1, sy_0, sy_1, sz_0, sz_1; int sx_0, sx_1, sy_0, sy_1, sz_0, sz_1;
""" """
#setup_z_Nz_Sz = None # setup_z_Nz_Sz = None
check_xyz_rank2 = """ check_xyz_rank2 = """
if (PyArray_NDIM(%(_x)s) != 2) { if (PyArray_NDIM(%(_x)s) != 2) {
...@@ -823,7 +823,7 @@ class GemmRelated(Op): ...@@ -823,7 +823,7 @@ class GemmRelated(Op):
{ {
""" """
#case_float_ab_constants = None # case_float_ab_constants = None
case_float_gemm = """ case_float_gemm = """
float* x = (float*)PyArray_DATA(%(_x)s); float* x = (float*)PyArray_DATA(%(_x)s);
...@@ -856,7 +856,7 @@ class GemmRelated(Op): ...@@ -856,7 +856,7 @@ class GemmRelated(Op):
{ {
""" """
#case_double_ab_constants = None # case_double_ab_constants = None
case_double_gemm = """ case_double_gemm = """
double* x = (double*)PyArray_DATA(%(_x)s); double* x = (double*)PyArray_DATA(%(_x)s);
...@@ -1028,10 +1028,10 @@ class Gemm(GemmRelated): ...@@ -1028,10 +1028,10 @@ class Gemm(GemmRelated):
if not (z.dtype == a.dtype == x.dtype == y.dtype == b.dtype): if not (z.dtype == a.dtype == x.dtype == y.dtype == b.dtype):
raise TypeError(Gemm.E_mixed, raise TypeError(Gemm.E_mixed,
(z.dtype, a.dtype, x.dtype, y.dtype, b.dtype)) (z.dtype, a.dtype, x.dtype, y.dtype, b.dtype))
if (not z.dtype.startswith('float') if (not z.dtype.startswith('float') and
and not z.dtype.startswith('complex')): not z.dtype.startswith('complex')):
raise TypeError(Gemm.E_float, (z.dtype)) raise TypeError(Gemm.E_float, (z.dtype))
output = z.type() output = z.type()
...@@ -1173,8 +1173,8 @@ class Gemm(GemmRelated): ...@@ -1173,8 +1173,8 @@ class Gemm(GemmRelated):
_z, _a, _x, _y, _b = inp _z, _a, _x, _y, _b = inp
_zout, = out _zout, = out
if node.inputs[0].type.dtype.startswith('complex'): if node.inputs[0].type.dtype.startswith('complex'):
raise utils.MethodNotDefined('%s.c_code' \ raise utils.MethodNotDefined('%s.c_code'
% self.__class__.__name__) % self.__class__.__name__)
if not config.blas.ldflags: if not config.blas.ldflags:
return super(Gemm, self).c_code(node, name, return super(Gemm, self).c_code(node, name,
(_z, _a, _x, _y, _b), (_zout, ), (_z, _a, _x, _y, _b), (_zout, ),
...@@ -1203,9 +1203,9 @@ def res_is_a(node, op, maxclients=None): ...@@ -1203,9 +1203,9 @@ def res_is_a(node, op, maxclients=None):
else: else:
retval = True retval = True
return node.owner \ return (node.owner and
and node.owner.op == op \ node.owner.op == op and
and retval retval)
def _as_scalar(res, dtype=None): def _as_scalar(res, dtype=None):
...@@ -1235,16 +1235,16 @@ def _as_scalar(res, dtype=None): ...@@ -1235,16 +1235,16 @@ def _as_scalar(res, dtype=None):
def _is_real_matrix(res): def _is_real_matrix(res):
return res.type.dtype in ('float32', 'float64') \ return (res.type.dtype in ('float32', 'float64') and
and res.type.ndim == 2 \ res.type.ndim == 2 and
and res.type.broadcastable[0] == False \ res.type.broadcastable[0] == False and
and res.type.broadcastable[1] == False # cope with tuple vs. list res.type.broadcastable[1] == False) # cope with tuple vs. list
def _is_real_vector(res): def _is_real_vector(res):
return res.type.dtype in ('float32', 'float64') \ return (res.type.dtype in ('float32', 'float64') and
and res.type.ndim == 1 \ res.type.ndim == 1 and
and res.type.broadcastable[0] == False res.type.broadcastable[0] == False)
def _beta_L_plus_alpha_M(beta, L, alpha, M, recurse_flip=True): def _beta_L_plus_alpha_M(beta, L, alpha, M, recurse_flip=True):
...@@ -1262,8 +1262,8 @@ def _beta_L_plus_alpha_M(beta, L, alpha, M, recurse_flip=True): ...@@ -1262,8 +1262,8 @@ def _beta_L_plus_alpha_M(beta, L, alpha, M, recurse_flip=True):
# it also might be the case that there is a dimshuffle between the + # it also might be the case that there is a dimshuffle between the +
# and the dot22. local_dot_to_dot22 in particular will put in such things. # and the dot22. local_dot_to_dot22 in particular will put in such things.
if (M.owner and isinstance(M.owner.op, T.DimShuffle) and if (M.owner and isinstance(M.owner.op, T.DimShuffle) and
M.owner.inputs[0].owner and M.owner.inputs[0].owner and
isinstance(M.owner.inputs[0].owner.op, Dot22)): isinstance(M.owner.inputs[0].owner.op, Dot22)):
MM = M.owner.inputs[0] MM = M.owner.inputs[0]
if M.owner.op.new_order == (0,): if M.owner.op.new_order == (0,):
# it is making a column MM into a vector # it is making a column MM into a vector
...@@ -1493,7 +1493,7 @@ def _gemm_from_factored_list(lst): ...@@ -1493,7 +1493,7 @@ def _gemm_from_factored_list(lst):
assert len(gemm_of_sM_list) == 1 assert len(gemm_of_sM_list) == 1
add_inputs = [item_to_var(input) add_inputs = [item_to_var(input)
for k, input in enumerate(lst) if k not in (i, j)] for k, input in enumerate(lst) if k not in (i, j)]
add_inputs.extend(gemm_of_sM_list) add_inputs.extend(gemm_of_sM_list)
if len(add_inputs) > 1: if len(add_inputs) > 1:
rval = [T.add(*add_inputs)] rval = [T.add(*add_inputs)]
...@@ -1583,7 +1583,7 @@ class GemmOptimizer(Optimizer): ...@@ -1583,7 +1583,7 @@ class GemmOptimizer(Optimizer):
(theano.scalar.Add, theano.scalar.Sub, (theano.scalar.Add, theano.scalar.Sub,
theano.scalar.Neg, theano.scalar.Mul))): theano.scalar.Neg, theano.scalar.Mul))):
continue continue
if not node in fgraph.apply_nodes: if node not in fgraph.apply_nodes:
# This mean that we already removed this node from # This mean that we already removed this node from
# the graph # the graph
continue continue
...@@ -1592,7 +1592,7 @@ class GemmOptimizer(Optimizer): ...@@ -1592,7 +1592,7 @@ class GemmOptimizer(Optimizer):
time_canonicalize += time1 time_canonicalize += time1
time_factor_can += time2 time_factor_can += time2
time_factor_list += time3 time_factor_list += time3
except InconsistencyError as e: except InconsistencyError:
nb_inconsistency_make += 1 nb_inconsistency_make += 1
continue continue
if new_outputs: if new_outputs:
...@@ -1725,8 +1725,8 @@ class Dot22(GemmRelated): ...@@ -1725,8 +1725,8 @@ class Dot22(GemmRelated):
_x, _y = inp _x, _y = inp
_zout, = out _zout, = out
if node.inputs[0].type.dtype.startswith('complex'): if node.inputs[0].type.dtype.startswith('complex'):
raise utils.MethodNotDefined('%s.c_code' \ raise utils.MethodNotDefined('%s.c_code'
% self.__class__.__name__) % self.__class__.__name__)
if len(self.c_libraries()) <= 0: if len(self.c_libraries()) <= 0:
return super(Dot22, self).c_code(node, name, (_x, _y), return super(Dot22, self).c_code(node, name, (_x, _y),
(_zout, ), sub) (_zout, ), sub)
...@@ -1895,17 +1895,16 @@ blas_optdb.register('local_dot_to_dot22', ...@@ -1895,17 +1895,16 @@ blas_optdb.register('local_dot_to_dot22',
in2out(local_dot_to_dot22), in2out(local_dot_to_dot22),
0, 'fast_run', 'fast_compile') 0, 'fast_run', 'fast_compile')
blas_optdb.register('gemm_optimizer', blas_optdb.register('gemm_optimizer',
GemmOptimizer(), GemmOptimizer(),
10, 'fast_run') 10, 'fast_run')
blas_optdb.register('local_gemm_to_gemv', blas_optdb.register('local_gemm_to_gemv',
EquilibriumOptimizer([ EquilibriumOptimizer([local_gemm_to_gemv,
local_gemm_to_gemv, local_gemm_to_ger,
local_gemm_to_ger, local_dot22_to_ger_or_gemv,
local_dot22_to_ger_or_gemv, local_dimshuffle_lift],
local_dimshuffle_lift], max_use_ratio=5,
max_use_ratio=5, ignore_newtrees=False),
ignore_newtrees=False), 15, 'fast_run')
15, 'fast_run')
# After destroyhandler(49.5) but before we try to make elemwise things # After destroyhandler(49.5) but before we try to make elemwise things
...@@ -1936,12 +1935,12 @@ class Dot22Scalar(GemmRelated): ...@@ -1936,12 +1935,12 @@ class Dot22Scalar(GemmRelated):
if not (a.dtype == x.dtype == y.dtype): if not (a.dtype == x.dtype == y.dtype):
raise TypeError('Dot22Scalar requires matching dtypes', raise TypeError('Dot22Scalar requires matching dtypes',
(a.dtype, x.dtype, y.dtype)) (a.dtype, x.dtype, y.dtype))
if (not a.dtype.startswith('float') if (not a.dtype.startswith('float') and
and not a.dtype.startswith('complex')): not a.dtype.startswith('complex')):
raise TypeError('Dot22Scalar requires float or complex args', raise TypeError('Dot22Scalar requires float or complex args',
a.dtype) a.dtype)
bz = [x.type.broadcastable[0], y.type.broadcastable[1]] bz = [x.type.broadcastable[0], y.type.broadcastable[1]]
outputs = [T.tensor(x.type.dtype, bz)] outputs = [T.tensor(x.type.dtype, bz)]
...@@ -1992,8 +1991,8 @@ class Dot22Scalar(GemmRelated): ...@@ -1992,8 +1991,8 @@ class Dot22Scalar(GemmRelated):
_x, _y, _a = inp _x, _y, _a = inp
_zout, = out _zout, = out
if node.inputs[0].type.dtype.startswith('complex'): if node.inputs[0].type.dtype.startswith('complex'):
raise utils.MethodNotDefined('%s.c_code' \ raise utils.MethodNotDefined('%s.c_code'
% self.__class__.__name__) % self.__class__.__name__)
if len(self.c_libraries()) <= 0: if len(self.c_libraries()) <= 0:
return super(Dot22Scalar, self).c_code(node, name, (_x, _y), return super(Dot22Scalar, self).c_code(node, name, (_x, _y),
(_zout, ), sub) (_zout, ), sub)
...@@ -2051,7 +2050,7 @@ def local_dot22_to_dot22scalar(node): ...@@ -2051,7 +2050,7 @@ def local_dot22_to_dot22scalar(node):
# The canonizer should have merged those mul together. # The canonizer should have merged those mul together.
i_mul = [x.owner and x.owner.op == T.mul and i_mul = [x.owner and x.owner.op == T.mul and
any([_as_scalar(x_i, dtype=d.dtype) any([_as_scalar(x_i, dtype=d.dtype)
for x_i in x.owner.inputs]) for x_i in x.owner.inputs])
for x in node.inputs] for x in node.inputs]
if not any(i_mul): if not any(i_mul):
# no scalar in input and no multiplication # no scalar in input and no multiplication
...@@ -2065,8 +2064,7 @@ def local_dot22_to_dot22scalar(node): ...@@ -2065,8 +2064,7 @@ def local_dot22_to_dot22scalar(node):
scalar_idx = -1 scalar_idx = -1
for i, x in enumerate(m.owner.inputs): for i, x in enumerate(m.owner.inputs):
if _as_scalar(x, dtype=d.dtype) and (theano.scalar.upcast( if _as_scalar(x, dtype=d.dtype) and (theano.scalar.upcast(
x.type.dtype, d.type.dtype) x.type.dtype, d.type.dtype) == d.type.dtype):
== d.type.dtype):
scalar_idx = i scalar_idx = i
break break
...@@ -2103,8 +2101,8 @@ def local_dot22_to_dot22scalar(node): ...@@ -2103,8 +2101,8 @@ def local_dot22_to_dot22scalar(node):
break break
if scalar_idx < 0: if scalar_idx < 0:
_logger.info('Not optimizing dot22 with inputs %s %s, as the type ' _logger.info('Not optimizing dot22 with inputs %s %s, as the type '
'of the scalar cannot be upcasted to the matrix type', 'of the scalar cannot be upcasted to the matrix type',
node.inputs, [x.type for x in node.inputs]) node.inputs, [x.type for x in node.inputs])
return False return False
assert scalar_idx < len(node.inputs) assert scalar_idx < len(node.inputs)
s = node.inputs[scalar_idx] s = node.inputs[scalar_idx]
...@@ -2128,8 +2126,8 @@ blas_optdb.register('local_dot22_to_dot22scalar', ...@@ -2128,8 +2126,8 @@ blas_optdb.register('local_dot22_to_dot22scalar',
11, 'fast_run') 11, 'fast_run')
#from opt import register_specialize, register_canonicalize # from opt import register_specialize, register_canonicalize
#@register_specialize # @register_specialize
@local_optimizer([T.sub, T.add]) @local_optimizer([T.sub, T.add])
def local_print_as_we_go_along(node): def local_print_as_we_go_along(node):
if node.op in (T.sub, T.add): if node.op in (T.sub, T.add):
......
...@@ -4,8 +4,7 @@ from theano import config ...@@ -4,8 +4,7 @@ from theano import config
from theano.tensor.opt import in2out from theano.tensor.opt import in2out
from theano.tensor.blas import ldflags, blas_header_text, blas_header_version from theano.tensor.blas import ldflags, blas_header_text, blas_header_version
from theano.tensor.blas import ( from theano.tensor.blas import blas_optdb, optdb, local_optimizer
blas_optdb, optdb, local_optimizer, EquilibriumOptimizer)
from theano.tensor.blas import Ger, ger, ger_destructive from theano.tensor.blas import Ger, ger, ger_destructive
from theano.tensor.blas import Gemv, gemv_inplace, gemv_no_inplace from theano.tensor.blas import Gemv, gemv_inplace, gemv_no_inplace
from theano.tensor import basic as T from theano.tensor import basic as T
...@@ -268,7 +267,7 @@ def ger_c_code(A, a, x, y, Z, destructive, fail): ...@@ -268,7 +267,7 @@ def ger_c_code(A, a, x, y, Z, destructive, fail):
(double*)x_data, &Sx, (double*)x_data, &Sx,
(double*)y_data, &Sy, (double*)y_data, &Sy,
(double*)(PyArray_DATA(%(Z)s)), &Sz1); (double*)(PyArray_DATA(%(Z)s)), &Sz1);
} }
else { else {
...@@ -610,7 +609,7 @@ def gemv_c_code(aa, xx, yy, zz, alpha, beta, destructive, fail, ...@@ -610,7 +609,7 @@ def gemv_c_code(aa, xx, yy, zz, alpha, beta, destructive, fail,
// so Sx1 == 1 is required for safety. // so Sx1 == 1 is required for safety.
if (Nx0 == 1 && Sx1 == 1) if (Nx0 == 1 && Sx1 == 1)
{ {
zz_data[0] = fbeta*zz_data[0] + alpha*sdot_(&Nx1, zz_data[0] = fbeta*zz_data[0] + alpha*sdot_(&Nx1,
(float*)(PyArray_DATA(%(xx)s)), &Sx1, (float*)(PyArray_DATA(%(xx)s)), &Sx1,
(float*)yy_data, &Sy); (float*)yy_data, &Sy);
} }
...@@ -633,7 +632,7 @@ def gemv_c_code(aa, xx, yy, zz, alpha, beta, destructive, fail, ...@@ -633,7 +632,7 @@ def gemv_c_code(aa, xx, yy, zz, alpha, beta, destructive, fail,
// so Sx1 == 1 is required for safety. // so Sx1 == 1 is required for safety.
if (Nx0 == 1 && Sx1 == 1) if (Nx0 == 1 && Sx1 == 1)
{ {
zz_data[0] = dbeta*zz_data[0] + alpha*ddot_(&Nx1, zz_data[0] = dbeta*zz_data[0] + alpha*ddot_(&Nx1,
(double*)(PyArray_DATA(%(xx)s)), &Sx1, (double*)(PyArray_DATA(%(xx)s)), &Sx1,
(double*)yy_data, &Sy); (double*)yy_data, &Sy);
} }
...@@ -732,8 +731,7 @@ def check_force_gemv_init(): ...@@ -732,8 +731,7 @@ def check_force_gemv_init():
gemv_no_inplace(aa, 1., xx, yy, 0.), gemv_no_inplace(aa, 1., xx, yy, 0.),
theano.compile.Mode(optimizer='fast_compile').excluding('gpu', theano.compile.Mode(optimizer='fast_compile').excluding('gpu',
'gpuarray'), 'gpuarray'),
profile=False profile=False)
)
finally: finally:
theano.config.compute_test_value = tv theano.config.compute_test_value = tv
theano.config.compute_test_value_opt = tvo theano.config.compute_test_value_opt = tvo
...@@ -742,11 +740,11 @@ def check_force_gemv_init(): ...@@ -742,11 +740,11 @@ def check_force_gemv_init():
# then we want gemv_c_code to initiliaze the memory to 0 so that we # then we want gemv_c_code to initiliaze the memory to 0 so that we
# don't inadvertantly introduce NaNs to the users data. # don't inadvertantly introduce NaNs to the users data.
aa_data = numpy.array( aa_data = numpy.array(
float('NaN')*numpy.ones((2,)), float('NaN') * numpy.ones((2,)),
dtype=theano.config.floatX dtype=theano.config.floatX
) )
yy_data = numpy.array( yy_data = numpy.array(
numpy.ones((2,))*2, numpy.ones((2,)) * 2,
dtype=theano.config.floatX dtype=theano.config.floatX
) )
xx_data = numpy.array( xx_data = numpy.array(
......
...@@ -12,11 +12,11 @@ from theano.tensor.opt import in2out ...@@ -12,11 +12,11 @@ from theano.tensor.opt import in2out
if have_fblas: if have_fblas:
from theano.tensor.blas import fblas from theano.tensor.blas import fblas
_blas_ger_fns = { _blas_ger_fns = {
numpy.dtype('float32'): fblas.sger, numpy.dtype('float32'): fblas.sger,
numpy.dtype('float64'): fblas.dger, numpy.dtype('float64'): fblas.dger,
numpy.dtype('complex64'): fblas.cgeru, numpy.dtype('complex64'): fblas.cgeru,
numpy.dtype('complex128'): fblas.zgeru, numpy.dtype('complex128'): fblas.zgeru,
} }
class ScipyGer(Ger): class ScipyGer(Ger):
...@@ -47,10 +47,10 @@ class ScipyGer(Ger): ...@@ -47,10 +47,10 @@ class ScipyGer(Ger):
A = A.copy() A = A.copy()
elif A.flags['C_CONTIGUOUS']: elif A.flags['C_CONTIGUOUS']:
A = local_ger(calpha[0], cy[0], cx[0], a=A.T, A = local_ger(calpha[0], cy[0], cx[0], a=A.T,
overwrite_a=int(self.destructive)).T overwrite_a=int(self.destructive)).T
else: else:
A = local_ger(calpha[0], cx[0], cy[0], a=A, A = local_ger(calpha[0], cx[0], cy[0], a=A,
overwrite_a=int(self.destructive)) overwrite_a=int(self.destructive))
cZ[0] = A cZ[0] = A
for o in node_output_compute: for o in node_output_compute:
o[0] = True o[0] = True
...@@ -87,10 +87,10 @@ if have_fblas: ...@@ -87,10 +87,10 @@ if have_fblas:
# precedence. Once the original Ger is replaced, then these optimizations # precedence. Once the original Ger is replaced, then these optimizations
# have no effect. # have no effect.
blas_optdb.register('scipy_blas', blas_optdb.register('scipy_blas',
use_scipy_blas, use_scipy_blas,
100, 'fast_run') 100, 'fast_run')
# this matches the InplaceBlasOpt defined in blas.py # this matches the InplaceBlasOpt defined in blas.py
optdb.register('make_scipy_blas_destructive', optdb.register('make_scipy_blas_destructive',
make_scipy_blas_destructive, make_scipy_blas_destructive,
70.0, 'fast_run', 'inplace') 70.0, 'fast_run', 'inplace')
...@@ -276,7 +276,7 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -276,7 +276,7 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
if index != 'x': if index != 'x':
order_loops += """ order_loops += """
%(ovar)s_loops_it->first = abs(PyArray_STRIDES(%(ovar)s)[%(index)i]); %(ovar)s_loops_it->first = abs(PyArray_STRIDES(%(ovar)s)[%(index)i]);
""" % locals() """ % locals()
else: else:
# Stride is 0 when dimension is broadcastable # Stride is 0 when dimension is broadcastable
order_loops += """ order_loops += """
...@@ -311,15 +311,13 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -311,15 +311,13 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
total = "%(var)s_n%(candidate)s" % locals() total = "%(var)s_n%(candidate)s" % locals()
break break
else: else:
total = '1'; total = '1'
totals.append(total) totals.append(total)
declare_totals = """ declare_totals = """
int init_totals[%(nnested)s] = {%(totals)s}; int init_totals[%(nnested)s] = {%(totals)s};
""" % dict( """ % dict(nnested=nnested,
nnested=nnested, totals=', '.join(totals))
totals=', '.join(totals)
)
# Sort totals to match the new order that was computed by sorting # Sort totals to match the new order that was computed by sorting
# the loop vector. One integer variable per loop is declared. # the loop vector. One integer variable per loop is declared.
...@@ -355,13 +353,11 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -355,13 +353,11 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
declare_strides = """ declare_strides = """
int init_strides[%(nvars)i][%(nnested)i] = { int init_strides[%(nvars)i][%(nnested)i] = {
%(strides)s %(strides)s
};""" % dict( };""" % dict(nvars=nvars,
nvars=nvars, nnested=nnested,
nnested=nnested, strides=', \n'.join(', '.join(get_loop_strides(lo, i))
strides=', \n'.join( for i, lo in enumerate(init_loop_orders)
', '.join(get_loop_strides(lo, i)) if len(lo) > 0))
for i, lo in enumerate(init_loop_orders)
if len(lo) > 0))
# Declare (sorted) stride and for each variable # Declare (sorted) stride and for each variable
# we iterate from innermost loop to outermost loop # we iterate from innermost loop to outermost loop
...@@ -385,9 +381,9 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -385,9 +381,9 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
declare_iter += "%(var)s_iter = (%(dtype)s*)(PyArray_DATA(%(var)s));\n" % locals() declare_iter += "%(var)s_iter = (%(dtype)s*)(PyArray_DATA(%(var)s));\n" % locals()
pointer_update = '' pointer_update = ''
for j , dtype in enumerate(dtypes): for j, dtype in enumerate(dtypes):
var = sub["lv%i" % j] var = sub["lv%i" % j]
pointer_update += "%(dtype)s &%(var)s_i = * ( %(var)s_iter"%locals() pointer_update += "%(dtype)s &%(var)s_i = * ( %(var)s_iter" % locals()
tot_jump = '' tot_jump = ''
for i in reversed(range(nnested)): for i in reversed(range(nnested)):
iterv = 'ITER_%i' % i iterv = 'ITER_%i' % i
...@@ -401,7 +397,7 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -401,7 +397,7 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
update = '' update = ''
forloop = '' forloop = ''
# The pointers are defined only in the most inner loop # The pointers are defined only in the most inner loop
if i == nnested-1: if i == nnested - 1:
update = pointer_update update = pointer_update
if i == 0: if i == 0:
if openmp: if openmp:
...@@ -413,19 +409,17 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -413,19 +409,17 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
%(forloop)s %(forloop)s
{ // begin loop %(i)i { // begin loop %(i)i
%(update)s %(update)s
%(loop)s %(loop)s
} // end loop %(i)i } // end loop %(i)i
""" % locals() """ % locals()
return '\n'.join([ return '\n'.join(['{',
'{', order_loops,
order_loops, declare_totals,
declare_totals, declare_strides,
declare_strides, declare_iter,
declare_iter, loop,
loop, '}\n'])
'}\n',
])
# print make_declare(((0, 1, 2, 3), ('x', 1, 0, 3), ('x', 'x', 'x', 0)), # print make_declare(((0, 1, 2, 3), ('x', 1, 0, 3), ('x', 'x', 'x', 0)),
# ('double', 'int', 'float'), # ('double', 'int', 'float'),
...@@ -451,16 +445,16 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op ...@@ -451,16 +445,16 @@ def make_reordered_loop(init_loop_orders, olv_index, dtypes, inner_task, sub, op
################## ##################
### DimShuffle ### # DimShuffle #
################## ##################
################# #################
### Broadcast ### # Broadcast #
################# #################
################ ################
### CAReduce ### # CAReduce #
################ ################
...@@ -527,4 +521,3 @@ def make_loop_careduce(loop_orders, dtypes, loop_tasks, sub): ...@@ -527,4 +521,3 @@ def make_loop_careduce(loop_orders, dtypes, loop_tasks, sub):
s += loop_tasks[-1] s += loop_tasks[-1]
return "{%s}" % s return "{%s}" % s
...@@ -5,6 +5,7 @@ from six.moves import xrange ...@@ -5,6 +5,7 @@ from six.moves import xrange
import theano import theano
from theano.tensor import basic from theano.tensor import basic
from theano.tensor import nlinalg # noqa
from theano import gof, scalar from theano import gof, scalar
from theano.gradient import DisconnectedType from theano.gradient import DisconnectedType
tensor = basic tensor = basic
......
...@@ -62,7 +62,7 @@ class Fourier(gof.Op): ...@@ -62,7 +62,7 @@ class Fourier(gof.Op):
(axis.data < 0 or axis.data > a.ndim - 1)): (axis.data < 0 or axis.data > a.ndim - 1)):
raise TypeError('%s: index of the transformed axis must be' raise TypeError('%s: index of the transformed axis must be'
' a scalar not smaller than 0 and smaller than' ' a scalar not smaller than 0 and smaller than'
' dimension of array' % self.__class__.__name__) ' dimension of array' % self.__class__.__name__)
if n is None: if n is None:
n = a.shape[axis] n = a.shape[axis]
n = tensor.as_tensor_variable(n) n = tensor.as_tensor_variable(n)
...@@ -78,7 +78,7 @@ class Fourier(gof.Op): ...@@ -78,7 +78,7 @@ class Fourier(gof.Op):
' strictly positive scalar' ' strictly positive scalar'
% self.__class__.__name__) % self.__class__.__name__)
return gof.Apply(self, [a, n, axis], [tensor.TensorType('complex128', return gof.Apply(self, [a, n, axis], [tensor.TensorType('complex128',
a.type.broadcastable)()]) a.type.broadcastable)()])
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
shape_a = in_shapes[0] shape_a = in_shapes[0]
...@@ -87,8 +87,8 @@ class Fourier(gof.Op): ...@@ -87,8 +87,8 @@ class Fourier(gof.Op):
if len(shape_a) == 1: if len(shape_a) == 1:
return [(n,)] return [(n,)]
elif isinstance(axis, tensor.TensorConstant): elif isinstance(axis, tensor.TensorConstant):
out_shape = list(shape_a[0: axis.data.item()]) + [n] +\ out_shape = (list(shape_a[0: axis.data.item()]) + [n] +
list(shape_a[axis.data + 1:]) list(shape_a[axis.data + 1:]))
else: else:
l = len(shape_a) l = len(shape_a)
shape_a = tensor.stack(*shape_a) shape_a = tensor.stack(*shape_a)
...@@ -136,7 +136,8 @@ class Fourier(gof.Op): ...@@ -136,7 +136,8 @@ class Fourier(gof.Op):
flip_shape = list(numpy.arange(0, a.ndim)[::-1]) flip_shape = list(numpy.arange(0, a.ndim)[::-1])
res = res.dimshuffle(flip_shape) res = res.dimshuffle(flip_shape)
res = tensor.switch(tensor.lt(n, tensor.shape(a)[axis]), res = tensor.switch(tensor.lt(n, tensor.shape(a)[axis]),
tensor.set_subtensor(res[n::, ], 0, False, False), res) tensor.set_subtensor(res[n::, ], 0, False, False),
res)
res = res.dimshuffle(flip_shape) res = res.dimshuffle(flip_shape)
# insures that gradient shape conforms to input shape: # insures that gradient shape conforms to input shape:
......
from __future__ import print_function from __future__ import print_function
import logging import logging
import theano
logger = logging.getLogger(__name__)
import numpy import numpy
from six.moves import xrange from six.moves import xrange
import theano
from theano.tensor import as_tensor_variable
from theano.gof import Op, Apply from theano.gof import Op, Apply
from theano.tensor import as_tensor_variable, dot, DimShuffle, Dot
from theano.tensor.blas import Dot22
from theano.tensor.opt import (register_stabilize,
register_specialize, register_canonicalize)
from theano.gof import local_optimizer
from theano.gof.opt import Optimizer
from theano.gradient import DisconnectedType from theano.gradient import DisconnectedType
from theano.tensor import basic as tensor from theano.tensor import basic as tensor
logger = logging.getLogger(__name__)
class MatrixPinv(Op): class MatrixPinv(Op):
"""Computes the pseudo-inverse of a matrix :math:`A`. """Computes the pseudo-inverse of a matrix :math:`A`.
...@@ -427,8 +423,10 @@ class EighGrad(Op): ...@@ -427,8 +423,10 @@ class EighGrad(Op):
N = x.shape[0] N = x.shape[0]
outer = numpy.outer outer = numpy.outer
G = lambda n: sum(v[:, m] * V.T[n].dot(v[:, m]) / (w[n] - w[m]) def G(n):
for m in xrange(N) if m != n) return sum(v[:, m] * V.T[n].dot(v[:, m]) / (w[n] - w[m])
for m in xrange(N) if m != n)
g = sum(outer(v[:, n], v[:, n] * W[n] + G(n)) g = sum(outer(v[:, n], v[:, n] * W[n] + G(n))
for n in xrange(N)) for n in xrange(N))
...@@ -641,16 +639,6 @@ def svd(a, full_matrices=1, compute_uv=1): ...@@ -641,16 +639,6 @@ def svd(a, full_matrices=1, compute_uv=1):
return SVD(full_matrices, compute_uv)(a) return SVD(full_matrices, compute_uv)(a)
def test_matrix_inverse_solve():
if not imported_scipy:
raise SkipTest("Scipy needed for the Solve op.")
A = theano.tensor.dmatrix('A')
b = theano.tensor.dmatrix('b')
node = matrix_inverse(A).dot(b).owner
[out] = inv_as_solve.transform(node)
assert isinstance(out.owner.op, Solve)
class lstsq(Op): class lstsq(Op):
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) return type(self) == type(other)
...@@ -670,9 +658,6 @@ class lstsq(Op): ...@@ -670,9 +658,6 @@ class lstsq(Op):
theano.tensor.lscalar(), theano.tensor.dvector()]) theano.tensor.lscalar(), theano.tensor.dvector()])
def perform(self, node, inputs, outputs): def perform(self, node, inputs, outputs):
x = inputs[0]
y = inputs[1]
rcond = inputs[2]
zz = numpy.linalg.lstsq(inputs[0], inputs[1], inputs[2]) zz = numpy.linalg.lstsq(inputs[0], inputs[1], inputs[2])
outputs[0][0] = zz[0] outputs[0][0] = zz[0]
outputs[1][0] = zz[1] outputs[1][0] = zz[1]
...@@ -703,7 +688,7 @@ def norm(x, ord): ...@@ -703,7 +688,7 @@ def norm(x, ord):
return x[x.nonzero()].shape[0] return x[x.nonzero()].shape[0]
else: else:
try: try:
z = tensor.sum(abs(x**ord))**(1./ord) z = tensor.sum(abs(x**ord))**(1. / ord)
except TypeError: except TypeError:
raise ValueError("Invalid norm order for vectors.") raise ValueError("Invalid norm order for vectors.")
return z return z
......
...@@ -33,7 +33,6 @@ supposed to be canonical. ...@@ -33,7 +33,6 @@ supposed to be canonical.
# TODO: intelligent merge for mul/add # TODO: intelligent merge for mul/add
# TODO: 0*x -> 0 # TODO: 0*x -> 0
import logging import logging
_logger = logging.getLogger('theano.tensor.opt')
from theano import gof from theano import gof
from theano.tensor.elemwise import CAReduce from theano.tensor.elemwise import CAReduce
...@@ -44,6 +43,8 @@ from theano.tensor.basic import (get_scalar_constant_value, ...@@ -44,6 +43,8 @@ from theano.tensor.basic import (get_scalar_constant_value,
from theano.tensor.opt import register_uncanonicalize from theano.tensor.opt import register_uncanonicalize
from theano import scalar as scal from theano import scalar as scal
_logger = logging.getLogger('theano.tensor.opt')
@register_uncanonicalize @register_uncanonicalize
@gof.local_optimizer([T._max_and_argmax]) @gof.local_optimizer([T._max_and_argmax])
...@@ -81,8 +82,8 @@ def local_max_to_min(node): ...@@ -81,8 +82,8 @@ def local_max_to_min(node):
if node.op == T.neg and node.inputs[0].owner: if node.op == T.neg and node.inputs[0].owner:
max = node.inputs[0] max = node.inputs[0]
if (max.owner and if (max.owner and
isinstance(max.owner.op, CAReduce) isinstance(max.owner.op, CAReduce) and
and max.owner.op.scalar_op == scal.maximum): max.owner.op.scalar_op == scal.maximum):
neg = max.owner.inputs[0] neg = max.owner.inputs[0]
if neg.owner and neg.owner.op == T.neg: if neg.owner and neg.owner.op == T.neg:
return [CAReduce(scal.minimum, return [CAReduce(scal.minimum,
......
import logging import logging
_logger = logging.getLogger("theano.tensor.type") import warnings
import numpy import numpy
import theano import theano
from theano import config from theano import config
from theano.gof import Constant, hashtype, Type, Variable from theano.gof import hashtype, Type, Variable
from theano.gof.utils import MethodNotDefined
from theano import scalar as scal from theano import scalar as scal
_logger = logging.getLogger("theano.tensor.type")
class TensorType(Type): class TensorType(Type):
"""Symbolic `Type` representing a numpy.ndarray value.""" """Symbolic `Type` representing a numpy.ndarray value."""
...@@ -39,7 +40,7 @@ class TensorType(Type): ...@@ -39,7 +40,7 @@ class TensorType(Type):
if self.dtype == 'floatX': if self.dtype == 'floatX':
self.dtype = config.floatX self.dtype = config.floatX
# broadcastable is immutable, and all elements are either # broadcastable is immutable, and all elements are either
### True or False # True or False
self.broadcastable = tuple(bool(b) for b in broadcastable) self.broadcastable = tuple(bool(b) for b in broadcastable)
self.dtype_specs() # error checking is done there self.dtype_specs() # error checking is done there
self.name = name self.name = name
...@@ -74,17 +75,17 @@ class TensorType(Type): ...@@ -74,17 +75,17 @@ class TensorType(Type):
# input (typical mistake, especially with shared variables). # input (typical mistake, especially with shared variables).
if isinstance(data, Variable): if isinstance(data, Variable):
raise TypeError( raise TypeError(
'Expected an array-like object, but found a Variable: ' 'Expected an array-like object, but found a Variable: '
'maybe you are trying to call a function on a (possibly ' 'maybe you are trying to call a function on a (possibly '
'shared) variable instead of a numeric array?') 'shared) variable instead of a numeric array?')
if ((type(data) is numpy.ndarray) if ((type(data) is numpy.ndarray) and
and (data.dtype == self.numpy_dtype)): (data.dtype == self.numpy_dtype)):
if data.dtype.num != self.numpy_dtype.num: if data.dtype.num != self.numpy_dtype.num:
data = theano._asarray(data, dtype=self.dtype) data = theano._asarray(data, dtype=self.dtype)
# -- now fall through to ndim check # -- now fall through to ndim check
elif((type(data) is numpy.memmap) elif ((type(data) is numpy.memmap) and
and (data.dtype == self.numpy_dtype)): (data.dtype == self.numpy_dtype)):
# numpy.memmap is a "safe" subclass of ndarray, # numpy.memmap is a "safe" subclass of ndarray,
# so we can use it whereever we expect a base ndarray. # so we can use it whereever we expect a base ndarray.
# however, casting it would defeat the purpose of not # however, casting it would defeat the purpose of not
...@@ -95,11 +96,11 @@ class TensorType(Type): ...@@ -95,11 +96,11 @@ class TensorType(Type):
# we raise a meaningful TypeError. # we raise a meaningful TypeError.
if not (type(data) is numpy.ndarray): if not (type(data) is numpy.ndarray):
raise TypeError("%s expected a ndarray object." % self, raise TypeError("%s expected a ndarray object." % self,
data, type(data)) data, type(data))
if data.dtype != self.numpy_dtype: if data.dtype != self.numpy_dtype:
raise TypeError(("%s expected a ndarray object with " raise TypeError(("%s expected a ndarray object with "
"dtype = %s (got %s).") % ( "dtype = %s (got %s).") %
self, self.numpy_dtype, data.dtype)) (self, self.numpy_dtype, data.dtype))
assert False, "This point should never be reached." assert False, "This point should never be reached."
else: else:
if allow_downcast: if allow_downcast:
...@@ -185,7 +186,7 @@ class TensorType(Type): ...@@ -185,7 +186,7 @@ class TensorType(Type):
" dimension.", data.shape, self.broadcastable) " dimension.", data.shape, self.broadcastable)
i += 1 i += 1
if (self.filter_checks_isfinite and if (self.filter_checks_isfinite and
not numpy.all(numpy.isfinite(data))): not numpy.all(numpy.isfinite(data))):
raise ValueError("non-finite elements not allowed") raise ValueError("non-finite elements not allowed")
return data return data
...@@ -208,14 +209,12 @@ class TensorType(Type): ...@@ -208,14 +209,12 @@ class TensorType(Type):
return other return other
raise TypeError( raise TypeError(
'Cannot convert Type %(othertype)s ' 'Cannot convert Type %(othertype)s '
'(of Variable %(other)s) into Type %(self)s. ' '(of Variable %(other)s) into Type %(self)s. '
'You can try to manually convert %(other)s into a %(self)s.' 'You can try to manually convert %(other)s into a %(self)s.' %
% dict( dict(othertype=other.type,
othertype=other.type, other=other,
other=other, self=self))
self=self)
)
def value_validity_msg(self, a): def value_validity_msg(self, a):
try: try:
...@@ -247,10 +246,10 @@ class TensorType(Type): ...@@ -247,10 +246,10 @@ class TensorType(Type):
'int64': (int, 'npy_int64', 'NPY_INT64'), 'int64': (int, 'npy_int64', 'NPY_INT64'),
'complex128': (complex, 'theano_complex128', 'NPY_COMPLEX128'), 'complex128': (complex, 'theano_complex128', 'NPY_COMPLEX128'),
'complex64': (complex, 'theano_complex64', 'NPY_COMPLEX64') 'complex64': (complex, 'theano_complex64', 'NPY_COMPLEX64')
}[self.dtype] }[self.dtype]
except KeyError: except KeyError:
raise TypeError("Unsupported dtype for %s: %s" raise TypeError("Unsupported dtype for %s: %s"
% (self.__class__.__name__, self.dtype)) % (self.__class__.__name__, self.dtype))
def to_scalar_type(self): def to_scalar_type(self):
return scal.get_scalar_type(dtype=self.dtype) return scal.get_scalar_type(dtype=self.dtype)
...@@ -261,11 +260,11 @@ class TensorType(Type): ...@@ -261,11 +260,11 @@ class TensorType(Type):
and other.broadcastable == self.broadcastable and other.broadcastable == self.broadcastable
def convert_variable(self, var): def convert_variable(self, var):
if (type(self) == type(var.type) and if (type(self) == type(var.type) and # noqa
self.dtype == var.type.dtype and self.dtype == var.type.dtype and
self.ndim == var.type.ndim and self.ndim == var.type.ndim and
all(sb == ob or ob for sb, ob in zip(self.broadcastable, all(sb == ob or ob for sb, ob in zip(self.broadcastable,
var.type.broadcastable))): var.type.broadcastable))):
return theano.tensor.patternbroadcast(var, self.broadcastable) return theano.tensor.patternbroadcast(var, self.broadcastable)
@staticmethod @staticmethod
...@@ -351,7 +350,7 @@ class TensorType(Type): ...@@ -351,7 +350,7 @@ class TensorType(Type):
rtol = 1.0000000000000001e-05 rtol = 1.0000000000000001e-05
atol = 1e-8 atol = 1e-8
cmp_elemwise = (numpy.absolute(a - b) <= cmp_elemwise = (numpy.absolute(a - b) <=
(atol + rtol * numpy.absolute(b))) (atol + rtol * numpy.absolute(b)))
# Find places where both a and b have missing values. # Find places where both a and b have missing values.
both_missing = a_missing * numpy.isnan(b) both_missing = a_missing * numpy.isnan(b)
...@@ -361,9 +360,9 @@ class TensorType(Type): ...@@ -361,9 +360,9 @@ class TensorType(Type):
# cmp_elemwise is weird when we have inf and -inf. # cmp_elemwise is weird when we have inf and -inf.
# set it to False # set it to False
cmp_elemwise = numpy.where( cmp_elemwise = numpy.where(
both_inf & cmp_elemwise, both_inf & cmp_elemwise,
a == b, a == b,
cmp_elemwise) cmp_elemwise)
# check the sign of the inf # check the sign of the inf
both_inf = numpy.where(both_inf, (a == b), both_inf) both_inf = numpy.where(both_inf, (a == b), both_inf)
...@@ -383,7 +382,7 @@ class TensorType(Type): ...@@ -383,7 +382,7 @@ class TensorType(Type):
return hashtype(self) ^ hash(self.dtype) ^ hash(self.broadcastable) return hashtype(self) ^ hash(self.dtype) ^ hash(self.broadcastable)
ndim = property(lambda self: len(self.broadcastable), ndim = property(lambda self: len(self.broadcastable),
doc="number of dimensions") doc="number of dimensions")
"""Number of dimensions """Number of dimensions
This read-only property is the preferred way to get the number of This read-only property is the preferred way to get the number of
...@@ -407,10 +406,10 @@ class TensorType(Type): ...@@ -407,10 +406,10 @@ class TensorType(Type):
else: else:
b = self.broadcastable b = self.broadcastable
named_broadcastable = {(): 'scalar', named_broadcastable = {(): 'scalar',
(False,): 'vector', (False,): 'vector',
(False, True): 'col', (False, True): 'col',
(True, False): 'row', (True, False): 'row',
(False, False): 'matrix'} (False, False): 'matrix'}
if b in named_broadcastable: if b in named_broadcastable:
bcast = named_broadcastable[b] bcast = named_broadcastable[b]
else: else:
...@@ -422,7 +421,7 @@ class TensorType(Type): ...@@ -422,7 +421,7 @@ class TensorType(Type):
def __repr__(self): def __repr__(self):
return str(self) return str(self)
#"TensorType{%s, %s}" % (str(self.dtype), str(self.broadcastable)) # "TensorType{%s, %s}" % (str(self.dtype), str(self.broadcastable))
def c_declare(self, name, sub, check_input=True): def c_declare(self, name, sub, check_input=True):
"""Override `CLinkerType.c_declare` """ """Override `CLinkerType.c_declare` """
...@@ -636,13 +635,13 @@ def values_eq_approx_always_true(a, b): ...@@ -636,13 +635,13 @@ def values_eq_approx_always_true(a, b):
# Register TensorType C code for ViewOp. # Register TensorType C code for ViewOp.
theano.compile.register_view_op_c_code( theano.compile.register_view_op_c_code(
TensorType, TensorType,
""" """
Py_XDECREF(%(oname)s); Py_XDECREF(%(oname)s);
%(oname)s = %(iname)s; %(oname)s = %(iname)s;
Py_XINCREF(%(oname)s); Py_XINCREF(%(oname)s);
""", """,
version=1) version=1)
# Register TensorType C code for Shape Op. # Register TensorType C code for Shape Op.
...@@ -665,51 +664,51 @@ theano.compile.register_shape_c_code( ...@@ -665,51 +664,51 @@ theano.compile.register_shape_c_code(
# Register TensorType C code for ViewOp. # Register TensorType C code for ViewOp.
theano.compile.register_shape_i_c_code( theano.compile.register_shape_i_c_code(
TensorType, TensorType,
""" """
if(!%(oname)s) if(!%(oname)s)
%(oname)s=(PyArrayObject*)PyArray_EMPTY(0, NULL, NPY_INT64, 0); %(oname)s=(PyArrayObject*)PyArray_EMPTY(0, NULL, NPY_INT64, 0);
((npy_int64*)PyArray_DATA(%(oname)s))[0]=PyArray_DIMS(%(iname)s)[%(i)s]; ((npy_int64*)PyArray_DATA(%(oname)s))[0]=PyArray_DIMS(%(iname)s)[%(i)s];
""", """,
""" """
if (%(i)s>=PyArray_NDIM(%(iname)s)){ if (%(i)s>=PyArray_NDIM(%(iname)s)){
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Number of dimensions lower than expected"); "Number of dimensions lower than expected");
%(fail)s %(fail)s
} }
""", """,
version=3) version=3)
# Register TensorType C code for DeepCopyOp # Register TensorType C code for DeepCopyOp
theano.compile.register_deep_copy_op_c_code( theano.compile.register_deep_copy_op_c_code(
TensorType, TensorType,
""" """
int alloc = %(oname)s == NULL; int alloc = %(oname)s == NULL;
for(int i=0; !alloc && i<PyArray_NDIM(%(oname)s); i++) { for(int i=0; !alloc && i<PyArray_NDIM(%(oname)s); i++) {
if(PyArray_DIMS(%(iname)s)[i] != PyArray_DIMS(%(oname)s)[i]) { if(PyArray_DIMS(%(iname)s)[i] != PyArray_DIMS(%(oname)s)[i]) {
alloc = true; alloc = true;
break; break;
} }
}
if(alloc) {
Py_XDECREF(%(oname)s);
%(oname)s = (PyArrayObject*)PyArray_NewCopy(%(iname)s,
NPY_ANYORDER);
if (!%(oname)s)
{
PyErr_SetString(PyExc_ValueError,
"DeepCopyOp: the copy failed!");
%(fail)s;
} }
if(alloc) { } else {
Py_XDECREF(%(oname)s); if(PyArray_CopyInto(%(oname)s, %(iname)s)){
%(oname)s = (PyArrayObject*)PyArray_NewCopy(%(iname)s, PyErr_SetString(PyExc_ValueError,
NPY_ANYORDER); "DeepCopyOp: the copy failed into already allocated space!");
if (!%(oname)s) %(fail)s;
{
PyErr_SetString(PyExc_ValueError,
"DeepCopyOp: the copy failed!");
%(fail)s;
}
} else {
if(PyArray_CopyInto(%(oname)s, %(iname)s)){
PyErr_SetString(PyExc_ValueError,
"DeepCopyOp: the copy failed into already allocated space!");
%(fail)s;
}
} }
""", }
version=2) """,
version=2)
theano.compile.register_rebroadcast_c_code( theano.compile.register_rebroadcast_c_code(
...@@ -723,7 +722,7 @@ theano.compile.register_rebroadcast_c_code( ...@@ -723,7 +722,7 @@ theano.compile.register_rebroadcast_c_code(
%(fail)s %(fail)s
} }
""", """,
version=1) version=1)
theano.compile.register_specify_shape_c_code( theano.compile.register_specify_shape_c_code(
......
...@@ -57,17 +57,7 @@ whitelist_flake8 = [ ...@@ -57,17 +57,7 @@ whitelist_flake8 = [
"typed_list/tests/test_type.py", "typed_list/tests/test_type.py",
"typed_list/tests/test_opt.py", "typed_list/tests/test_opt.py",
"typed_list/tests/test_basic.py", "typed_list/tests/test_basic.py",
"tensor/blas_headers.py",
"tensor/type.py",
"tensor/fourier.py",
"tensor/__init__.py", "tensor/__init__.py",
"tensor/opt_uncanonicalize.py",
"tensor/blas.py",
"tensor/extra_ops.py",
"tensor/nlinalg.py",
"tensor/blas_c.py",
"tensor/elemwise_cgen.py",
"tensor/blas_scipy.py",
"tensor/tests/test_subtensor.py", "tensor/tests/test_subtensor.py",
"tensor/tests/test_utils.py", "tensor/tests/test_utils.py",
"tensor/tests/test_nlinalg.py", "tensor/tests/test_nlinalg.py",
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论