# This code is part of TQSim.
#
# (C) Copyright Constantine Quantum Technologies, 2022.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
from typing import List
import numpy as np
def __check_rule(anyon1: int, anyon2: int, outcome: int) -> bool:
""" Returns True if 'anyon1 x anyon2 = outcome' obeys the Fibonacci
fusion rules, returns False otherwise.
Parameters
----------
anyon1 : int
Anyon charge of the 1st anyon.
anyon2 : int
Anyon charge of the 2nd anyon.
outcome : int
Anyon charge of the fusion result.
Returns
-------
bool
True if the Fibonacci fusion rules are obeyed, False otherwise.
"""
if anyon1 and anyon2:
return True
elif (anyon1 or anyon2) and outcome == 1:
return True
elif not (anyon1 or anyon2) and outcome == 0:
return True
else:
return False
def __check_outcomes(outcomes: List[int]) -> bool:
previous_outcome = 1
for outcome in outcomes:
if __check_rule(previous_outcome, 1, outcome):
previous_outcome = outcome
else:
return False
return True
def __check_state(state) -> bool:
nb_qudits = len(state["qudits"])
qudit_len = len(state["qudits"][0])
for qudit in state["qudits"]:
if len(qudit) == qudit_len:
if not __check_outcomes(qudit):
return False
else:
return False
if nb_qudits != len(state["roots"]) + 1:
return False
previous_outcome = state["qudits"][0][-1]
for i, outcome in enumerate(state["roots"]):
if __check_rule(previous_outcome, state["qudits"][i + 1][-1], outcome):
previous_outcome = outcome
else:
return False
return True
def __gen_state(comb: List[int], nb_qudits: int, qudit_len: int):
state = {"qudits": [], "roots": []}
for i, label in enumerate(comb):
if i < nb_qudits * qudit_len:
if i % qudit_len:
state["qudits"][-1].append(label)
else:
state["qudits"].append([label])
else:
state["roots"].append(label)
return state
[docs]def generate_basis(nb_qudits: int, nb_anyons_per_qudit: int):
"""Generates all the basis states for a system of a given number of
qudits, and a given number of anyons per qudit.
Parameters
----------
nb_qudits : int
Number of qudits in the circuit.
nb_anyons_per_qudit : int
Number of anyons in each qudit.
Returns
-------
basis : List[basis states]
A list of basis states.
"""
nb_roots = nb_qudits - 1
qudit_len = nb_anyons_per_qudit - 1
nb_labels = nb_qudits * qudit_len + nb_roots
basis = []
curr_comb = [0] * nb_labels
final_comb = [1] * nb_labels
curr_state = __gen_state(curr_comb, nb_qudits, qudit_len)
if __check_state(curr_state):
basis.append(curr_state)
while not np.all(curr_comb == final_comb):
for i, label in enumerate(curr_comb):
if label == 0:
curr_comb[i] = 1
break
else:
curr_comb[i] = 0
curr_state = __gen_state(curr_comb, nb_qudits, qudit_len)
if __check_state(curr_state):
basis.append(curr_state)
return basis