|
| 1 | +# import sys |
| 2 | +# sys.path.append('/Users/pedrolauand/inflation') |
| 3 | +from inflation import InflationProblem, InflationLP, InflationSDP |
| 4 | +import numpy as np |
| 5 | +""" |
| 6 | +Crazy idea: Use dummy intermediate latents to encode causal symmetry (to indicate the different Hilbert spaces of a single source) |
| 7 | +""" |
| 8 | +def exists_shared_source_modified(inf_indices1: np.ndarray, |
| 9 | + inf_indices2: np.ndarray) -> bool: |
| 10 | + common_sources = np.logical_and(inf_indices1, inf_indices2) |
| 11 | + if not np.any(common_sources): |
| 12 | + return False |
| 13 | + return not set(inf_indices1[common_sources]).isdisjoint(set(inf_indices2[common_sources])) |
| 14 | +def overlap_matrix(all_inflation_indxs: np.ndarray) -> np.ndarray: |
| 15 | + n = len(all_inflation_indxs) |
| 16 | + adj_mat = np.eye(n, dtype=bool) |
| 17 | + for i in range(1, n): |
| 18 | + inf_indices_i = all_inflation_indxs[i] |
| 19 | + for j in range(i): |
| 20 | + inf_indices_j = all_inflation_indxs[j] |
| 21 | + if exists_shared_source_modified(inf_indices_i, inf_indices_j): |
| 22 | + adj_mat[i, j] = True |
| 23 | + adj_mat = np.logical_or(adj_mat, adj_mat.T) |
| 24 | + return adj_mat |
| 25 | +def name_interpret_always_copy_indices(*args, **kwargs): |
| 26 | + return InflationProblem._interpretation_to_name(*args, include_copy_indices=True) |
| 27 | + |
| 28 | +def ring_problem(n: int) -> InflationProblem: |
| 29 | + inf_prob = InflationProblem( |
| 30 | + dag={"i1": ["A"], |
| 31 | + "i2": ["A"], }, |
| 32 | + outcomes_per_party=(2,), |
| 33 | + settings_per_party=(1,), |
| 34 | + classical_sources=None, |
| 35 | + inflation_level_per_source=(n,n), |
| 36 | + order=["A"]) |
| 37 | + |
| 38 | + to_stabilize = np.flatnonzero(inf_prob._lexorder[:, 1] == inf_prob._lexorder[:, 2]) |
| 39 | + |
| 40 | + #Artificially kill all self-loops |
| 41 | + # inf_prob._default_notcomm[:, to_stabilize] = True |
| 42 | + # inf_prob._default_notcomm[to_stabilize] = True |
| 43 | + # inf_prob._default_notcomm[np.ix_(to_stabilize, to_stabilize)] = False |
| 44 | + |
| 45 | + #Fix factorization |
| 46 | + inf_prob._inflation_indices_overlap = overlap_matrix(inf_prob._all_unique_inflation_indices) |
| 47 | + |
| 48 | + # Fix symmetries |
| 49 | + # print("Never use: ", to_stabilize) |
| 50 | + new_symmetries = np.array([ |
| 51 | + perm for perm in inf_prob.symmetries |
| 52 | + if np.array_equal(np.sort(perm[to_stabilize]), to_stabilize) |
| 53 | + ], dtype=int) |
| 54 | + inf_prob.symmetries = new_symmetries |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | + #Hacks to prevent knowability assumptions |
| 59 | + # inf_prob.is_network = False |
| 60 | + # inf_prob._is_knowable_q_non_networks = (lambda x: False) |
| 61 | + |
| 62 | + inf_prob._interpretation_to_name = name_interpret_always_copy_indices |
| 63 | + |
| 64 | + return inf_prob |
| 65 | +# def ring_LP(n: int, **kwargs) -> InflationLP: |
| 66 | +# inf_lp = InflationLP(ring_problem(n), **kwargs) |
| 67 | +# inf_lp.all_commuting_q_1d = (lambda x: False) |
| 68 | +# inf_lp.all_commuting_q_2d = (lambda x: False) |
| 69 | +# inf_lp.all_operators_commute = False |
| 70 | +# return inf_lp |
| 71 | + |
| 72 | +prob_4 = ring_problem(4) |
| 73 | +# print(prob_4._compatible_template_measurements.astype(int)) |
| 74 | +# cliques = prob_4.all_and_maximal_compatible_templates()[-1] |
| 75 | +# for clique in cliques[:4]: |
| 76 | +# print(prob_4._compatible_template_measurements.astype(int)[np.ix_(clique,clique)]) |
| 77 | +# print(prob_4._lexorder[prob_4._template_idxs[clique]]) |
| 78 | + |
| 79 | +ring_4_LP = InflationLP(prob_4, verbose=2) |
| 80 | +print("Nonfanout inflation atomic factors:") |
| 81 | +print(ring_4_LP.atomic_factors) |
| 82 | + |
| 83 | +ring_4_SDP = InflationSDP(prob_4, verbose=2) |
| 84 | +ring_4_SDP.generate_relaxation("npa2") |
| 85 | + |
| 86 | +print("Quantum inflation **nonfanout/commuting** factors:") |
| 87 | +print(ring_4_SDP.physical_atoms) |
| 88 | +print("Quantum inflation **noncommuting** factors:") |
| 89 | +print(sorted(set(ring_4_SDP.atomic_factors).difference(ring_4_SDP.physical_atoms))) |
| 90 | +# # print(ring_4_SDP.momentmatrix) |
| 91 | +# # |
| 92 | +# known_values = {} |
| 93 | +# E1 = 0 |
| 94 | +# # E1 ≥0.1656 |
| 95 | +# E2 = -1 / np.sqrt(2) |
| 96 | +# # Inputting values |
| 97 | +# known_values["P[A^{1,2}=0]"] = 1 / 2 * (1 + E1) |
| 98 | +# |
| 99 | +# known_values["P[A^{1,2}=0 A^{2,3}=0]"] = 1 / 4 * (1 + 2*E1 + E2) |
| 100 | +# print(known_values) |
| 101 | +# |
| 102 | +# ring_4_SDP.update_values(known_values) |
| 103 | +# ring_4_SDP.solve(solve_dual=False) |
| 104 | +# |
0 commit comments