def _testSS( self, op, array1=numpy.array([[1.0, 0], [3, 0], [0, 6]]), array2=numpy.asarray([[0, 2.0], [0, 4], [5, 0]]) ): for mtype in _mtypes: a = mtype(array1) aR = as_sparse_variable(a) self.assertFalse(aR.data is a) self.assertTrue(_is_sparse(a)) self.assertTrue(_is_sparse_variable(aR)) b = mtype(array2) bR = as_sparse_variable(b) self.assertFalse(bR.data is b) self.assertTrue(_is_sparse(b)) self.assertTrue(_is_sparse_variable(bR)) apb = op(aR, bR) self.assertTrue(_is_sparse_variable(apb)) self.assertTrue(apb.type.dtype == aR.type.dtype, apb.type.dtype) self.assertTrue(apb.type.dtype == bR.type.dtype, apb.type.dtype) self.assertTrue(apb.type.format == aR.type.format, apb.type.format) self.assertTrue(apb.type.format == bR.type.format, apb.type.format) val = eval_outputs([apb]) self.assertTrue(val.shape == (3, 2)) if op is add: self.assertTrue(numpy.all(val.todense() == (a + b).todense())) ans = numpy.array([[1.0, 2], [3, 4], [5, 6]]) self.assertTrue(numpy.all(val.todense() == ans)) verify_grad_sparse(op, [a, b], structured=False) elif op is mul: self.assertTrue(numpy.all(val.todense() == (a.multiply(b)).todense())) ans = numpy.array([[1, 0], [9, 0], [0, 36]]) self.assertTrue(numpy.all(val.todense() == ans))
def _testSD( self, op, array1=numpy.array([[1.0, 0], [3, 0], [0, 6]]), array2=numpy.asarray([[0, 2.0], [0, 4], [5, 0]]) ): for mtype in _mtypes: a = numpy.array(array1) aR = tensor.as_tensor_variable(a) self.assertFalse(aR.data is a) # constants are copied self.assertTrue(_is_dense(a)) self.assertTrue(_is_dense_variable(aR)) b = mtype(array2) bR = as_sparse_variable(b) self.assertFalse(bR.data is b) # constants are copied self.assertTrue(_is_sparse(b)) self.assertTrue(_is_sparse_variable(bR)) apb = op(aR, bR) self.assertTrue(apb.type.dtype == aR.type.dtype, apb.type.dtype) self.assertTrue(apb.type.dtype == bR.type.dtype, apb.type.dtype) val = eval_outputs([apb]) self.assertTrue(val.shape == (3, 2)) if op is add: self.assertTrue(_is_dense_variable(apb)) self.assertTrue(numpy.all(val == (a + b))) ans = numpy.array([[1.0, 2], [3, 4], [5, 6]]) self.assertTrue(numpy.all(val == ans)) elif op is mul: self.assertTrue(_is_sparse_variable(apb)) self.assertTrue(numpy.all(val.todense() == (b.multiply(a)))) self.assertTrue(numpy.all(val.todense() == numpy.array([[1, 0], [9, 0], [0, 36]])))
def __init__(self, alpha=None, W=None, tau=None,lam=None,sparse=False, *args, **kwargs): self.alpha = tt.as_tensor_variable(alpha) self.tau = tt.as_tensor_variable(tau) self.sparse = sparse self.D = D = W.sum(axis=0) self.D_W = np.diag(D) self.n = self.D.shape[0] self.median = self.mode = self.mean = np.zeros(self.n) super(CAR, self).__init__(*args, **kwargs) # eigenvalues of D^−1/2 * W * D^−1/2 if lam is None: Dinv_sqrt = np.diag(1 / np.sqrt(D)) DWD = np.matmul(np.matmul(Dinv_sqrt, W), Dinv_sqrt) self.lam = eigvalsh(DWD) else: self.lam = lam # sparse representation of W if sparse: w_sparse = csr_matrix(W) self.W = as_sparse_variable(w_sparse) else: self.W = shared(W) self.D_tt = tt.as_tensor_variable(D) self.D = D
def _testDS(self, op, array1=numpy.array([[1., 0], [3, 0], [0, 6]]), array2=numpy.asarray([[0, 2.], [0, 4], [5, 0]])): for mtype in _mtypes: a = mtype(array1) aR = as_sparse_variable(a) self.assertFalse(aR.data is a) self.assertTrue(_is_sparse(a)) self.assertTrue(_is_sparse_variable(aR)) b = numpy.asarray(array2) bR = tensor.as_tensor_variable(b) self.assertFalse(bR.data is b) self.assertTrue(_is_dense(b)) self.assertTrue(_is_dense_variable(bR)) apb = op(aR, bR) self.assertTrue(apb.type.dtype == aR.type.dtype, apb.type.dtype) self.assertTrue(apb.type.dtype == bR.type.dtype, apb.type.dtype) val = eval_outputs([apb]) self.assertTrue(val.shape == (3, 2)) if op is add: self.assertTrue(_is_dense_variable(apb)) self.assertTrue(numpy.all(val == (a + b))) ans = numpy.array([[1., 2], [3, 4], [5, 6]]) self.assertTrue(numpy.all(val == ans)) elif op is mul: self.assertTrue(_is_sparse_variable(apb)) ans = numpy.array([[1, 0], [9, 0], [0, 36]]) self.assertTrue(numpy.all(val.todense() == (a.multiply(b)))) self.assertTrue(numpy.all(val.todense() == ans))
def make_sparse(value, dtype=None): if dtype is None: dtype = floatx() assert hasattr(value, 'tocoo') _assert_sparse_module() var = th_sparse_module.as_sparse_variable(value) return var
def make_node(self, A, b): A = ts.as_sparse_variable(A) b = ts.as_sparse_or_tensor_variable(b) assert A.ndim == 2 assert b.ndim in [1, 2] x = tt.tensor(dtype=b.dtype) return Apply(self, [A, b], [x])
def variable(value, dtype=_FLOATX, name=None): '''Instantiate a tensor variable. ''' if hasattr(value, 'tocoo'): _assert_sparse_module() return th_sparse_module.as_sparse_variable(value) else: value = np.asarray(value, dtype=dtype) return theano.shared(value=value, name=name, strict=False)
def test_transpose_csr(self): a = as_sparse_variable(scipy.sparse.csr_matrix(scipy.sparse.eye(5, 3))) self.assertTrue(a.data.shape == (5, 3)) self.assertTrue(a.type.dtype == "float64") self.assertTrue(a.type.format == "csr") ta = transpose(a) self.assertTrue(ta.type.dtype == "float64", ta.type.dtype) self.assertTrue(ta.type.format == "csc", ta.type.format) vta = eval_outputs([ta]) self.assertTrue(vta.shape == (3, 5))
def test_transpose_csr(self): a = as_sparse_variable(scipy.sparse.csr_matrix(scipy.sparse.eye(5, 3))) self.assertTrue(a.data.shape == (5, 3)) self.assertTrue(a.type.dtype == 'float64') self.assertTrue(a.type.format == 'csr') ta = transpose(a) self.assertTrue(ta.type.dtype == 'float64', ta.type.dtype) self.assertTrue(ta.type.format == 'csc', ta.type.format) vta = eval_outputs([ta]) self.assertTrue(vta.shape == (3, 5))
def test_transpose_csc(self): sp = scipy.sparse.csc_matrix(scipy.sparse.eye(5, 3)) a = as_sparse_variable(sp) self.assertFalse(a.data is sp) self.assertTrue(a.data.shape == (5, 3)) self.assertTrue(a.type.dtype == 'float64', a.type.dtype) self.assertTrue(a.type.format == 'csc', a.type.format) ta = transpose(a) self.assertTrue(ta.type.dtype == 'float64', ta.type.dtype) self.assertTrue(ta.type.format == 'csr', ta.type.format) vta = eval_outputs([ta]) self.assertTrue(vta.shape == (3, 5))
def make_node(self, x): x = as_sparse_variable(x) return gof.Apply(self, [x], [x.type()])
def test_upcast(self): array1 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype="float32") array2 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype="int32") array3 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype="int8") # AddSS and MulSS for mtype in _mtypes: a = mtype(array1) aR = as_sparse_variable(a) b = mtype(array2) bR = as_sparse_variable(b) c = mtype(array3) cR = as_sparse_variable(c) # Ops that do not upcast self.assertRaises(NotImplementedError, add, aR, bR) self.assertRaises(NotImplementedError, add, bR, aR) self.assertRaises(NotImplementedError, add, bR, cR) self.assertRaises(NotImplementedError, add, cR, bR) self.assertRaises(NotImplementedError, add, aR, cR) self.assertRaises(NotImplementedError, add, cR, aR) self.assertRaises(NotImplementedError, mul, aR, bR) self.assertRaises(NotImplementedError, mul, bR, aR) self.assertRaises(NotImplementedError, mul, bR, cR) self.assertRaises(NotImplementedError, mul, cR, bR) self.assertRaises(NotImplementedError, mul, aR, cR) self.assertRaises(NotImplementedError, mul, cR, aR) # AddSD and MulSD for mtype in _mtypes: a = mtype(array1) a_sv = as_sparse_variable(a) a_dv = tensor.as_tensor_variable(array1) b = mtype(array2) b_sv = as_sparse_variable(b) b_dv = tensor.as_tensor_variable(array2) c = mtype(array3) c_sv = as_sparse_variable(c) c_dv = tensor.as_tensor_variable(array3) # add does not upcast self.assertRaises(NotImplementedError, add, a_sv, b_dv) self.assertRaises(NotImplementedError, add, b_sv, a_dv) self.assertRaises(NotImplementedError, add, b_sv, c_dv) self.assertRaises(NotImplementedError, add, c_sv, b_dv) self.assertRaises(NotImplementedError, add, a_sv, c_dv) self.assertRaises(NotImplementedError, add, c_sv, a_dv) # mul may upcast the dense input if needed if config.cast_policy in ("custom", "numpy") or ( config.cast_policy == "numpy+floatX" and config.floatX == "float64" ): # The result should be a float64 (not implemented). self.assertRaises(NotImplementedError, mul, a_sv, b_dv) elif config.cast_policy == "numpy+floatX" and config.floatX == "float32": # The result should be a float32. assert mul(a_sv, b_dv).dtype == "float32" else: raise NotImplementedError() self.assertRaises(NotImplementedError, mul, b_sv, a_dv) assert mul(b_sv, c_dv).dtype == "int32" self.assertRaises(NotImplementedError, mul, c_sv, b_dv) assert mul(a_sv, c_dv).dtype == "float32" self.assertRaises(NotImplementedError, mul, c_sv, a_dv)
def solve(self, u=None, vT=None, b=None, u_guess=None, vT_guess=None, b_guess=None, u_mu=0.0, u_sig=0.01, vT_mu=1.0, vT_sig=0.3, vT_rho=3.e-5, b_mu=1.0, b_sig=0.1, niter_adam=100, niter_linear=100, temp=1.e3, **kwargs): """ """ if not self._loaded: raise RuntimeError("Please load or generate a dataset first.") # Data covariance self.F_CInv = np.ones_like(self.F) / self.ferr ** 2 self.F_lndet = np.sum(np.log(2 * np.pi * self.F_CInv.reshape(-1))) # Prior on `u` self.u_cinv = np.ones(self.N - 1) / u_sig ** 2 self.u_mu = np.ones(self.N - 1) * u_mu self.u_lndet = np.sum(np.log(2 * np.pi * self.u_cinv)) # Gaussian process prior on `vT` self.vT_mu = (np.ones(self.Kp) * vT_mu).reshape(1, -1) if vT_rho > 0.0: kernel = celerite.terms.Matern32Term(np.log(vT_sig), np.log(vT_rho)) gp = celerite.GP(kernel) vT_C = gp.get_matrix(self.lam_padded) cho_C = cho_factor(vT_C) self.vT_CInv = cho_solve(cho_C, np.eye(self.Kp)) self.vT_CInvmu = cho_solve(cho_C, self.vT_mu.reshape(-1)) self.vT_lndet = -2 * np.sum(np.log(2 * np.pi * np.diag(cho_C[0]))) else: self.vT_CInv = np.ones(self.Kp) / vT_sig ** 2 self.vT_CInvmu = (self.vT_CInv * self.vT_mu) self.vT_lndet = np.sum(np.log(2 * np.pi * self.vT_CInv)) self.vT_CInv = np.diag(self.vT_CInv) # Prior on `b` self.b_cinv = np.ones(self.M) / b_sig ** 2 self.b_mu = np.ones(self.M) * b_mu self.b_lndet = self.M * np.log(2 * np.pi / b_sig ** 2) # Simple linear solves if (u is not None) and (vT is not None): self.u = u self.vT = vT self._compute_b() elif (u is not None) and (b is not None): self.u = u self.b = b self._compute_vT() elif (vT is not None) and (b is not None): self.b = b self.vT = vT self._compute_u() # Non-linear else: # Get our guesses going if u is not None: self.u = u var_names = ["vT", "b"] if vT_guess is None and b_guess is None: self.b = np.ones(self.M) self._compute_vT(T=temp) elif vT_guess is not None: self.vT = vT_guess self._compute_b(T=temp) elif b_guess is not None: self.b = b_guess self._compute_vT(T=temp) else: raise ValueError("Unexpected branch!") elif vT is not None: self.vT = vT var_names = ["u", "b"] if u_guess is None and b_guess is None: self.b = np.ones(self.M) self._compute_u(T=temp) elif u_guess is not None: self.u = u_guess self._compute_b(T=temp) elif b_guess is not None: self.b = b_guess self._compute_u(T=temp) else: raise ValueError("Unexpected branch!") elif b is not None: self.b = b var_names = ["u", "vT"] if u_guess is None and vT_guess is None: self.u = self.u_mu + u_sig * np.random.randn(self.N - 1) self._compute_vT(T=temp) elif u_guess is not None: self.u = u_guess self._compute_vT(T=temp) elif vT_guess is not None: self.vT = vT_guess self._compute_u(T=temp) else: raise ValueError("") else: var_names = ["u", "vT", "b"] if vT_guess is None and b_guess is None and u_guess is None: self.b = np.ones(self.M) self.u = self.u_mu + u_sig * np.random.randn(self.N - 1) self._compute_vT(T=temp) elif u_guess is not None: self.u = u_guess if vT_guess is None and b_guess is None: self.b = np.ones(self.M) self._compute_vT(T=temp) elif vT_guess is not None: self.vT = vT_guess self._compute_b(T=temp) elif b_guess is not None: self.b = b_guess self._compute_vT(T=temp) else: raise ValueError("Unexpected branch!") elif vT_guess is not None: self.vT = vT_guess if b_guess is None: self.b = np.ones(self.M) self._compute_u(T=temp) else: self.b = b_guess self._compute_u(T=temp) elif b_guess is not None: self.b = b_guess self.u = self.u_mu + u_sig * np.random.randn(self.N - 1) self._compute_vT(T=temp) else: raise ValueError("Unexpected branch!") # Initialize the variables to the guesses vars = [] if "u" in var_names: u = theano.shared(self.u) vars += [u] else: u = tt.as_tensor_variable(self.u) if "vT" in var_names: vT = theano.shared(self.vT) vars += [vT] else: vT = tt.as_tensor_variable(self.vT) # Compute the model D = ts.as_sparse_variable(self.D) a = tt.reshape(tt.dot(tt.reshape( tt.concatenate([[1.0], u]), (-1, 1)), tt.reshape(vT, (1, -1))), (-1,)) self.map[1:, :] = u b = self.map.flux(theta=self.theta) B = tt.reshape(b, (-1, 1)) M = tt.reshape(ts.dot(D, a), (self.M, -1)) / B # Compute the likelihood r = tt.reshape(self.F - M, (-1,)) cov = tt.reshape(self.F_CInv, (-1,)) lnlike = -0.5 * (tt.sum(r ** 2 * cov) + self.F_lndet) # Compute the prior lnprior = -0.5 * (tt.sum((u - self.u_mu) ** 2 * self.u_cinv) + self.u_lndet) lnprior += -0.5 * (tt.dot(tt.dot(tt.reshape((vT - self.vT_mu), (1, -1)), self.vT_CInv), tt.reshape((vT - self.vT_mu), (-1, 1)))[0, 0] + self.vT_lndet) # The full loss loss = -(lnlike + lnprior) best_loss = loss.eval() best_u = u.eval() best_vT = vT.eval() best_b = b.eval() lnlike_val = np.zeros(niter_adam + 1) lnprior_val = np.zeros(niter_adam + 1) lnlike_val[0] = lnlike.eval() lnprior_val[0] = lnprior.eval() # Optimize upd = Adam(loss, vars, **kwargs) train = theano.function([], [u, vT, b, loss, lnlike, lnprior], updates=upd) for n in tqdm(1 + np.arange(niter_adam)): u_val, vT_val, b_val, loss_val, lnlike_val[n], lnprior_val[n] = train() if (loss_val < best_loss): best_loss = loss_val best_u = u_val best_vT = vT_val best_b = b_val # We're done! self.u = best_u self.vT = best_vT self.b = best_b self.lnlike = lnlike_val self.lnprior = lnprior_val self._solved = True
def solve(self, y1=None, s=None, baseline=None, y1_guess=None, s_guess=None, baseline_guess=None, niter=100, T=1.0, dlogT=-0.25, optimizer="NAdam", dcf=10.0, quiet=False, **kwargs): """Solve the Doppler imaging problem. Returns: ``(loss, cho_y1, cho_s)``, a tuple containing the array of loss values during the optimization and the Cholesky factorization of the covariance matrices of ``y1`` and ``s``, if available (otherwise the latter two are set to ``None``.) """ # Check the optimizer is valid if optimizer.lower() == "nadam": optimizer = NAdam elif optimizer.lower() == "adam": optimizer = Adam else: raise ValueError("Invalid optimizer.") # Figure out what to solve for known = [] if s is not None: known += ["s"] if y1 is not None: known += ["y1"] if ("y1" in known) and ("s" in known): # Nothing to do here but ingest the values! self.y1 = y1 self.s = s return self.loss(), None, None elif "y1" in known: # Easy: it's a linear problem self.y1 = y1 cho_s = self.compute_s() return self.loss(), None, cho_s else: if ("s" in known) and (baseline is not None): # Still a linear problem! self.s = s cho_y1 = self.compute_y1(baseline=baseline) return self.loss(), cho_y1, None else: # Non-linear. Let's use (N)Adam. if "s" in known: # We know `s` and need to solve for # `y1` w/o any baseline knowledge. s_guess = s else: # We know *nothing*! # Estimate `v^T` from the deconvolved mean spectrum if s_guess is None: fmean = np.mean(self.F, axis=0) fmean -= np.mean(fmean) diagonals = np.tile(self.kT()[0].reshape(-1, 1), self.K) offsets = np.arange(self.W) A = diags(diagonals, offsets, (self.K, self.Kp), format="csr") LInv = (dcf**2 * self.ferr**2 / self.s_sig**2 * np.eye(A.shape[1])) s_guess = 1.0 + np.linalg.solve( A.T.dot(A).toarray() + LInv, A.T.dot(fmean)) # Save this for later self.s_deconv = s_guess # Estimate `y1` w/o baseline knowledge # If `baseline_guess` is `None`, this is done via # a Taylor expansion; see ``compute_y1()``. if y1_guess is None: self.s = s_guess self.compute_y1(T=T, baseline=baseline_guess) y1_guess = self.y1 # Initialize the variables self.y1 = y1_guess self.s = s_guess # Tempering params if T > 1.0: T_arr = 10**np.arange(np.log10(T), 0, dlogT) T_arr = np.append(T_arr, [1.0]) niter_bilin = len(T_arr) else: T_arr = [1.0] niter_bilin = 1 # Loss array loss_val = np.zeros(niter_bilin + niter + 1) loss_val[0] = self.loss() # Iterative bi-linear solve if niter_bilin > 0: if not quiet: print("Running bi-linear solver...") best_loss = loss_val[0] best_y1 = self.y1 best_s = self.s for n in tqdm(range(niter_bilin), disable=quiet): # Compute `y1` using the previous baseline self.compute_y1(T=T_arr[n], baseline=self.baseline()) # Compute `s` using the current `y1` if "s" not in known: self.compute_s(T=T_arr[n]) loss_val[n + 1] = self.loss() if loss_val[n + 1] < best_loss: best_loss = loss_val[n + 1] best_y1 = self.y1 best_s = self.s self.y1 = best_y1 self.s = best_s # Non-linear solve if niter > 0: # Theano nonlienar solve. Variables: y1 = theano.shared(self.y1) s = theano.shared(self.s) if "s" in known: theano_vars = [y1] else: theano_vars = [y1, s] # Compute the model D = ts.as_sparse_variable(self.D()) a = tt.reshape( tt.dot( tt.reshape(tt.concatenate([[1.0], y1]), (-1, 1)), tt.reshape(s, (1, -1)), ), (-1, ), ) b = tt.dot( self._map.design_matrix(theta=self.theta), tt.reshape(tt.concatenate([[1.0], y1]), (-1, 1)), ) B = tt.reshape(b, (-1, 1)) M = tt.reshape(ts.dot(D, a), (self.M, -1)) / B # Compute the loss r = tt.reshape(self.F - M, (-1, )) cov = tt.reshape(self._F_CInv, (-1, )) lnlike = -0.5 * tt.sum(r**2 * cov) lnprior = (-0.5 * tt.sum( (y1 - self.y1_mu)**2 / self.y1_sig**2) + -0.5 * tt.sum( (b - self.baseline_mu)**2 / self.baseline_sig**2) + -0.5 * tt.dot( tt.dot( tt.reshape((s - self.s_mu), (1, -1)), self._s_CInv, ), tt.reshape((s - self.s_mu), (-1, 1)), )[0, 0]) loss = -(lnlike + lnprior) best_loss = loss.eval() best_y1 = y1.eval() best_s = s.eval() if not quiet: print("Running non-linear solver...") upd = optimizer(loss, theano_vars, **kwargs) train = theano.function([], [y1, s, loss], updates=upd) for n in tqdm(1 + niter_bilin + np.arange(niter), disable=quiet): y1_val, s_val, loss_val[n] = train() if loss_val[n] < best_loss: best_loss = loss_val[n] best_y1 = y1_val best_s = s_val # We are done! self.y1 = best_y1 self.s = best_s # Estimate the covariance of `y1` conditioned on `s` # and the covariance of `s` conditioned on `y1`. # Note that the covariance of `y1` is computed from # the linearization that allows us to simultaneously # solve for the baseline. y1_curr = np.array(self.y1) cho_y1 = self.compute_y1() self.y1 = y1_curr if "s" not in known: s_curr = np.array(self.s) cho_s = self.compute_s() self.s = s_curr else: cho_s = None return loss_val, cho_y1, cho_s
def test_upcast(self): array1 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype='float32') array2 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype='int32') array3 = numpy.array([[1, 0], [3, 0], [0, 6]], dtype='int8') # AddSS and MulSS for mtype in _mtypes: a = mtype(array1) aR = as_sparse_variable(a) b = mtype(array2) bR = as_sparse_variable(b) c = mtype(array3) cR = as_sparse_variable(c) # Ops that do not upcast self.assertRaises(NotImplementedError, add, aR, bR) self.assertRaises(NotImplementedError, add, bR, aR) self.assertRaises(NotImplementedError, add, bR, cR) self.assertRaises(NotImplementedError, add, cR, bR) self.assertRaises(NotImplementedError, add, aR, cR) self.assertRaises(NotImplementedError, add, cR, aR) self.assertRaises(NotImplementedError, mul, aR, bR) self.assertRaises(NotImplementedError, mul, bR, aR) self.assertRaises(NotImplementedError, mul, bR, cR) self.assertRaises(NotImplementedError, mul, cR, bR) self.assertRaises(NotImplementedError, mul, aR, cR) self.assertRaises(NotImplementedError, mul, cR, aR) # AddSD and MulSD for mtype in _mtypes: a = mtype(array1) a_sv = as_sparse_variable(a) a_dv = tensor.as_tensor_variable(array1) b = mtype(array2) b_sv = as_sparse_variable(b) b_dv = tensor.as_tensor_variable(array2) c = mtype(array3) c_sv = as_sparse_variable(c) c_dv = tensor.as_tensor_variable(array3) # add does not upcast self.assertRaises(NotImplementedError, add, a_sv, b_dv) self.assertRaises(NotImplementedError, add, b_sv, a_dv) self.assertRaises(NotImplementedError, add, b_sv, c_dv) self.assertRaises(NotImplementedError, add, c_sv, b_dv) self.assertRaises(NotImplementedError, add, a_sv, c_dv) self.assertRaises(NotImplementedError, add, c_sv, a_dv) # mul may upcast the dense input if needed if (config.cast_policy in ('custom', 'numpy') or (config.cast_policy == 'numpy+floatX' and config.floatX == 'float64')): # The result should be a float64 (not implemented). self.assertRaises(NotImplementedError, mul, a_sv, b_dv) elif (config.cast_policy == 'numpy+floatX' and config.floatX == 'float32'): # The result should be a float32. assert mul(a_sv, b_dv).dtype == 'float32' else: raise NotImplementedError() self.assertRaises(NotImplementedError, mul, b_sv, a_dv) assert mul(b_sv, c_dv).dtype == 'int32' self.assertRaises(NotImplementedError, mul, c_sv, b_dv) assert mul(a_sv, c_dv).dtype == 'float32' self.assertRaises(NotImplementedError, mul, c_sv, a_dv)