def get_fhats_sp(fname, tup): st = time.time() mat = scipy.io.loadmat(fname) A = mat['A'] B = mat['B'] n = A.shape[0] popt = Perm(tup) fhats = {} opt_reps = {} tot = 0 print(f'Load time: {time.time()-st:.4f}s') # coset rep group elements reps_i, reps_j = cos_reps_minus2_pairs(n) reps = [i * j for i in reps_i for j in reps_j] for irrep in [(n - 2, 1, 1), (n - 2, 2), (n - 1, 1), (n, )][::-1]: st = time.time() sp_rho = SnIrrep(irrep, 'sparse') mats_i = [sp_rho(i) for i in reps_i] mats_j = [sp_rho(j) for j in reps_j] rep_mats = [mi @ mj for mi in mats_i for mj in mats_j] fh = fhat_AB(A, B, irrep, reps, rep_mats) rep = sp_rho(popt) tot += hook_length(irrep) * (rep.toarray() * fh).sum() / math.factorial(n) fhats[irrep] = fh opt_reps[irrep] = rep print(f'Time: {time.time() - st:.2f}s | Irrep: {irrep} | {type(fh)}') print(f'Total time: {time.time() - st:.2f}s') print(tot) return fhats, opt_reps
def make_blocked(blocks, n): bmat = np.zeros((n * n, n * n)) irreps = [(n - 2, 1, 1), (n - 2, 2), (n - 1, 1), (n - 1, 1), (n - 1, 1), (n, ), (n, )] idx = 0 for irrep in irreps: dim = hook_length(irrep) bmat[idx:idx + d, idx:idx + d] = irreps[irrep] idx += dim return bmat
def gen_fhat_blocks(f, _lambdas, group): d = int(sum([hook_length(l) for l in _lambdas])) fhat = np.zeros((d, d)) idx = 0 for irrep in _lambdas: rho = SnIrrep(irrep) mat = ft(f, rho, group) k = mat.shape[0] fhat[idx:idx + k, idx:idx + k] = mat idx += k return fhat
def make_block_tensor(n, g): irreps = [(n - 2, 1, 1), (n - 2, 2), (n - 1, 1), (n - 1, 1), (n - 1, 1), (n,), (n,)] hls = [hook_length(ir) for ir in irreps] tot = int(sum(hls)) mat = np.zeros((tot, tot)) idx = 0 for ir, d in zip(irreps, hls): d = int(d) rho = SnIrrep(ir) mat[idx: idx+d, idx: idx+d] = rho(g) idx += d return mat
def get_fhat_cos(A, _lambda, cos_reps, cos_mats): n = sum(_lambda) d = hook_length(_lambda) mat = np.zeros((d, d)) mat[-1, -1] = math.factorial(n - 2) tot = 0 if _lambda == (n - 1, 1): mat[-2, -2] = mat[-1, -1] for c, crep in zip(cos_reps, cos_mats): tot += A[c(n) - 1, c(n - 1) - 1] * (crep @ mat) return tot
def qap_ft(mat, _lambda): ''' We will only ever take the FT of: (n-1, 1), (n-2, 2), (n-2, 1, 1) ''' n = sum(_lambda) rho = SnIrrep(_lambda, fmt='dense') fhat = 0 cos_reps = sn_minus2_coset(n) sn_minus2_size = math.factorial(n - 2) hl = hook_length(_lambda) fmat = np.zeros((hl, hl)) fmat[-1, -1] = sn_minus2_size if _lambda == (n - 1, 1): fmat[-2, -2] = sn_minus2_size for p in cos_reps: feval = mat[p(n) - 1, p(n - 1) - 1] fhat += rho(p) @ (feval * fmat) return fhat
def fhat_mat(A, _lambda, cos_reps=None): ''' A: numpy matrix of size n x n _lambda: partition of n cos_reps: (optional) list of coset representatives for S_n / S_{n-2} Returns: fourier matrix of the graph function given by A at irrep _lambda ''' n = sum(_lambda) rho = SnIrrep(_lambda) d = hook_length(_lambda) mat = np.zeros((d, d)) mat[-1, -1] = math.factorial(n - 2) tot = 0 if _lambda == (n - 1, 1): mat[-2, -2] = mat[-1, -1] if cos_reps is None: cos_reps = cos_reps_minus2(n) for c in cos_reps: tot += A[c(n) - 1, c(n - 1) - 1] * (rho(c) @ mat) return tot
def fourier_admm_qap(L, Vhat, J, args, n, outer_AB): st = time.time() maxit = args.maxit tol = args.tol gamma = args.gamma low_rank = args.low_rank K = args.K normL = np.linalg.norm(L) Vhat_nrows = Vhat.shape[0] L = L * (n * n / normL) mask = make_bdiag_mask(n) beta = n / 3. Y0 = make_y0(n) # R0 = make_r0(n, Vhat, Y0) R0 = np.eye((n - 1)**2 + 1) Z0 = Y0 - (Vhat @ R0 @ Vhat.T) Y = Y0 R = R0 Z = Z0 C = load_cg_transform(n, '../intertwiners/c{n}.npy') blocks = { (n - 2, 1, 1): np.eye(hook_length((n - 2, 1, 1))), (n - 2, 2): np.eye(hook_length((n - 2, 2))), (n - 1, 1): np.eye(hook_length((n - 1, 1))), (n, ): np.eye(1), } B = make_blocked(blocks, n) for i in tqdm(range(maxit)): R_pre_proj = Vhat.T @ (Y + Z / beta) @ Vhat R_pre_proj = (R_pre_proj + R_pre_proj.T) / 2. S, U = np.linalg.eigh(R_pre_proj) if not args.low_rank: pos_idx = S > 0 if pos_idx.sum() > 0: vhat_u = Vhat @ U[:, pos_idx] VRV = (vhat_u * S[pos_idx]) @ vhat_u.T else: VRV = np.zeros(Y.shape) else: if S[-1] > 0: vhat_u = Vhat @ U[:, -1:] VRV = S[-1] * vhat_u @ vhat_u.T else: VRV = np.zeros(Y.shape) # update Y # Y = VRV - ((L + Z) / beta) Y = CBC - ((L + Z) / beta) Y = (Y + Y.T) / 2. Y[J] = 0 Y[0, 0] = 1 Y = np.minimum(1, np.maximum(0, Y)) Y[J] = 0 Y[0, 0] = 1 Y[np.abs(Y) < tol] = 0 pR = Y - VRV # update Z # Z = Z + gamma * beta * (Y - VRV) Z = Z + gamma * beta * (Y - CBC) Z = (Z + Z.T) / 2. Z[np.abs(Z) < tol] = 0 if i % 100 == 0: scale = normL / (n * n) npr = np.linalg.norm(pR, 'fro') lbd = lower_bound(L, J, Vhat, Z, n, scale=scale) dy = np.square(Y.dot(np.ones(len(Y))) - np.ones(len(Y))).sum() dyt = np.square(Y.T.dot(np.ones(len(Y))) - np.ones(len(Y))).sum() print( f'Iter {i} | Lower bound: {lbd:.2f} | pR: {npr:.6f} | Ye - e: {dy:.4f} {dyt:.4f}' ) tt = time.time() - st print('Done! | Elapsed: {:.2f}min'.format(tt / 60))