From bce3fc3ba8d9de0c3ca1d652dfa6539ecd957b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Hu=C5=A1ek?= <husek@iuuk.mff.cuni.cz> Date: Tue, 6 Apr 2021 15:55:32 +0200 Subject: [PATCH] Flower snark experiment --- experiments/flower-snarks.py | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 experiments/flower-snarks.py diff --git a/experiments/flower-snarks.py b/experiments/flower-snarks.py new file mode 100755 index 0000000..b1e5243 --- /dev/null +++ b/experiments/flower-snarks.py @@ -0,0 +1,88 @@ +#!/usr/bin/python + +DOC = """ +Calculate that the number of CDCs of Flower snark $J_k$ is $16^{(1-o(1))k}$. + +We calculate the step matrix $M$, show that 16 is its eigenvalue by finding +its eigenvector. The eigenvector is guessed for the ratios of coefficients +of $M^10 x$ and $M^9 x$ where $x$ is the initial vector. This eigenvector +shares one non-zero coordinate with the final vector. +""" + +import sys, os +sys.path.append(os.path.dirname(__file__) + "/..") + +from graph_tools.all import * +from sage.all import identity_matrix, QQ, DiGraph, matrix + +def test_eigenvalue(M, x): + H = M - x*identity_matrix(QQ, M.ncols(), sparse=True) + if H.is_singular(): + print(" Value %i is an eigenvalue of M with geometric multiplicity %i" % + (x, H.ncols() - H.rank())) + +def matrix_to_rev_graph(M): + assert M.ncols() == M.nrows() + return DiGraph([range(M.ncols()), M.dict().keys()], + format="vertices_and_edges", loops=True) + + +if __name__ == "__main__": + print(DOC) + print("Stabilizing...") + S = FlowerSnark.stabilize(CircuitDoubleCover, jordan=False) + print("Done") + M = S["step_matrix"] + + print("\nThe rank of the step matrix M: %s" % M.rank()) + upto = 16 + print("Testing if integers up to %i are eigenvalues:" % upto) + for x in range(upto + 1): + test_eigenvalue(M, x) + + fin = S["finalize"] + + print("\nCheking correctness of the matrix") + N = 16 + A = S["initial_vector"] + for i in range(3, N): + nu1 = FlowerSnark.graph(i).eval(CircuitDoubleCover) + A = M * A + nu2 = fin * A + assert nu1 == nu2 + print(" ν(J_%i) = %i" % (i, nu1)) + print(" Done") + + print("\nCalculating the eigenvector for eigenvalue 16") + to_dict = lambda g: { b.boundary: b.value for b in g } + gadget_to_dict = lambda i: to_dict(FlowerSnark.gadget(i).eval_gadget(CircuitDoubleCover)) + + X10 = gadget_to_dict(10) + X9 = gadget_to_dict(9) + B = [ b for b in X10.keys() if b in X9 and X10[b] / X9[b] > 15 ] + m = min( X10[b] for b in B ) + vec = { b: int(round(X10[b] / m)) for b in B } + print(" Guessed eigenvector (with %i non-zero coordinates):" % len(vec)) + for b, v in sorted(vec.items()): + print(" %i at %s" % (v, b)) + + print(" Checking it...") + nex = to_dict(FlowerSnark._next_gadget(FakeGadget(6, + [ Boundary(b, v) for b, v in vec.items() ])).eval_gadget(CircuitDoubleCover)) + + assert nex.keys() == vec.keys() + for b in vec: + assert vec[b] * 16 == nex[b], "Oops at %b" % b + + assert set(S["variables"]).issuperset(vec.keys()) + index = { b: i for i, b in enumerate(S["variables"]) } + vec_ = matrix(QQ, M.ncols(), 1, { (index[b], 0): v for b, v in vec.items() }) + assert M * vec_ == 16 * vec_ + + print(" Done") + + print(" Boundaries of with the non-zero value in both the eigenvector and the final vector:") + for i in range(vec_.nrows()): + if vec_[i, 0] > 0 and fin[0, i] > 0: + print(" %s" % (S["variables"][i],)) + -- GitLab