Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge mistakes #42

Merged
merged 15 commits into from
Jun 17, 2024
Merged
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "maturin"

[project]
name = "anyon-braiding-simulator"
requires-python = ">=3.8"
requires-python = ">=3.12"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
Expand Down
12 changes: 4 additions & 8 deletions python/anyon_braiding_simulator/Model.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
# Standard Library
import cmath
from enum import Enum
from itertools import product

import numpy as np


class AnyonModel(Enum):
Ising = 1
Fibonacci = 2
Custom = 3
from anyon_braiding_simulator import AnyonModel


class Model:
Expand Down Expand Up @@ -37,6 +31,7 @@ def __init__(self, model_type: AnyonModel, num_fusion_channels=5) -> None:
self.model_type = model_type

if model_type == AnyonModel.Ising:
self._charges = {'vacuum', 'sigma', 'psi'}
self._r_mtx = cmath.exp(-1j * np.pi / 8) * np.array([[1, 0], [0, 1j]])

self._f_mtx = np.zeros((3, 3, 3, 3, 2, 2))
Expand All @@ -52,6 +47,7 @@ def __init__(self, model_type: AnyonModel, num_fusion_channels=5) -> None:
self._rules = []

elif model_type == AnyonModel.Fibonacci:
self._charges = {'vacuum', 'psi'}
self._r_mtx = np.array([[cmath.exp(4 * np.pi * 1j / 5), 0], [0, -1 * cmath.exp(2 * np.pi * 1j / 5)]])
self._f_mtx = []
self._rules = []
Expand Down Expand Up @@ -118,4 +114,4 @@ def getFMatrix(self, a: str, b: str, c: str, d: str) -> np.ndarray:
if i not in anyondict:
raise ValueError('invalid anyon name')

