Anders and Briegel in Python
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

119 рядки
3.9KB

  1. """
  2. Provides an extremely basic graph structure, based on neighbour lists
  3. """
  4. from collections import defaultdict
  5. import itertools as it
  6. import clifford
  7. import json
  8. class GraphState(object):
  9. def __init__(self):
  10. self.ngbh = defaultdict(set)
  11. self.vops = defaultdict(int)
  12. def add_vertex(self, v):
  13. """ Add a vertex if it doesn't already exist """
  14. if not v in self.ngbh:
  15. self.ngbh[v] = set()
  16. self.vops[v] = clifford.by_name["hadamard"]
  17. def add_edge(self, v1, v2):
  18. """ Add an edge between two vertices in the self """
  19. if not v1 in self.ngbh:
  20. self.vops[v1] = clifford.by_name["hadamard"]
  21. if not v2 in self.ngbh:
  22. self.vops[v2] = clifford.by_name["hadamard"]
  23. self.ngbh[v1].add(v2)
  24. self.ngbh[v2].add(v1)
  25. def del_edge(self, v1, v2):
  26. """ Delete an edge between two vertices in the self """
  27. self.ngbh[v1].remove(v2)
  28. self.ngbh[v2].remove(v1)
  29. def has_edge(self, v1, v2):
  30. """ Test existence of an edge between two vertices in the self """
  31. return v2 in self.ngbh[v1]
  32. def toggle_edge(self, v1, v2):
  33. """ Toggle an edge between two vertices in the self """
  34. if self.has_edge(v1, v2):
  35. self.del_edge(v1, v2)
  36. else:
  37. self.add_edge(v1, v2)
  38. def edgelist(self):
  39. """ Describe a graph as an edgelist """
  40. edges = frozenset(tuple(sorted((i, n)))
  41. for i, v in self.ngbh.items()
  42. for n in v)
  43. return [tuple(e) for e in edges]
  44. def remove_vop(self, a, avoid):
  45. """ Reduces VOP[a] to the identity """
  46. others = self.ngbh[a] - {avoid}
  47. swap_qubit = others.pop() if others else avoid
  48. for v in reversed(clifford.decompositions[self.vops[a]]):
  49. self.local_complementation(a if v == "x" else swap_qubit)
  50. def local_complementation(self, v):
  51. """ As defined in LISTING 1 of Anders & Briegel """
  52. for i, j in it.combinations(self.ngbh[v], 2):
  53. self.toggle_edge(i, j)
  54. # Update VOPs: TODO check ordering and replace by self.act_local_rotation
  55. self.vops[v] = clifford.times_table[
  56. self.vops[v]][clifford.by_name["sqx"]]
  57. for i in self.ngbh[v]:
  58. self.vops[i] = clifford.times_table[
  59. self.vops[i]][clifford.by_name["msqz"]]
  60. def act_local_rotation(self, a, op):
  61. """ Act a local rotation """
  62. self.vops[a] = clifford.times_table[op,self.vops[a]]
  63. def act_cz(self, a, b):
  64. """ Act a controlled-phase gate on two qubits """
  65. if self.ngbh[a] - {b}:
  66. self.remove_vop(a, b)
  67. if self.ngbh[b] - {a}:
  68. self.remove_vop(b, a)
  69. if self.ngbh[a] - {b}:
  70. self.remove_vop(a, b)
  71. edge = self.has_edge(a, b)
  72. # TODO put this in a new function for diff hook
  73. new_edge, self.vops[a], self.vops[b] = clifford.cz_table[edge, self.vops[a], self.vops[b]]
  74. if new_edge != edge:
  75. self.toggle_edge(a, b)
  76. def __str__(self):
  77. """ Represent as a string for quick debugging """
  78. return "graph:\n vops: {}\n ngbh: {}\n"\
  79. .format(str(dict(self.vops)), str(dict(self.ngbh)))
  80. def to_json(self):
  81. """ Convert the graph to JSON form """
  82. ngbh = {key: tuple(value) for key, value in self.ngbh.items()}
  83. return json.dumps({"vops": self.vops, "ngbh": ngbh})
  84. class DiffedGraphState(GraphState):
  85. """ Just like a graph state, but tracks changes for rendering purposes """
  86. def __init__(self):
  87. GraphState.__init__(self)
  88. self.diff = []
  89. def add_vertex(self, v):
  90. GraphState.add_vertex(self, v)
  91. self.diff.append("add_vertex {}".format(v))
  92. def add_edge(self, v1, v2):
  93. GraphState.add_edge(self, v1, v2)
  94. self.diff.append("add_edge {} {}".format(v1, v2))