def test_different_inits(self): np.random.seed(314) mean = np.ones(3) * 5 cov = np.eye(3) * 0.1 X = stats.multivariate_normal.rvs(mean, cov, 100) print(X.shape) Y = stats.multivariate_normal.rvs(mean, cov, 100) W = stats.ortho_group.rvs(3) Y = Y @ W aligner_1 = SeedlessProcrustes(init="2d") aligner_1.fit(X, Y) aligner_2 = SeedlessProcrustes(init="sign_flips") aligner_2.fit(X, Y) test_sign_flips = SignFlips() self.assertTrue( np.all( test_sign_flips.fit(X, Y).Q_ == aligner_2.selected_initial_Q_)) aligner_3 = SeedlessProcrustes(init="custom") aligner_3.fit(X, Y) self.assertTrue(np.all(np.eye(3) == aligner_3.selected_initial_Q_)) aligner_4 = SeedlessProcrustes(init="custom", initial_Q=-np.eye(3)) aligner_4.fit(X, Y) self.assertTrue(np.all(-np.eye(3) == aligner_4.selected_initial_Q_)) aligner_5 = SeedlessProcrustes(init="custom", initial_P=np.ones((100, 100)) / 10000) aligner_5.fit(X, Y)
def test_max_criterion(self): X = np.arange(6).reshape(3, 2) * (-1) Y = np.arange(6).reshape(3, 2) @ np.diag([1, -1]) + 0.5 # in this case, Y should be unchanged, and X matched to Y # so X flips sign in the first dimension Q_answer = np.array([[-1, 0], [0, 1]]) X_answer = X.copy() @ Q_answer # set criterion to "max", see if that works aligner = SignFlips(criterion="max") aligner.fit(X, Y) Q_test = aligner.Q_ X_test = aligner.transform(X) self.assertTrue(np.all(Q_test == Q_answer)) self.assertTrue(np.all(X_test == X_answer))
def test_sim(self): n = 150 rho = 0.9 n_per_block = int(n / 3) n_blocks = 3 block_members = np.array(n_blocks * [n_per_block]) block_probs = np.array([[0.2, 0.01, 0.01], [0.01, 0.1, 0.01], [0.01, 0.01, 0.2]]) directed = False loops = False A1, A2 = sbm_corr(block_members, block_probs, rho, directed=directed, loops=loops) ase = AdjacencySpectralEmbed(n_components=3, algorithm="truncated") x1 = ase.fit_transform(A1) x2 = ase.fit_transform(A2) xh1 = SignFlips().fit_transform(x1, x2) S = xh1 @ x2.T res = self.barygm.fit(A1, A2, S=S) self.assertTrue(0.7 <= (sum(res.perm_inds_ == np.arange(n)) / n)) A1 = A1[:-1, :-1] xh1 = xh1[:-1, :] S = xh1 @ x2.T res = self.barygm.fit(A1, A2, S=S) self.assertTrue(0.6 <= (sum(res.perm_inds_ == np.arange(n)) / n))
def test_bad_kwargs(self): with self.assertRaises(TypeError): SignFlips(criterion={"this is a": "dict"}) with self.assertRaises(ValueError): SignFlips(criterion="cep") # check delayed ValueError with self.assertRaises(ValueError): aligner = SignFlips(criterion="median") X = np.arange(6).reshape(6, 1) Y = np.arange(6).reshape(6, 1) aligner.criterion = "something" aligner.fit(X, Y)
def test_two_datasets(self): X = np.arange(6).reshape(3, 2) * (-1) Y = np.arange(6).reshape(3, 2) @ np.diag([1, -1]) + 0.5 # X flips sign in the first dimension Q_answer = np.array([[-1, 0], [0, 1]]) X_answer = X.copy() @ Q_answer # first, do fit and transform separately aligner_1 = SignFlips() aligner_1.fit(X, Y) Q_test = aligner_1.Q_ X_test = aligner_1.transform(X) self.assertTrue(np.all(Q_test == Q_answer)) self.assertTrue(np.all(X_test == X_answer)) # now, do fit_transform aligner_2 = SignFlips() X_test = aligner_2.fit_transform(X, Y) Q_test = aligner_2.Q_ self.assertTrue(np.all(Q_test == Q_answer)) self.assertTrue(np.all(X_test == X_answer)) # try giving a different matrix as the sole input (I) I_test = aligner_2.transform(np.eye(2)) I_answer = np.diag([-1, 1]) self.assertTrue(np.all(I_test == I_answer))
def test_bad_datasets(self): X = np.arange(6).reshape(6, 1) Y = np.arange(6).reshape(6, 1) Y_wrong_d = np.arange(12).reshape(6, 2) # check passing weird stuff as input (caught by us) with self.assertRaises(TypeError): aligner = SignFlips() aligner.fit("hello there", Y) with self.assertRaises(TypeError): aligner = SignFlips() aligner.fit(X, "hello there") with self.assertRaises(TypeError): aligner = SignFlips() aligner.fit({"hello": "there"}, Y) with self.assertRaises(TypeError): aligner = SignFlips() aligner.fit(X, {"hello": "there"}) # check passing arrays of weird ndims (caught by check_array) with self.assertRaises(ValueError): aligner = SignFlips() aligner.fit(X, Y.reshape(3, 2, 1)) with self.assertRaises(ValueError): aligner = SignFlips() aligner.fit(X.reshape(3, 2, 1), Y) # check passing arrays with different dimensions (caught by us) with self.assertRaises(ValueError): aligner = SignFlips() aligner.fit(X, Y_wrong_d) # check passing array with wrong dimensions to transform (caught by us) with self.assertRaises(ValueError): aligner = SignFlips() aligner.fit(X, Y) aligner.transform(Y_wrong_d)