Skip to content

Commit

Permalink
Converted and formatted circuit drawings, need to import this properl…
Browse files Browse the repository at this point in the history
…yinto quantum circuit!
  • Loading branch information
brennanfreeze committed Aug 25, 2024
1 parent a42ef76 commit 9283da6
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/circuit_drawing/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .circuit_drawing import *
115 changes: 115 additions & 0 deletions src/circuit_drawing/circuit_drawing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from .drawings import *
from .wire import Wire


class CircuitDrawing:
def __init__(self, qubits: int):
self.qubits = qubits
self.circuit_queue = []
self.max_length = 0
for _ in range(qubits):
self.circuit_queue.append(Wire())

def equal_length(self) -> None:
for i in range(self.qubits):
while self.circuit_queue[i].length < self.max_length:
self.add_drawing(horizontal_line(), i)

def add_drawing(self, drawing: str, qubit: int) -> None:
self.circuit_queue[qubit].add(drawing)
self.max_length = max(self.max_length, self.circuit_queue[qubit].length)

def insert_single(self, gate: str, qubit: int) -> None:
to_insert = self.max_length - 1
if self.max_length:
while (
to_insert > 0
and self.circuit_queue[qubit].at(to_insert) == horizontal_line()
):
to_insert -= 1
if self.circuit_queue[qubit].at(to_insert) != horizontal_line():
to_insert += 1
self.circuit_queue[qubit].insert(to_insert, single_gate(gate))
self.max_length = max(self.max_length, self.circuit_queue[qubit].length)
else:
self.add_drawing(single_gate(gate), qubit)
self.equal_length()

def two_qubit(self, qubit_1: int, qubit_2: int, gate=None) -> None:
self.equal_length()
start = min(qubit_1, qubit_2)
end = max(qubit_1, qubit_2)
for i in range(start + 1, end):
self.add_drawing(multi_connect(), i)
if gate:
self.add_drawing(multi_control(is_end=qubit_1 > qubit_2), qubit_1)
self.add_drawing(
single_gate(gate, is_controlled=True, is_start=qubit_1 > qubit_2),
qubit_2,
)
else:
self.add_drawing(swap_point(), qubit_1)
self.add_drawing(swap_point(), qubit_2)
self.equal_length()

def add_multi(self, gate: str, controls, target: int) -> None:
controls.append(target)
self.equal_length()
for i in range(self.qubits):
if i == target:
if target <= min(controls):
self.add_drawing(
single_gate(gate, is_controlled=True, is_start=True), i
)
else:
self.add_drawing(single_gate(gate, is_controlled=True), i)
elif min(controls) == i:
self.add_drawing(multi_control(), i)
elif max(controls) == i:
self.add_drawing(multi_control(is_end=True), i)
elif i in controls:
self.add_drawing(multi_control(is_connector=True), i)
elif i in range(min(controls), max(controls)):
self.add_drawing(multi_connect(), i)
self.equal_length()

def add_swap(self, qubit_1, qubit_2) -> None:
self.two_qubit(qubit_1=qubit_1, qubit_2=qubit_2)

def add_control(self, gate, control, target) -> None:
self.two_qubit(qubit_1=control, qubit_2=target, gate=gate)

def add_block(self, gate: str, qubits) -> None:
center = (max(qubits) + min(qubits)) // 2
for i in range(self.qubits):
if i == center:
self.add_drawing(block_gate(gate), i)
elif i == min(qubits):
self.add_drawing(block_top(), i)
elif i == max(qubits):
self.add_drawing(block_bottom(), i)
elif i in range(min(qubits), max(qubits)) or i in qubits:
self.add_drawing(block_connect(), i)
self.equal_length()

def make_wire(self, wire, i) -> str:
top = [" "]
middle = ["q" + str(i) + "─"]
bottom = [" "]
if self.qubits >= 10:
top += " "
middle += "─" if i >= 10 else "──"
bottom += " "
for item in range(len(wire)):
size = len(wire[item]) // 3
for counter in range(size):
top[-1] += wire[item][counter]
middle[-1] += wire[item][counter + size]
bottom[-1] += wire[item][counter + size * 2]
return "".join(top) + "\n" + "".join(middle) + "\n" + "".join(bottom) + "\n"

def make(self) -> str:
output = ""
for i in range(len(self.circuit_queue)):
output += self.make_wire(self.circuit_queue[i].content, i)
return output
52 changes: 52 additions & 0 deletions src/circuit_drawing/drawings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
def multi_control(is_connector: bool = False, is_end: bool = False) -> str:
res = " ──■── │ "
if is_connector:
res = " │ ──■── │ "
elif is_end:
res = " │ ──■── "
return res


def multi_connect() -> str:
return " │ ──┼── │ "


def horizontal_line() -> str:
return " ───── "


def block_bottom() -> str:
return "│ │┤ ├└───┘"


def block_connect():
return "│ │┤ ├│ │"


def block_gate(gate: str) -> str:
return "│ │┤MUL├│ │"


def block_top() -> str:
return "┌───┐┤ ├│ │"


def single_gate(gate, is_controlled: bool = False, is_start: bool = False):
top = "┌─┴─┐" if (is_controlled and not is_start) else "┌───┐"
middle = "┤"
match len(gate):
case 1:
middle += " " + gate + " ├"
case 2:
middle += gate + " ├"
case _:
middle += gate + "├"
return top + middle + ("└───┘" if not is_start else "└─┬─┘")


def swap_point():
return " ──╳── "


def vertical_line():
return " │ "
17 changes: 17 additions & 0 deletions src/circuit_drawing/wire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Wire:
def __init__(self):
self.length = 0
self.content = []

def add(self, to_add: str) -> None:
self.length += 1
self.content.append(to_add)

def insert(self, to_insert: int, to_add: str) -> None:
if to_insert >= self.length:
self.add(to_add)
else:
self.content[to_insert] = to_add

def at(self, index: int) -> str:
return "" if index >= self.length else self.content[index]

0 comments on commit 9283da6

Please sign in to comment.