<jupyter_start><jupyter_text>Analysis of the rank of the constraint matrixThis notebook is meant to give more intuiton on when the constraint matrix, denotend $[\pmb{T}_A, \pmb{U\Sigma}]$ in the paper is full rank, and thus when the unique solution to the linear system exists.We use the notation from the proof of Theorem 1. Thus, by *left matrix* we mean the matrix consisting of rows$$\text{vec}\left(\begin{bmatrix} \pmb{a}_{m_n} \\ 1\end{bmatrix}  \pmb{f}_n^\top \right)^\top.$$By *full matrix* we mean the matrix consising of rows $$\begin{bmatrix}\text{vec}\left(\begin{bmatrix} \pmb{a}_{m_n} \\ 1\end{bmatrix}  \pmb{f}_n^\top \right)^\top & f_K(t_n) \dots f_{2K-1}(t_n)\end{bmatrix}.$$To switch between full matrix and left matrix use the flag `full_matrix`.In the Relax and Recover paper, we assume that at each time, there is maximum one measurement taken. To see what happens if is not the case, you can set the flag `one_per_time` to `False`.<jupyter_code>full_matrix = True
one_per_time = True<jupyter_output><empty_output><jupyter_text>Run simulations and calculate matrix rank Calculate the matrix rank for `n_repetitions` for different trajectories, anchros positions and different measurements subsets. From this, we can estimate the probability that the matrix is full rank for given parameters.<jupyter_code>experiment_params={
    "n_dimensions": 2,
    "n_constraints": 5,
    "n_repetitions": 500, # do 5000 for smooth results
    "full_matrix": full_matrix,
    "n_anchors_list": [3, 4, 6, 20], # calcualte different number of anchors in a loop
    "n_times": 40 if one_per_time else 15, # reduce number of times if many measurements per time are available
    "one_per_time": one_per_time,
}

start = time.time()
ranks, params = p.matrix_rank_experiment(**experiment_params)
end = time.time()
print("elapsed time: {:.2f}s".format(end - start))

estimated_probabilities = np.mean(ranks >= params["max_rank"], axis=2)
estimated_variance = np.var(ranks >= params["max_rank"], axis=2)<jupyter_output><empty_output><jupyter_text>Calculate the probability based on Theorem 1 If only one measurement per time is used, then the Theorem 1 holds and the upper bound calculated below becomes a tight bound. If many measurements per time are allowed, then Theorem gives a necessary, but not sufficient condition (thus an upper bound).<jupyter_code>probabilities = []

start = time.time()
for idx, n_anchors in enumerate(params["n_anchors_list"]):
    print("{} anchors".format(n_anchors))
    probabilities.append([p.probability_upper_bound(
        params["n_dimensions"],
        params["n_constraints"],
        n_measurements=n,
        position_wise=False,
        n_anchors=n_anchors,
        n_times=np.Infinity if one_per_time else params["n_times"],
        full_matrix=params["full_matrix"]
    ) for n in params["n_measurements_list"]])
probabilities = np.array(probabilities)
print("time: {:.2f}s".format(time.time()-start))<jupyter_output><empty_output><jupyter_text>Plot the resutls<jupyter_code>f, ax = plt.subplots(figsize=(10, 5))
plot_probabilities(estimated_probabilities, params, ax, linestyle=":", variance=estimated_variance)
plot_probabilities(probabilities.T, params, ax, label="calcualted")
matrix_name = "Full matrix" if params["full_matrix"] else "Left hand side"
measurements_type = "one measurement per time" if params["one_per_time"] else "many measurements per time"
ax.set_title("{}, {}, complexity {}".format(matrix_name, measurements_type, params["n_constraints"]))
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11486486486486487, 'fraction_numerical': 0.009009009009009009, 'mean_word_length': 5.604089219330855, 'pattern_counts': {'":': 8, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '514393', 'license': 'MIT', 'n_tokens_mistral': 1145, 'n_tokens_neox': 1087, 'n_words': 348, 'path': 'TheoryTesting.ipynb', 'repo_name': 'LCAV/continuous-localization', 'size': '3552'}