# Path: src/common.py
# def removekey(d, key):
# def colinear(p0, p1, p2):
# def manhattan_dist(A,B):
# def euclidean_dist(A,B):
# def Charge(X_charge = 0, Z_charge = 0):
# def Sign(count, num_sides):
#     def __init__(self, depth, dimension = 2):
#     def Syndrome(self, type, charge_type):
#     def PhysicalErrors(self):
#     def distance(self, type, node1, node2):
#     def Assessment(self):
# class Code:


from decoders import *
from matplotlib import path
from math import floor
from src import common
import sys
import networkx as nx
import numpy as np
import itertools
                        loops_graph.add_edge(*edge)
        Exts = code.External['red']+code.External['blue']+code.External['green']

        code, loops_graph = correctLoops(code, loops_graph, charge_type)
        while hasConnectedBoundaries(code, loops_graph, Exts):
            ext1, ext2 = connectedBoundaries(loops_graph, Exts)
            code, loops_graph = makeBoundLoop(code, loops_graph, ext1, ext2)
            code, loops_graph = correctLoops(code, loops_graph, charge_type)
        return code

def correctLoops(code, loops_graph, charge_type):
    while nx.cycle_basis(loops_graph) != []:
        cycle = nx.cycle_basis(loops_graph)[0]
        loop = path.Path(cycle)
        for data in code.Primal.nodes():
            if loop.contains_points([data]) == [True]:
                charge = code.Primal.node[data]['charge'][charge_type]
                code.Primal.node[data]['charge'][charge_type] = (charge + 1)%2

        l = len(cycle)
        for i in range(l):
            n1, n2 = cycle[i], cycle[(i+1)%l]
            loops_graph.remove_edge(*(n1,n2))

    return code, loops_graph

def DSP_Path(DualGraph, terminal1, terminal2):
    return nx.shortest_path(DualGraph, terminal1, terminal2)

def DSP_AssociatedExternal(int_node, external_nodes):

# Path: src/common.py
# def removekey(d, key):
# def colinear(p0, p1, p2):
# def manhattan_dist(A,B):
# def euclidean_dist(A,B):
# def Charge(X_charge = 0, Z_charge = 0):
# def Sign(count, num_sides):
#     def __init__(self, depth, dimension = 2):
#     def Syndrome(self, type, charge_type):
#     def PhysicalErrors(self):
#     def distance(self, type, node1, node2):
#     def Assessment(self):
# class Code:


# Path: src/decoders/dsp.py
from decoders import *
from matplotlib import path
from math import floor
from src import common
import sys
import networkx as nx
import numpy as np
import itertools

                        loops_graph.add_edge(*edge)
        Exts = code.External['red']+code.External['blue']+code.External['green']

        code, loops_graph = correctLoops(code, loops_graph, charge_type)
        while hasConnectedBoundaries(code, loops_graph, Exts):
            ext1, ext2 = connectedBoundaries(loops_graph, Exts)
            code, loops_graph = makeBoundLoop(code, loops_graph, ext1, ext2)
            code, loops_graph = correctLoops(code, loops_graph, charge_type)
        return code

def correctLoops(code, loops_graph, charge_type):
    while nx.cycle_basis(loops_graph) != []:
        cycle = nx.cycle_basis(loops_graph)[0]
        loop = path.Path(cycle)
        for data in code.Primal.nodes():
            if loop.contains_points([data]) == [True]:
                charge = code.Primal.node[data]['charge'][charge_type]
                code.Primal.node[data]['charge'][charge_type] = (charge + 1)%2

        l = len(cycle)
        for i in range(l):
            n1, n2 = cycle[i], cycle[(i+1)%l]
            loops_graph.remove_edge(*(n1,n2))

    return code, loops_graph

def DSP_Path(DualGraph, terminal1, terminal2):
    return nx.shortest_path(DualGraph, terminal1, terminal2)

def DSP_AssociatedExternal(int_node, external_nodes):

    return min(external_nodes, key = lambda x:common.euclidean_dist(int_node, x))