Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
427 changes: 427 additions & 0 deletions pylintrc

Large diffs are not rendered by default.

32 changes: 18 additions & 14 deletions src/koala/chern_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
def crosshair_marker(lattice: Lattice, projector: np.ndarray, crosshair_position: np.ndarray):
"""Generate the crosshair marker for a lattice and Hamiltonian

:param lattice: the lattice on which the Hamiltonian is placed
:type lattice: Lattice
:param projector: A projectro onto a set of occupied states
:type projector: np.ndarray
:param crosshair_position: the position of the crosshair in the bulk
:type crosshair_position: np.ndarray
:return: an array giving the marker value at every point in the system
:rtype: np.ndarray
Args:
lattice (Lattice): the lattice on which the Hamiltonian is
placed
projector (np.ndarray): A projectro onto a set of occupied
states
crosshair_position (np.ndarray): the position of the crosshair
in the bulk

Returns:
np.ndarray: an array giving the marker value at every point in
the system
"""


Expand All @@ -28,12 +31,13 @@ def crosshair_marker(lattice: Lattice, projector: np.ndarray, crosshair_position
def chern_marker(lattice: Lattice, projector: np.ndarray):
"""generate the Chern marker for the system

:param lattice: the lattice
:type lattice: Lattice
:param projector: a projector onto a set of occupied states
:type projector: np.ndarray
:return: the Chern marker value for each point in the system
:rtype: np.ndarray
Args:
lattice (Lattice): the lattice
projector (np.ndarray): a projector onto a set of occupied
states

Returns:
np.ndarray: the Chern marker value for each point in the system
"""

positions = lattice.vertices.positions
Expand Down
141 changes: 73 additions & 68 deletions src/koala/example_graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ def tri_square_pent():


def tutte_graph():
"""
Returns a tutte graph, a cubic graph with no Hamiltonian cycle, but is three-colorable.
"""Returns a tutte graph, a cubic graph with no Hamiltonian cycle, but is three-colorable.

Returns:
vertices: np.array shape (nvertices, ndim) - A list of the positions of all the vertices that make up the graph
Expand Down Expand Up @@ -182,12 +181,14 @@ def tutte_graph():
def n_ladder(n_sites: int, wobble=False):
"""Produces a strip-ladder type graph - good for testing if things work in strip geometry

:param n_sites: number of sites in the x-direction
:type n_sites: int
:param wobble: adds a sin wobble to the ladder shape - for testing if plaquettes come out that shouldnt be there, defaults to False
:type wobble: bool, optional
:return: a lattice for the ladder system
:rtype: Lattice
Args:
n_sites (int): number of sites in the x-direction
wobble (bool, optional): adds a sin wobble to the ladder shape -
for testing if plaquettes come out that shouldnt be there,
defaults to False

Returns:
Lattice: a lattice for the ladder system
"""

x_positions = np.linspace(0.05, 0.95, n_sites)
Expand Down Expand Up @@ -222,8 +223,8 @@ def n_ladder(n_sites: int, wobble=False):
def multi_graph() -> Lattice:
"""Returns a graph with multiple edges between the same two sites

:return: A multiple-y connected graph
:rtype: Lattice
Returns:
Lattice: A multiple-y connected graph
"""
return Lattice(
vertices=np.array([[0.5, 0.7], [0.5, 0.3]]),
Expand All @@ -235,8 +236,8 @@ def multi_graph() -> Lattice:
def bridge_graph():
"""gives a simple example of a graph with a bridge - somethiing that could mess up the plaquette finder (but shouldnt any more!)

:return: A simple lattice with a bridge
:rtype: Lattice
Returns:
Lattice: A simple lattice with a bridge
"""
vertices = np.array(
[[0.1, 0.2], [0.1, 0.8], [0.4, 0.5], [0.6, 0.5], [0.9, 0.8], [0.9, 0.2]]
Expand All @@ -255,12 +256,15 @@ def generate_honeycomb(n_horizontal_cells: int, return_coloring=False) -> Lattic
"""Generates a regular honeycomb lattice with n_horizonta_cells number of cells in the x-direction, and a similar amount in the y direction
but slightly fudged to fir a square system

:param n_horizontal_cells: number of cells wide you want the lattice
:type n_horizontal_cells: int
:param return_coloring: if True also returns a regular kitaev-style coloring for all the edges, defaults to False
:type return_coloring: bool, optional
:return: a lattice or a lattice and a coloring
:rtype: Lattice, np.ndarray (optional)
Args:
n_horizontal_cells (int): number of cells wide you want the
lattice
return_coloring (bool, optional): if True also returns a regular
kitaev-style coloring for all the edges, defaults to False

Returns:
Lattice, np.ndarray (optional): a lattice or a lattice and a
coloring
"""

# define a basic unit cell with four sites
Expand Down Expand Up @@ -382,10 +386,11 @@ def next_direction(n_horizontal, n_vertical, n, shift):
def generate_hex_square_oct(n_cells: int) -> Lattice:
"""Generates a lattice containing squares, hexagons and octagons

:param n_cells: Number of unit cells in the x or y directions
:type n_cells: int
:return: the lattice object for this system
:rtype: Lattice
Args:
n_cells (int): Number of unit cells in the x or y directions

Returns:
Lattice: the lattice object for this system
"""

site_coordinates = np.array(
Expand Down Expand Up @@ -457,12 +462,16 @@ def next_direction(cells, n, shift):
def generate_tri_non(n_cells, return_coloring=False):
"""generate a lattice of nonagons and triangles

:param n_cells: system dimensions. If an int is passed then the system is n_cells x n_cells. If an iterable is passed the system is n_cells[0] x n_cells[1]
:type n_cells: int or iter[int]
:param return_coloring: optional arg to return a coloring of the edges, defaults to False
:type return_coloring: bool, optional
:return: the lattice and optionally a coloring
:rtype: Lattice or Lattice, np.ndarray
Args:
n_cells (int or iter[int]): system dimensions. If an int is
passed then the system is n_cells x n_cells. If an iterable
is passed the system is n_cells[0] x n_cells[1]
return_coloring (bool, optional): optional arg to return a
coloring of the edges, defaults to False

Returns:
Lattice or Lattice, np.ndarray: the lattice and optionally a
coloring
"""

unit_points = np.array([[0.4, 0.1], [0.1, 0.4], [0.4, 0.4], [0.6, 0.6]])
Expand Down Expand Up @@ -493,14 +502,11 @@ def generate_tri_non(n_cells, return_coloring=False):
def _next_cell_number(n_horizontal, n_vertical, n, shift):
"""gives you the index of the next unit cell in the list of all unit cells

:param n_horizontal: number unit cells in x direction
:type n_horizontal: int
:param n_vertical: number of unit cells in y direction
:type n_vertical: int
:param n: what index you are currently at
:type n: int
:param shift: whoch way you want to shift to
:type shift: list
Args:
n_horizontal (int): number unit cells in x direction
n_vertical (int): number of unit cells in y direction
n (int): what index you are currently at
shift (list): whoch way you want to shift to
"""
y = n // n_horizontal
new_y = (y + shift[1]) % n_vertical
Expand All @@ -513,14 +519,11 @@ def _next_cell_number(n_horizontal, n_vertical, n, shift):
def _crossing(n_x, n_y, n, shift):
"""tells you if the shift crosses PBC in the x or why direction

:param n_x: system size in x
:type n_x: int
:param n_y: system_size in y
:type n_y: int
:param n: what index you are currently at
:type n: int
:param shift: whoch way you want to shift to
:type shift: list
Args:
n_x (int): system size in x
n_y (int): system_size in y
n (int): what index you are currently at
shift (list): whoch way you want to shift to
"""

x = n % n_x
Expand All @@ -545,18 +548,18 @@ def tile_unit_cell(
) -> Lattice:
"""given a description of a unit cell, this tiles it to make a full lattice

:param unit_points: coordinates of points in the unit cell
:type unit_points: np.ndarray
:param unit_edges: indices of edges in unit cell
:type unit_edges: np.ndarray
:param unit_crossing: whether the edges cross to the next unit cell in x and y direction
:type unit_crossing: np.ndarray
:param unit_cell_dimensions: size of unit cell
:type unit_cell_dimensions: np.ndarray
:param n_xy: number of tilings you want. if this is iterable then assume it has the form [nx, ny]. If an int then we assume we want [n,n]
:type n_xy: int or list
:return: the final lattice
:rtype: Lattice
Args:
unit_points (np.ndarray): coordinates of points in the unit cell
unit_edges (np.ndarray): indices of edges in unit cell
unit_crossing (np.ndarray): whether the edges cross to the next
unit cell in x and y direction
unit_cell_dimensions (np.ndarray): size of unit cell
n_xy (int or list): number of tilings you want. if this is
iterable then assume it has the form [nx, ny]. If an int
then we assume we want [n,n]

Returns:
Lattice: the final lattice
"""

try:
Expand Down Expand Up @@ -606,11 +609,14 @@ def tile_unit_cell(
def single_plaquette(n_sides: int) -> Lattice:
"""Makes a graph consisting of a single plaquette with n_sides sides

:param n_sides: how many sides the polygon should have
:type n_sides: int
:raises Exception: n_sides must be >2
:return: a lattice containing a single polygon
:rtype: Lattice
Args:
n_sides (int): how many sides the polygon should have

Raises:
Exception: n_sides must be >2

Returns:
Lattice: a lattice containing a single polygon
"""

if n_sides < 3:
Expand Down Expand Up @@ -656,14 +662,13 @@ def make_amorphous(
):
"""Makes an amorphous lattice with L**2 plaquettes

:param L: The lattice will have L**2 plaquettes
:type L: int
Args:
L (int): The lattice will have L**2 plaquettes
return_points (bool): if True returns Lattice, coloring, ground
state ujk, original_random_points

:param return_points: if True returns Lattice, coloring, ground state ujk, original_random_points
:type return_points: bool

:return: Lattice, coloring, ground state ujk
:rtype: Lattice
Returns:
Lattice: Lattice, coloring, ground state ujk
"""
if rng is None:
rng = np.random.default_rng()
Expand Down
57 changes: 27 additions & 30 deletions src/koala/flux_finder/flux_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@
from .pathfinding import straight_line_length, periodic_straight_line_length, path_between_plaquettes

def fluxes_from_bonds(l, bonds, real = True) -> np.ndarray:
"""
Given a lattice l and a set of bonds = +/-1 defined on the edges of the lattice, calculate the fluxes.
"""Given a lattice l and a set of bonds = +/-1 defined on the edges of the lattice, calculate the fluxes.
The fluxes are defined on each plaquette as the the product of each bond in the direction,
with the sign fliped otherwise.

:param l: The lattice.
:type l: Lattice
:param bonds: The bond variables +1 or -1
:type bonds: np.ndarray
:return: fluxes
:rtype: np.ndarray
Args:
l (Lattice): The lattice.
bonds (np.ndarray): The bond variables +1 or -1

Returns:
np.ndarray: fluxes
"""
fluxes = np.zeros(len(l.plaquettes), dtype = 'int') if real else np.zeros(len(l.plaquettes), dtype = 'complex')

Expand All @@ -36,11 +35,12 @@ def fluxes_from_bonds(l, bonds, real = True) -> np.ndarray:
def fluxes_to_labels(fluxes: np.ndarray) -> np.ndarray:
"""Remaps fluxes from the set {1,-1} to labels in the form {0,1} for plotting.

:param fluxes: Fluxes in the format +1 or -1
:type fluxes: np.ndarray
:return: labels in [0,1]
:rtype: np.ndarray
"""
Args:
fluxes (np.ndarray): Fluxes in the format +1 or -1

Returns:
np.ndarray: labels in [0,1]
"""
return ((1 - fluxes)//2).astype(np.int8)

def _random_bonds(l : Lattice) -> np.ndarray:
Expand All @@ -61,8 +61,7 @@ def _greedy_plaquette_pairing(plaquettes, distance_func):
return np.array(pairs)

def _flip_adjacent_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray):
"""
See docs for find_flux_sector, this helper method implements step 2)
"""See docs for find_flux_sector, this helper method implements step 2)
which is that it looks for adjacent -1 fluxes and flips their edges
"""
for edge_index, (p_a, p_b) in enumerate(l.edges.adjacent_plaquettes):
Expand All @@ -82,9 +81,7 @@ def _flip_adjacent_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray):
return bonds, fluxes

def _flip_isolated_fluxes(l : Lattice, bonds : np.ndarray, fluxes : np.ndarray):
"""
See docs for find_flux_sector, this helper method implements step 3-5)
"""
"""See docs for find_flux_sector, this helper method implements step 3-5)"""
indices_to_flip = np.where(fluxes == -1)[0]

def pos(p): return l.plaquettes[p].center
Expand All @@ -102,16 +99,15 @@ def distance_func(a,b): return straight_line_length(pos(a), pos(b))
def find_flux_sector(l: Lattice, target_flux_sector : np.ndarray = None,
initial_bond_guess : np.ndarray = None,
):
"""
Find a bond configuration that produces the given flux sector for the lattice l.

"""Find a bond configuration that produces the given flux sector for the lattice l.

The high level method is:
1) Figure out which fluxes need to flip using fluxes_to_flip = target_flux_sector / initial_flux_sector
2) Look for any adjacent -1 fluxes in fluxes_to_flip that can be anhilated by just flipping 1 edge.
3) Pair the remaining fluxes off into close-ish pairs
4) Use A* to find a path between each pair.
5) Flip all the edges along each path.

Where:
A bond configuration is an assignment of +/-1 to each bond.
A flux sector is an assignment of +/-1 to even plaquette and +/-i to odd plaquettes.
Expand Down Expand Up @@ -145,14 +141,15 @@ def find_flux_sector(l: Lattice, target_flux_sector : np.ndarray = None,
def n_to_ujk_flipped(n: int, ujk: np.ndarray, min_spanning_set: np.ndarray):
"""given an integer n in the 0 - 2^(number of edges in spanning tree), this code flips the edges of ujk in the spanning tree in the combination given by the binary representation of n. Useful for exhaustively searching over the entire flux space of a lattice.

:param n: number determining the flip configuration
:type n: int
:param ujk: the edge signs of the wholelattice
:type ujk: np.ndarray( ±1 )
:param min_spanning_set: an array containing a minimum set of edges that form a plaquete-spanning tree on the system
:type min_spanning_set: np.ndarray( int )
:return: a flipped set of ujk
:rtype: np.ndarray( ±1 )
Args:
n (int): number determining the flip configuration
ujk (np.ndarray( ±1 )): the edge signs of the wholelattice
min_spanning_set (np.ndarray( int )): an array containing a
minimum set of edges that form a plaquete-spanning tree on
the system

Returns:
np.ndarray( ±1 ): a flipped set of ujk
"""
n_in_tree = len(min_spanning_set)
str_format = '0' + str(n_in_tree) + 'b'
Expand Down
Loading