提交 6937f122 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Merge pull request #1524 from nouiz/fix_cycle

Fix cycle
...@@ -117,17 +117,17 @@ def test_ifelse(): ...@@ -117,17 +117,17 @@ def test_ifelse():
mode=Mode(linker=linker, optimizer='fast_run')) mode=Mode(linker=linker, optimizer='fast_run'))
try: try:
print "case 1" #print "case 1"
f(1, 'a', 'b') f(1, 'a', 'b')
assert False assert False
except NotImplementedOp.E: except NotImplementedOp.E:
pass pass
print "... passed" #print "... passed"
print "case 2" #print "case 2"
print f(0, 'a', 'b') #print f(0, 'a', 'b')
assert f(0, 'a', 'b') == 'b' assert f(0, 'a', 'b') == 'b'
print "... passed" #print "... passed"
def more_complex_test(): def more_complex_test():
......
from copy import copy
import unittest import unittest
import numpy import numpy
...@@ -45,6 +44,7 @@ class MyType(Type): ...@@ -45,6 +44,7 @@ class MyType(Type):
raise ValueError("Invalid value") raise ValueError("Invalid value")
return x return x
class MyOp(Op): class MyOp(Op):
def make_node(self, *inputs): def make_node(self, *inputs):
...@@ -81,14 +81,16 @@ class TestOp: ...@@ -81,14 +81,16 @@ class TestOp:
def test_sanity_0(self): def test_sanity_0(self):
r1, r2 = MyType(1)(), MyType(2)() r1, r2 = MyType(1)(), MyType(2)()
node = MyOp.make_node(r1, r2) node = MyOp.make_node(r1, r2)
assert [x for x in node.inputs] == [r1, r2] # Are the inputs what I provided? # Are the inputs what I provided?
assert [x.type for x in node.outputs] == [MyType(3)] # Are the outputs what I expect? assert [x for x in node.inputs] == [r1, r2]
# Are the outputs what I expect?
assert [x.type for x in node.outputs] == [MyType(3)]
assert node.outputs[0].owner is node and node.outputs[0].index == 0 assert node.outputs[0].owner is node and node.outputs[0].index == 0
# validate # validate
def test_validate(self): def test_validate(self):
try: try:
MyOp(Generic()(), MyType(1)()) # MyOp requires MyType instances MyOp(Generic()(), MyType(1)()) # MyOp requires MyType instances
raise Exception("Expected an exception") raise Exception("Expected an exception")
except Exception, e: except Exception, e:
if str(e) != "Error 1": if str(e) != "Error 1":
...@@ -100,6 +102,7 @@ class TestOp: ...@@ -100,6 +102,7 @@ class TestOp:
rval = f() rval = f()
assert rval == 'test Op no input' assert rval == 'test Op no input'
class TestMakeThunk(unittest.TestCase): class TestMakeThunk(unittest.TestCase):
def test_no_c_code(self): def test_no_c_code(self):
class IncOnePython(Op): class IncOnePython(Op):
...@@ -121,28 +124,25 @@ class TestMakeThunk(unittest.TestCase): ...@@ -121,28 +124,25 @@ class TestMakeThunk(unittest.TestCase):
output, = outputs output, = outputs
output[0] = input + 1 output[0] = input + 1
i = scalar.int32('i') i = scalar.int32('i')
o = IncOnePython()(i) o = IncOnePython()(i)
# Check that the c_code function is not implemented # Check that the c_code function is not implemented
self.assertRaises((NotImplementedError, utils.MethodNotDefined), self.assertRaises((NotImplementedError, utils.MethodNotDefined),
o.owner.op.c_code, o.owner.op.c_code,
o.owner, 'o', ['x'], 'z', {'fail': ''}) o.owner, 'o', ['x'], 'z', {'fail': ''})
storage_map = { storage_map = {i: [numpy.int32(3)],
i: [numpy.int32(3)], o: [None]}
o: [None]} compute_map = {i: [True],
compute_map = { o: [False]}
i: [True],
o: [False]}
thunk = o.owner.op.make_thunk(o.owner, storage_map, compute_map, thunk = o.owner.op.make_thunk(o.owner, storage_map, compute_map,
no_recycling=[]) no_recycling=[])
required = thunk() required = thunk()
# Check everything went OK # Check everything went OK
assert not required # We provided all inputs assert not required # We provided all inputs
assert compute_map[o][0] assert compute_map[o][0]
assert storage_map[o][0] == 4 assert storage_map[o][0] == 4
...@@ -166,28 +166,25 @@ class TestMakeThunk(unittest.TestCase): ...@@ -166,28 +166,25 @@ class TestMakeThunk(unittest.TestCase):
z, = outputs z, = outputs
return "%(z)s = %(x)s + 1;" % locals() return "%(z)s = %(x)s + 1;" % locals()
i = scalar.int32('i') i = scalar.int32('i')
o = IncOneC()(i) o = IncOneC()(i)
# Check that the perform function is not implemented # Check that the perform function is not implemented
self.assertRaises((NotImplementedError, utils.MethodNotDefined), self.assertRaises((NotImplementedError, utils.MethodNotDefined),
o.owner.op.perform, o.owner.op.perform,
o.owner, 0, [None]) o.owner, 0, [None])
storage_map = { storage_map = {i: [numpy.int32(3)],
i: [numpy.int32(3)], o: [None]}
o: [None]} compute_map = {i: [True],
compute_map = { o: [False]}
i: [True],
o: [False]}
thunk = o.owner.op.make_thunk(o.owner, storage_map, compute_map, thunk = o.owner.op.make_thunk(o.owner, storage_map, compute_map,
no_recycling=[]) no_recycling=[])
if theano.config.cxx: if theano.config.cxx:
required = thunk() required = thunk()
# Check everything went OK # Check everything went OK
assert not required # We provided all inputs assert not required # We provided all inputs
assert compute_map[o][0] assert compute_map[o][0]
assert storage_map[o][0] == 4 assert storage_map[o][0] == 4
else: else:
...@@ -201,30 +198,33 @@ def test_test_value_python_objects(): ...@@ -201,30 +198,33 @@ def test_test_value_python_objects():
def test_test_value_ndarray(): def test_test_value_ndarray():
x = numpy.zeros((5,5)) x = numpy.zeros((5, 5))
v = op.get_test_value(x) v = op.get_test_value(x)
assert (v == x).all() assert (v == x).all()
def test_test_value_constant(): def test_test_value_constant():
x = T.as_tensor_variable(numpy.zeros((5,5))) x = T.as_tensor_variable(numpy.zeros((5, 5)))
v = op.get_test_value(x) v = op.get_test_value(x)
assert numpy.all(v == numpy.zeros((5,5))) assert numpy.all(v == numpy.zeros((5, 5)))
def test_test_value_shared(): def test_test_value_shared():
x = shared(numpy.zeros((5,5))) x = shared(numpy.zeros((5, 5)))
v = op.get_test_value(x) v = op.get_test_value(x)
assert numpy.all(v == numpy.zeros((5,5))) assert numpy.all(v == numpy.zeros((5, 5)))
def test_test_value_op(): def test_test_value_op():
try: try:
prev_value = config.compute_test_value prev_value = config.compute_test_value
config.compute_test_value = 'raise' config.compute_test_value = 'raise'
x = T.log(numpy.ones((5,5))) x = T.log(numpy.ones((5, 5)))
v = op.get_test_value(x) v = op.get_test_value(x)
assert numpy.allclose(v, numpy.zeros((5,5))) assert numpy.allclose(v, numpy.zeros((5, 5)))
finally: finally:
config.compute_test_value = prev_value config.compute_test_value = prev_value
...@@ -244,11 +244,11 @@ def test_get_debug_values_no_debugger(): ...@@ -244,11 +244,11 @@ def test_get_debug_values_no_debugger():
finally: finally:
config.compute_test_value = prev_value config.compute_test_value = prev_value
def test_get_det_debug_values_ignore(): def test_get_det_debug_values_ignore():
"""get_debug_values should return [] when debugger is ignore """get_debug_values should return [] when debugger is ignore
and some values are missing """ and some values are missing """
prev_value = config.compute_test_value prev_value = config.compute_test_value
try: try:
config.compute_test_value = 'ignore' config.compute_test_value = 'ignore'
...@@ -267,21 +267,21 @@ def test_get_debug_values_success(): ...@@ -267,21 +267,21 @@ def test_get_debug_values_success():
(and the debugger is on)""" (and the debugger is on)"""
prev_value = config.compute_test_value prev_value = config.compute_test_value
for mode in [ 'ignore', 'warn', 'raise' ]: for mode in ['ignore', 'warn', 'raise']:
try: try:
config.compute_test_value = mode config.compute_test_value = mode
x = T.vector() x = T.vector()
x.tag.test_value = numpy.zeros((4,), dtype=config.floatX) x.tag.test_value = numpy.zeros((4,), dtype=config.floatX)
y = numpy.zeros((5,5)) y = numpy.zeros((5, 5))
iters = 0 iters = 0
for x_val, y_val in op.get_debug_values(x, y): for x_val, y_val in op.get_debug_values(x, y):
assert x_val.shape == (4,) assert x_val.shape == (4,)
assert y_val.shape == (5,5) assert y_val.shape == (5, 5)
iters += 1 iters += 1
...@@ -290,6 +290,7 @@ def test_get_debug_values_success(): ...@@ -290,6 +290,7 @@ def test_get_debug_values_success():
finally: finally:
config.compute_test_value = prev_value config.compute_test_value = prev_value
def test_get_debug_values_exc(): def test_get_debug_values_exc():
"""tests that get_debug_value raises an exception when """tests that get_debug_value raises an exception when
debugger is set to raise and a value is missing """ debugger is set to raise and a value is missing """
...@@ -317,13 +318,14 @@ def test_get_debug_values_exc(): ...@@ -317,13 +318,14 @@ def test_get_debug_values_exc():
finally: finally:
config.compute_test_value = prev_value config.compute_test_value = prev_value
def test_debug_error_message(): def test_debug_error_message():
"""tests that debug_error_message raises an """tests that debug_error_message raises an
exception when it should.""" exception when it should."""
prev_value = config.compute_test_value prev_value = config.compute_test_value
for mode in [ 'ignore', 'raise' ]: for mode in ['ignore', 'raise']:
try: try:
config.compute_test_value = mode config.compute_test_value = mode
......
...@@ -360,7 +360,7 @@ class TestEquilibrium(object): ...@@ -360,7 +360,7 @@ class TestEquilibrium(object):
x, y, z = map(MyVariable, 'xyz') x, y, z = map(MyVariable, 'xyz')
e = op3(op4(x, y)) e = op3(op4(x, y))
g = Env([x, y, z], [e]) g = Env([x, y, z], [e])
print g #print g
opt = EquilibriumOptimizer( opt = EquilibriumOptimizer(
[PatternSub((op1, 'x', 'y'), (op2, 'x', 'y')), [PatternSub((op1, 'x', 'y'), (op2, 'x', 'y')),
PatternSub((op4, 'x', 'y'), (op1, 'x', 'y')), PatternSub((op4, 'x', 'y'), (op1, 'x', 'y')),
...@@ -368,14 +368,14 @@ class TestEquilibrium(object): ...@@ -368,14 +368,14 @@ class TestEquilibrium(object):
], ],
max_use_ratio = 10) max_use_ratio = 10)
opt.optimize(g) opt.optimize(g)
print g #print g
assert str(g) == '[Op2(x, y)]' assert str(g) == '[Op2(x, y)]'
def test_2(self): def test_2(self):
x, y, z = map(MyVariable, 'xyz') x, y, z = map(MyVariable, 'xyz')
e = op1(op1(op3(x, y))) e = op1(op1(op3(x, y)))
g = Env([x, y, z], [e]) g = Env([x, y, z], [e])
print g #print g
opt = EquilibriumOptimizer( opt = EquilibriumOptimizer(
[PatternSub((op1, (op2, 'x', 'y')), (op4, 'x', 'y')), [PatternSub((op1, (op2, 'x', 'y')), (op4, 'x', 'y')),
PatternSub((op3, 'x', 'y'), (op4, 'x', 'y')), PatternSub((op3, 'x', 'y'), (op4, 'x', 'y')),
...@@ -391,7 +391,7 @@ class TestEquilibrium(object): ...@@ -391,7 +391,7 @@ class TestEquilibrium(object):
x, y, z = map(MyVariable, 'xyz') x, y, z = map(MyVariable, 'xyz')
e = op3(op4(x, y)) e = op3(op4(x, y))
g = Env([x, y, z], [e]) g = Env([x, y, z], [e])
print 'before', g #print 'before', g
# display pesky warnings along with stdout # display pesky warnings along with stdout
# also silence logger for 'theano.gof.opt' # also silence logger for 'theano.gof.opt'
_logger = logging.getLogger('theano.gof.opt') _logger = logging.getLogger('theano.gof.opt')
...@@ -407,5 +407,5 @@ class TestEquilibrium(object): ...@@ -407,5 +407,5 @@ class TestEquilibrium(object):
opt.optimize(g) opt.optimize(g)
finally: finally:
_logger.setLevel(oldlevel) _logger.setLevel(oldlevel)
print 'after', g #print 'after', g
assert str(g) == '[Op1(x, y)]' assert str(g) == '[Op1(x, y)]'
...@@ -422,8 +422,38 @@ static PyMemberDef CudaNdarray_members[] = ...@@ -422,8 +422,38 @@ static PyMemberDef CudaNdarray_members[] =
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
PyObject * CudaNdarray_CreateArrayObj(CudaNdarray * self) PyObject * CudaNdarray_CreateArrayObj(CudaNdarray * self, PyObject *args)
{ {
PyObject * dtype = NULL;
if (args && !PyArg_ParseTuple(args, "|O", &dtype))
return NULL;
if (dtype) {
PyArray_Descr* dtype2;
// PyArray_DescrConverter try to convert anything to a PyArray_Descr.
if(!PyArray_DescrConverter(dtype, &dtype2))
{
PyObject * str = PyObject_Repr(dtype);
PyErr_Format(PyExc_TypeError,
"CudaNdarray dtype parameter not understood: %s",
PyString_AsString(str)
);
Py_CLEAR(str);
return NULL;
}
int typeNum = dtype2->type_num;
Py_DECREF(dtype2);
if (typeNum != NPY_FLOAT32)
{
PyObject * str = PyObject_Repr(dtype);
PyErr_Format(PyExc_TypeError,
"CudaNdarray support only support float32 dtype, provided: %d",
typeNum
);
Py_CLEAR(str);
return NULL;
}
}
int verbose = 0; int verbose = 0;
if(self->nd>=0 && CudaNdarray_SIZE(self)==0){ if(self->nd>=0 && CudaNdarray_SIZE(self)==0){
npy_intp * npydims = (npy_intp*)malloc(self->nd * sizeof(npy_intp)); npy_intp * npydims = (npy_intp*)malloc(self->nd * sizeof(npy_intp));
...@@ -1291,7 +1321,7 @@ CudaNdarray_exp(CudaNdarray* self) ...@@ -1291,7 +1321,7 @@ CudaNdarray_exp(CudaNdarray* self)
static PyMethodDef CudaNdarray_methods[] = static PyMethodDef CudaNdarray_methods[] =
{ {
{"__array__", {"__array__",
(PyCFunction)CudaNdarray_CreateArrayObj, METH_NOARGS, (PyCFunction)CudaNdarray_CreateArrayObj, METH_VARARGS,
"Copy from the device to a numpy ndarray"}, "Copy from the device to a numpy ndarray"},
{"__copy__", {"__copy__",
(PyCFunction)CudaNdarray_View, METH_NOARGS, (PyCFunction)CudaNdarray_View, METH_NOARGS,
......
...@@ -473,7 +473,7 @@ DllExport int CudaNdarray_CopyFromCudaNdarray(CudaNdarray * self, ...@@ -473,7 +473,7 @@ DllExport int CudaNdarray_CopyFromCudaNdarray(CudaNdarray * self,
* Transfer the contents of CudaNdarray `self` to a new numpy ndarray. * Transfer the contents of CudaNdarray `self` to a new numpy ndarray.
*/ */
DllExport PyObject * DllExport PyObject *
CudaNdarray_CreateArrayObj(CudaNdarray * self); CudaNdarray_CreateArrayObj(CudaNdarray * self, PyObject *args = NULL);
DllExport PyObject * DllExport PyObject *
CudaNdarray_ZEROS(int n, int * dims); CudaNdarray_ZEROS(int n, int * dims);
......
...@@ -726,7 +726,7 @@ class TestConv2DGPU(unittest.TestCase): ...@@ -726,7 +726,7 @@ class TestConv2DGPU(unittest.TestCase):
featshp_logical = (featshp[0], featshp[1], featshp[2] * stride, featshp_logical = (featshp[0], featshp[1], featshp[2] * stride,
featshp[3] * stride) featshp[3] * stride)
kshp_rotated = (kshp[1], kshp[0], kshp[2], kshp[3]) kshp_rotated = (kshp[1], kshp[0], kshp[2], kshp[3])
print featshp, kshp_rotated, featshp_logical[1:], kshp[2:] #print featshp, kshp_rotated, featshp_logical[1:], kshp[2:]
image_estimate = tensor.nnet.conv2d(a, kernel_rotated, image_estimate = tensor.nnet.conv2d(a, kernel_rotated,
border_mode='full', border_mode='full',
image_shape=featshp, image_shape=featshp,
...@@ -735,7 +735,7 @@ class TestConv2DGPU(unittest.TestCase): ...@@ -735,7 +735,7 @@ class TestConv2DGPU(unittest.TestCase):
kshp_logical=kshp[2:]) kshp_logical=kshp[2:])
func = theano.function([a, A], image_estimate, mode=theano_mode) func = theano.function([a, A], image_estimate, mode=theano_mode)
theano.printing.debugprint(func,) #theano.printing.debugprint(func,)
assert any([isinstance(node.op, theano.sandbox.cuda.blas.GpuConv) assert any([isinstance(node.op, theano.sandbox.cuda.blas.GpuConv)
for node in func.maker.fgraph.toposort()]) for node in func.maker.fgraph.toposort()])
......
...@@ -38,6 +38,17 @@ def test_host_to_device(): ...@@ -38,6 +38,17 @@ def test_host_to_device():
c = numpy.asarray(b) c = numpy.asarray(b)
assert numpy.all(a == c) assert numpy.all(a == c)
# test with float32 dtype
d = numpy.asarray(b, dtype='float32')
assert numpy.all(a == d)
# test with not float32 dtype
try:
numpy.asarray(b, dtype='int8')
assert False
except TypeError:
pass
def test_add_iadd_idiv(): def test_add_iadd_idiv():
for shapes in ( for shapes in (
......
...@@ -3425,6 +3425,10 @@ class Join(Op): ...@@ -3425,6 +3425,10 @@ class Join(Op):
bcastable = [False] * len( bcastable = [False] * len(
as_tensor_variable_args[0].type.broadcastable) as_tensor_variable_args[0].type.broadcastable)
if not python_all([x.ndim == len(bcastable)
for x in as_tensor_variable_args[1:]]):
raise TypeError("Join() can only join tensor with the same number of dimensions.")
inputs = [as_tensor_variable(axis)] + list(as_tensor_variable_args) inputs = [as_tensor_variable(axis)] + list(as_tensor_variable_args)
if inputs[0].type not in int_types: if inputs[0].type not in int_types:
raise TypeError('Axis could not be cast to an integer type', raise TypeError('Axis could not be cast to an integer type',
......
...@@ -395,9 +395,9 @@ def local_dimshuffle_lift(node): ...@@ -395,9 +395,9 @@ def local_dimshuffle_lift(node):
inode = input.owner inode = input.owner
if inode and isinstance(inode.op, Elemwise) and (len(input.clients) == 1): if inode and isinstance(inode.op, Elemwise) and (len(input.clients) == 1):
# Don't use make_node to have tag.test_value set. # Don't use make_node to have tag.test_value set.
ret = inode.op(*[DimShuffle(input.type.broadcastable, ret = inode.op(*[DimShuffle(inp.type.broadcastable,
op.new_order, op.new_order,
op.inplace)(input) for input in op.inplace)(inp) for inp in
inode.inputs], **dict(return_list=True)) inode.inputs], **dict(return_list=True))
return ret return ret
if inode and isinstance(inode.op, DimShuffle): if inode and isinstance(inode.op, DimShuffle):
...@@ -943,12 +943,12 @@ class ShapeFeature(object): ...@@ -943,12 +943,12 @@ class ShapeFeature(object):
else: else:
new_shape.append(s_j) new_shape.append(s_j)
assert all([not hasattr(r.type, "broadcastable") or assert all([not hasattr(r.type, "broadcastable") or
not r.type.broadcastable[i] or not r.type.broadcastable[idx] or
# The two following comparison are a speed optimization # The two following comparison are a speed optimization
# But we never timed this speed optimization! # But we never timed this speed optimization!
self.lscalar_one.equals(new_shape[i]) or self.lscalar_one.equals(new_shape[idx]) or
self.lscalar_one.equals(T.extract_constant(new_shape[i])) self.lscalar_one.equals(T.extract_constant(new_shape[idx]))
for i in range(r.ndim)]) for idx in range(r.ndim)])
self.shape_of[r] = tuple(new_shape) self.shape_of[r] = tuple(new_shape)
for sv in self.shape_of[r]: for sv in self.shape_of[r]:
self.shape_of_reverse_index.setdefault(sv, set()).add(r) self.shape_of_reverse_index.setdefault(sv, set()).add(r)
...@@ -1041,13 +1041,13 @@ class ShapeFeature(object): ...@@ -1041,13 +1041,13 @@ class ShapeFeature(object):
# Ensure shapes are in 'int64'. This is to make sure the assert # Ensure shapes are in 'int64'. This is to make sure the assert
# found in the `local_useless_subtensor` optimization does not fail. # found in the `local_useless_subtensor` optimization does not fail.
new_shape = []
for sh_idx, sh in enumerate(o_shapes): for sh_idx, sh in enumerate(o_shapes):
if sh is None: if sh is None:
continue continue
if not isinstance(sh, (list, tuple)): if not isinstance(sh, (list, tuple)):
raise ValueError("infer_shape of %s didn't return a list of" raise ValueError("infer_shape of %s didn't return a list of"
" list. It returned '%s'" % (str(node), str(o_shapes))) " list. It returned '%s'" % (str(node), str(o_shapes)))
new_shape = []
for i, d in enumerate(sh): for i, d in enumerate(sh):
# Note: we ignore any shape element that is not typed (i.e., # Note: we ignore any shape element that is not typed (i.e.,
# does not have a 'dtype' attribute). This means there may # does not have a 'dtype' attribute). This means there may
...@@ -1064,7 +1064,6 @@ class ShapeFeature(object): ...@@ -1064,7 +1064,6 @@ class ShapeFeature(object):
# 'int64'. # 'int64'.
new_shape += sh[len(new_shape):] new_shape += sh[len(new_shape):]
o_shapes[sh_idx] = tuple(new_shape) o_shapes[sh_idx] = tuple(new_shape)
new_shape = []
for r, s in izip(node.outputs, o_shapes): for r, s in izip(node.outputs, o_shapes):
self.set_shape(r, s) self.set_shape(r, s)
...@@ -1091,6 +1090,23 @@ class ShapeFeature(object): ...@@ -1091,6 +1090,23 @@ class ShapeFeature(object):
# At that point, node is no longer a client of r, but of new_r # At that point, node is no longer a client of r, but of new_r
for (shpnode, idx) in (r.clients + [(node, i)]): for (shpnode, idx) in (r.clients + [(node, i)]):
if isinstance(getattr(shpnode, 'op', None), Shape_i): if isinstance(getattr(shpnode, 'op', None), Shape_i):
idx = shpnode.op.i
repl = self.shape_of[new_r][idx]
if repl.owner is shpnode:
# This mean the replacement shape object is
# exactly the same as the current shape object. So
# no need for replacement. This happen for example
# with the InputToGpuOptimizer optimizer.
continue
if (repl.owner and
repl.owner.inputs[0] is shpnode.inputs[0] and
isinstance(repl.owner.op, Shape_i) and
repl.owner.op.i == shpnode.op.i):
# The replacement is a shape_i of the same
# input. So no need to do this equivalent
# replacement.
continue
self.scheduled[shpnode] = new_r self.scheduled[shpnode] = new_r
# In case 2, if r is a variable that we've scheduled for shape update, # In case 2, if r is a variable that we've scheduled for shape update,
# then we should cancel it. # then we should cancel it.
...@@ -1228,6 +1244,9 @@ def local_track_shape_i(node): ...@@ -1228,6 +1244,9 @@ def local_track_shape_i(node):
except AttributeError: except AttributeError:
return return
if node in shape_feature.scheduled: if node in shape_feature.scheduled:
# Don't unschedule node as it could be reinserted in the
# fgraph as we don't change it in the shapefeature internal
# structure.
assert isinstance(node.op, Shape_i) assert isinstance(node.op, Shape_i)
replacement = shape_feature.scheduled[node] replacement = shape_feature.scheduled[node]
return [shape_feature.shape_of[replacement][node.op.i]] return [shape_feature.shape_of[replacement][node.op.i]]
...@@ -2271,7 +2290,6 @@ def local_join_1(node): ...@@ -2271,7 +2290,6 @@ def local_join_1(node):
""" """
if not isinstance(node.op, T.Join): if not isinstance(node.op, T.Join):
return return
axis = node.inputs[0]
tensors = node.inputs[1:] tensors = node.inputs[1:]
if len(tensors) == 1: if len(tensors) == 1:
return [tensors[0]] return [tensors[0]]
......
...@@ -3317,6 +3317,12 @@ class T_Join_and_Split(unittest.TestCase): ...@@ -3317,6 +3317,12 @@ class T_Join_and_Split(unittest.TestCase):
numpy.concatenate([T_shared.get_value(), numpy.concatenate([T_shared.get_value(),
T_shared.get_value()])) T_shared.get_value()]))
def test_mixed_ndim_error(self):
rng = numpy.random.RandomState(seed=utt.fetch_seed())
v = self.shared(rng.rand(4).astype(self.floatX))
m = self.shared(rng.rand(4, 4).astype(self.floatX))
self.assertRaises(TypeError, self.join_op(), 0, v, m)
class test_comparison(unittest.TestCase): class test_comparison(unittest.TestCase):
"""Test <, >, <=, >=, == and != """Test <, >, <=, >=, == and !=
...@@ -5694,7 +5700,7 @@ class T_get_scalar_constant_value(unittest.TestCase): ...@@ -5694,7 +5700,7 @@ class T_get_scalar_constant_value(unittest.TestCase):
# For now get_scalar_constant_value goes through only MakeVector and Join of # For now get_scalar_constant_value goes through only MakeVector and Join of
# scalars. # scalars.
v = tensor.ivector() v = tensor.ivector()
a = tensor.stack(v, 2, 3) a = tensor.stack(v, [2], [3])
self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[0]) self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[0])
self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[1]) self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[1])
self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[2]) self.assertRaises(tensor.NotScalarConstantError, get_scalar_constant_value, a[2])
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论