def MinimizeTrace(u, alpha, bc, sqrt_relax=1e-16): # Compute the tensor decompositions D = MakeD(alpha) theta, sb = AnglesAndSuperbases(D) theta = np.array([theta[:-1], theta[1:]]) # Compute the second order differences in the direction orthogonal to the superbase sb_rotated = np.array([-sb[1], sb[0]]) d2u = bc.Diff2(u, sb_rotated) d2u[..., bc.not_interior] = 0. # Placeholder values to silent NaNs # Compute the coefficients of the tensor decompositions sb1, sb2 = np.roll(sb, 1, axis=1), np.roll(sb, 2, axis=1) sb1, sb2 = (e.reshape((2, 3, 1) + sb.shape[2:]) for e in (sb1, sb2)) D = D.reshape((2, 2, 1, 3, 1) + D.shape[3:]) # Axes of D are space,space,index of superbase element, index of D, index of superbase, and possibly shape of u scals = lp.dot_VAV(sb1, D, sb2) # Compute the coefficients of the trigonometric polynomial scals, theta = (bc.as_field(e) for e in (scals, theta)) coefs = -lp.dot_VV(scals, np.expand_dims(d2u, axis=1)) # Optimality condition for the trigonometric polynomial in the interior value = coefs[0] - np.sqrt( np.maximum(coefs[1]**2 + coefs[2]**2, sqrt_relax)) coefs_ = np.array(coefs) # removed AD information angle = np.arctan2(-coefs_[2], -coefs_[1]) / 2. angle[angle < 0] += np.pi # Boundary conditions for the trigonometric polynomial minimization mask = np.logical_not(np.logical_and(theta[0] <= angle, angle <= theta[1])) t, c = theta[:, mask], coefs[:, mask] value[mask], amin_t = ad.min_argmin(c[0] + c[1] * np.cos(2 * t) + c[2] * np.sin(2 * t), axis=0) # Minimize over superbases value, amin_sb = ad.min_argmin(value, axis=0) # Record the optimal angles for future use angle[mask] = np.take_along_axis(t, np.expand_dims(amin_t, axis=0), axis=0).squeeze(axis=0) # Min over bc angle = np.take_along_axis(angle, np.expand_dims(amin_sb, axis=0), axis=0) # Min over superbases return value, angle
def SchemeMALBR_OptInner(u,SB,bc,oracle=None): # If the active superbases are known, then take only these if not(oracle is None): SB = np.take_along_axis(SB,np.broadcast_to(oracle,SB.shape[:2]+(1,)+oracle.shape),axis=2) d2u = bc.Diff2(u,SB) d2u[...,bc.not_interior] = 0. # Placeholder value to silent NaN warnings # Evaluate the complex non-linear function using dense - sparse composition result = ad.apply(MALBR_H,d2u,shape_bound=u.shape) return ad.min_argmin(result,axis=0)
def SchemeSampling_OptInner(u, diffs, bc, oracle=None): # Select the active tensors, if they are known if not (oracle is None): diffs = np.take_along_axis(diffs, np.broadcast_to( oracle, diffs.shape[:2] + (1, ) + oracle.shape), axis=2) print("Has AD information :", ad.is_ad(u), ". Number active tensors per point :", diffs.shape[2]) # Tensor decomposition coefs, offsets = Selling.Decomposition(diffs) # Return the minimal value, and the minimizing index return ad.min_argmin(lp.dot_VV(coefs, bc.Diff2(u, offsets)), axis=0)