return self._f_mtx[anyondict[a], anyondict[b], anyondict[c], anyondict[d]]
return self._f_mtx[anyondict[a]][anyondict[b]][anyondict[c]][anyondict[d]]
6 changes: 6 additions & 0 deletions python/anyon_braiding_simulator/Simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ def update_anyons(self, is_increasing: bool, anyons: list) -> None:
anyons are being removed.
anyons: list - List of anyons to add or remove.
"""

if is_increasing:
# Check if any anyons are being added that are already in the simulator
for anyon in anyons:
for anyon_in_sim in self._anyons:
if anyon_in_sim.name == anyon.name:
raise ValueError('Anyon name is already in simulator')
self._anyons.extend(anyons)
else:
self._anyons = [anyon for anyon in self._anyons if anyon not in anyons]
Expand Down
39 changes: 22 additions & 17 deletions python/anyon_braiding_simulator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ def anyon(*args):

name = args[0]
topological_charge = args[1]
position = ()

topo_charge = {
'psi': IsingTopoCharge.Psi,
'sigma': IsingTopoCharge.Sigma,
'vac': IsingTopoCharge.Vacuum,
}
try:
topo_charge = {
'psi': IsingTopoCharge.Psi,
'sigma': IsingTopoCharge.Sigma,
'vac': IsingTopoCharge.Vacuum,
}
topological_charge = topo_charge[args[1].lower()]
except ValueError:
print('Error: topological charge must be a number')
except KeyError:
print(f'Error: topological charge must be in {list(topo_charge.keys())}')
return

if len(args) == 2:
Expand All @@ -47,7 +48,6 @@ def anyon(*args):

position_1D = len(anyons) # Index/position of new anyon in 1D
position = (position_1D, 0)
print(f'Created anyon {name} with TC {topological_charge} at position {position_1D} in 1D')
else:
# Make sure any previous anyons were specified in 2D space
if sim.get_dim_of_anyon_pos() == 1:
Expand All @@ -67,10 +67,15 @@ def anyon(*args):
print('Error: position must be formatted as {x,y} where x and y are numbers')
return

print(f'Created anyon {name} with TC {topological_charge} at position {position} in 2D')

new_anyon = Anyon(name, topological_charge, position)
sim.update_anyons(True, [new_anyon])
try:
sim.update_anyons(True, [new_anyon])
if len(args) == 2:
print(f'Created anyon {name} with TC {topological_charge} at position {position[0]} in 1D')
else:
print(f'Created anyon {name} with TC {topological_charge} at position {position} in 2D')
except ValueError:
print('Error: An anyon with the same name already exists')


def model(*args):
Expand All @@ -89,7 +94,6 @@ def model(*args):

model_convert = {'ising': AnyonModel.Ising, 'fibonacci': AnyonModel.Fibonacci}

# TODO: figure out why this throws an error
model = Model(model_convert[model_type.lower()])
sim.set_model(model)

Expand Down Expand Up @@ -126,7 +130,7 @@ def braid(*args):
print('Error: Not enough arguments')
return

braid = Braid(sim.list_anyons(), sim._model)
braid = Braid(sim.list_anyons())
cmd = args[0]

if cmd.lower() == 'swap':
Expand Down Expand Up @@ -164,8 +168,8 @@ def __init__(self):
sys.exit(0)
else:
print('\nError: Invalid model.')
input_to_model_type = {'ising': AnyonModel.Ising, 'fibonacci': AnyonModel.Fibonacci}
model(input_to_model_type[user_input.lower()])

model(user_input)

# Prompt the user to input the anyon details
no_anyons = True
Expand Down Expand Up @@ -250,15 +254,16 @@ def do_list(self, arg):
if args[0] == 'help' or args[0] == '-h':
print(self.command_options['list'])
else:
print(sim.list_anyons())
print(f'Anyons: {"\n\t".join([str(anyon) for anyon in sim.list_anyons()])}')

def do_exit(self, arg):
"Exit the simulator"
return True

def do_help(self, arg):
"Print help"
print('Commands: fusion, braid, exit, help')
cmds = ['anyon', 'model', 'fusion', 'braid', 'exit', 'list']
print(f'Commands: {", ".join(sorted(cmds))}')


if __name__ == '__main__':
Expand Down
6 changes: 6 additions & 0 deletions python/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ def exec(cmds: list[str]):
def test_join():
cmds = ['ising', 'exit']
exec(cmds)


@pytest.mark.main
def test_fusion():
cmds = ['ising', 'anyon psi 0 0', 'anyon sigma 1 0', 'fusion 0 1', 'exit']
exec(cmds)
1 change: 0 additions & 1 deletion src/fusion/fusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ impl Fusion {
}

/// Assumes model is Ising
/// TODO: THIS IS NON DETERMINISTIC WTF
fn qubit_enc(&self) -> PyResult<Vec<FusionPair>> {
let enum_to_canonical = |charge: IsingTopoCharge| -> [u64; 3] {
match charge {
Expand Down
20 changes: 17 additions & 3 deletions src/model/anyon.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::slice::SliceIndex;

use pyo3::prelude::*;

/// Lazy solution for now, will properly implement a more general Topo Charge w/ specified
Expand All @@ -20,6 +18,14 @@ impl IsingTopoCharge {
IsingTopoCharge::Sigma => 2,
}
}

pub fn to_string(&self) -> &str {
match self {
IsingTopoCharge::Psi => "Psi",
IsingTopoCharge::Vacuum => "Vacuum",
IsingTopoCharge::Sigma => "Sigma",
}
}
}

#[pyclass]
Expand Down Expand Up @@ -53,7 +59,6 @@ impl AccessAnyon for Anyon {
}
}


#[pymethods]
impl Anyon {
#[new]
Expand All @@ -64,4 +69,13 @@ impl Anyon {
position,
}
}

fn __str__(&self) -> PyResult<String> {
Ok(format!(
"Anyon: name={}, charge={}, position={:?}",
self.name,
self.charge.to_string(),
self.position
))
}
}