pktron 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pktron-0.1.0/LICENSE +22 -0
- pktron-0.1.0/PKG-INFO +55 -0
- pktron-0.1.0/README.md +28 -0
- pktron-0.1.0/pktron/__init__.py +4 -0
- pktron-0.1.0/pktron/algorithms.py +44 -0
- pktron-0.1.0/pktron/backend.py +82 -0
- pktron-0.1.0/pktron/gates.py +92 -0
- pktron-0.1.0/pktron/quantum.py +94 -0
- pktron-0.1.0/pktron/visualization.py +61 -0
- pktron-0.1.0/pktron.egg-info/PKG-INFO +55 -0
- pktron-0.1.0/pktron.egg-info/SOURCES.txt +14 -0
- pktron-0.1.0/pktron.egg-info/dependency_links.txt +1 -0
- pktron-0.1.0/pktron.egg-info/requires.txt +3 -0
- pktron-0.1.0/pktron.egg-info/top_level.txt +1 -0
- pktron-0.1.0/setup.cfg +4 -0
- pktron-0.1.0/setup.py +26 -0
pktron-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2025 CETQAP
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
pktron-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pktron
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A quantum circuit simulator with statevector, stabilizer, and MPS backends
|
|
5
|
+
Home-page: https://github.com/cetqap/pktron
|
|
6
|
+
Author: CETQAP
|
|
7
|
+
Author-email: info@thecetqap.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy>=1.21.0
|
|
15
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
16
|
+
Requires-Dist: quimb>=1.4.0
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# PKTron: Pakistan Tron Quantum Simulator
|
|
29
|
+
|
|
30
|
+
PKTron is a 100 Qubit quantum circuit simulator and Pakistan's 1st Quantum Simulator for 100 Qubits - Version 0.1.0 supporting statevector, stabilizer, and MPS backends. It provides tools for quantum circuit simulation, visualization, and quantum algorithms.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
```bash
|
|
34
|
+
pip install pktron
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
```python
|
|
39
|
+
from pktron import QuantumCircuit, execute, StatevectorSimulator
|
|
40
|
+
from pktron.gates import h, cnot
|
|
41
|
+
|
|
42
|
+
qc = QuantumCircuit(2, "statevector")
|
|
43
|
+
h(qc, 0)
|
|
44
|
+
cnot(qc, 0, 1)
|
|
45
|
+
result = execute(qc, StatevectorSimulator())
|
|
46
|
+
print(result.get_counts())
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
- Quantum circuit simulation with multiple backends
|
|
51
|
+
- Visualization of quantum states (histogram, Bloch sphere)
|
|
52
|
+
- Basic quantum algorithms (e.g., Quantum Treasure Hunt)
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
MIT License
|
pktron-0.1.0/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# PKTron: Pakistan Tron Quantum Simulator
|
|
2
|
+
|
|
3
|
+
PKTron is a 100 Qubit quantum circuit simulator and Pakistan's 1st Quantum Simulator for 100 Qubits - Version 0.1.0 supporting statevector, stabilizer, and MPS backends. It provides tools for quantum circuit simulation, visualization, and quantum algorithms.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
```bash
|
|
7
|
+
pip install pktron
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```python
|
|
12
|
+
from pktron import QuantumCircuit, execute, StatevectorSimulator
|
|
13
|
+
from pktron.gates import h, cnot
|
|
14
|
+
|
|
15
|
+
qc = QuantumCircuit(2, "statevector")
|
|
16
|
+
h(qc, 0)
|
|
17
|
+
cnot(qc, 0, 1)
|
|
18
|
+
result = execute(qc, StatevectorSimulator())
|
|
19
|
+
print(result.get_counts())
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
- Quantum circuit simulation with multiple backends
|
|
24
|
+
- Visualization of quantum states (histogram, Bloch sphere)
|
|
25
|
+
- Basic quantum algorithms (e.g., Quantum Treasure Hunt)
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
MIT License
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
from .gates import h, rx, ry, cnot, cz, s, toffoli, t
|
|
4
|
+
|
|
5
|
+
def quantum_flip(circuit):
|
|
6
|
+
h(circuit, 0)
|
|
7
|
+
if circuit.num_qubits > 1:
|
|
8
|
+
cnot(circuit, 0, 1)
|
|
9
|
+
rx(circuit, 0, np.pi/4)
|
|
10
|
+
circuit.gate_history.append("Quantum Flip")
|
|
11
|
+
|
|
12
|
+
def super_quantum_dance(circuit):
|
|
13
|
+
h(circuit, 0)
|
|
14
|
+
if circuit.num_qubits > 1:
|
|
15
|
+
ry(circuit, 1, np.pi/2)
|
|
16
|
+
cnot(circuit, 0, 1)
|
|
17
|
+
if circuit.num_qubits > 2:
|
|
18
|
+
toffoli(circuit, 0, 1, 2)
|
|
19
|
+
t(circuit, 0)
|
|
20
|
+
circuit.gate_history.append("Super Quantum Dance")
|
|
21
|
+
|
|
22
|
+
def quantum_treasure_hunt(circuit):
|
|
23
|
+
target_state = 2**circuit.num_qubits - 1
|
|
24
|
+
h(circuit, 0)
|
|
25
|
+
if circuit.num_qubits > 1:
|
|
26
|
+
cnot(circuit, 0, 1)
|
|
27
|
+
ry(circuit, 1, np.random.uniform(0, np.pi))
|
|
28
|
+
rx(circuit, 0, np.random.uniform(0, np.pi))
|
|
29
|
+
outcome, probs = circuit.measure()
|
|
30
|
+
score = probs[target_state] * 100
|
|
31
|
+
circuit.gate_history.append(f"Quantum Treasure Hunt (Score: {score:.1f})")
|
|
32
|
+
return score
|
|
33
|
+
|
|
34
|
+
def quantum_magic_spin(circuit):
|
|
35
|
+
target_state = 0
|
|
36
|
+
rx(circuit, 0, np.random.uniform(0, 2*np.pi))
|
|
37
|
+
if circuit.num_qubits > 1:
|
|
38
|
+
ry(circuit, 1, np.random.uniform(0, np.pi))
|
|
39
|
+
cz(circuit, 0, 1)
|
|
40
|
+
s(circuit, 0)
|
|
41
|
+
outcome, probs = circuit.measure()
|
|
42
|
+
score = probs[target_state] * 100
|
|
43
|
+
circuit.gate_history.append(f"Quantum Magic Spin (Score: {score:.1f})")
|
|
44
|
+
return score
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
import quimb.tensor as qtn
|
|
4
|
+
from .quantum import QuantumCircuit
|
|
5
|
+
|
|
6
|
+
class StatevectorSimulator:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.name = "statevector_simulator"
|
|
9
|
+
|
|
10
|
+
def run(self, circuit, shots=1024):
|
|
11
|
+
counts = {}
|
|
12
|
+
for _ in range(shots):
|
|
13
|
+
outcome, _ = circuit.measure()
|
|
14
|
+
state = f"{outcome:0{circuit.num_qubits}b}"
|
|
15
|
+
counts[state] = counts.get(state, 0) + 1
|
|
16
|
+
return Result(counts, circuit)
|
|
17
|
+
|
|
18
|
+
class StabilizerSimulator:
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.name = "stabilizer_simulator"
|
|
21
|
+
|
|
22
|
+
def run(self, circuit, shots=1024):
|
|
23
|
+
tableau = np.eye(circuit.num_qubits, dtype=int)
|
|
24
|
+
affected = set()
|
|
25
|
+
for gate in circuit.gate_history:
|
|
26
|
+
parts = [p for p in gate.split() if p.isdigit()]
|
|
27
|
+
if parts:
|
|
28
|
+
affected.update(int(p) for p in parts[:2])
|
|
29
|
+
counts = {}
|
|
30
|
+
for _ in range(shots):
|
|
31
|
+
outcome = [0] * circuit.num_qubits
|
|
32
|
+
for qb in affected:
|
|
33
|
+
outcome[qb] = np.random.randint(0, 2)
|
|
34
|
+
state = ''.join(map(str, outcome))
|
|
35
|
+
counts[state] = counts.get(state, 0) + 1
|
|
36
|
+
return Result(counts, circuit)
|
|
37
|
+
|
|
38
|
+
class MPS_Simulator:
|
|
39
|
+
def __init__(self, max_bond_dim=100):
|
|
40
|
+
self.name = "mps_simulator"
|
|
41
|
+
self.max_bond_dim = max_bond_dim
|
|
42
|
+
|
|
43
|
+
def run(self, circuit, shots=1024):
|
|
44
|
+
if circuit.num_qubits > 20:
|
|
45
|
+
print("MPS: Large n, default sampling.")
|
|
46
|
+
counts = {'0' * circuit.num_qubits: shots}
|
|
47
|
+
return Result(counts, circuit)
|
|
48
|
+
try:
|
|
49
|
+
mps = qtn.MPS_computational_state('0' * circuit.num_qubits)
|
|
50
|
+
for gate in circuit.gate_history[:2]:
|
|
51
|
+
if 'H on qubit' in gate:
|
|
52
|
+
qb = int(gate.split()[-1])
|
|
53
|
+
mps.apply_gate(qtn.pauli('H'), [qb])
|
|
54
|
+
elif 'Rx(' in gate:
|
|
55
|
+
qb = int(gate.split()[-3].strip(')'))
|
|
56
|
+
theta = float(gate.split('(')[1].split(')')[0])
|
|
57
|
+
mps.apply_gate(qtn.gate_Rx(theta), [qb])
|
|
58
|
+
mps.compress(max_bond=self.max_bond_dim)
|
|
59
|
+
counts = {'0' * circuit.num_qubits: shots}
|
|
60
|
+
return Result(counts, circuit)
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print(f"MPS error: {e}. Falling back to statevector.")
|
|
63
|
+
return StatevectorSimulator().run(QuantumCircuit(min(circuit.num_qubits, 10), "statevector"), shots)
|
|
64
|
+
|
|
65
|
+
class Result:
|
|
66
|
+
def __init__(self, counts, circuit):
|
|
67
|
+
self.counts = counts
|
|
68
|
+
self.circuit = circuit
|
|
69
|
+
|
|
70
|
+
def get_counts(self):
|
|
71
|
+
return self.counts
|
|
72
|
+
|
|
73
|
+
def execute(circuits, backend=None, shots=1024):
|
|
74
|
+
if backend is None:
|
|
75
|
+
backend = StatevectorSimulator()
|
|
76
|
+
if isinstance(circuits, QuantumCircuit):
|
|
77
|
+
return backend.run(circuits, shots)
|
|
78
|
+
else:
|
|
79
|
+
results = []
|
|
80
|
+
for circuit in circuits:
|
|
81
|
+
results.append(backend.run(circuit, shots))
|
|
82
|
+
return results
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
def h(circuit, qubit):
|
|
5
|
+
H = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
|
|
6
|
+
circuit._apply_single_qubit_gate(H, qubit)
|
|
7
|
+
circuit.gate_history.append(f"H on qubit {qubit}")
|
|
8
|
+
|
|
9
|
+
def x(circuit, qubit):
|
|
10
|
+
X = np.array([[0, 1], [1, 0]])
|
|
11
|
+
circuit._apply_single_qubit_gate(X, qubit)
|
|
12
|
+
circuit.gate_history.append(f"X on qubit {qubit}")
|
|
13
|
+
|
|
14
|
+
def y(circuit, qubit):
|
|
15
|
+
Y = np.array([[0, -1j], [1j, 0]])
|
|
16
|
+
circuit._apply_single_qubit_gate(Y, qubit)
|
|
17
|
+
circuit.gate_history.append(f"Y on qubit {qubit}")
|
|
18
|
+
|
|
19
|
+
def z(circuit, qubit):
|
|
20
|
+
Z = np.array([[1, 0], [0, -1]])
|
|
21
|
+
circuit._apply_single_qubit_gate(Z, qubit)
|
|
22
|
+
circuit.gate_history.append(f"Z on qubit {qubit}")
|
|
23
|
+
|
|
24
|
+
def s(circuit, qubit):
|
|
25
|
+
S = np.array([[1, 0], [0, 1j]])
|
|
26
|
+
circuit._apply_single_qubit_gate(S, qubit)
|
|
27
|
+
circuit.gate_history.append(f"S on qubit {qubit}")
|
|
28
|
+
|
|
29
|
+
def sdg(circuit, qubit):
|
|
30
|
+
Sdg = np.array([[1, 0], [0, -1j]])
|
|
31
|
+
circuit._apply_single_qubit_gate(Sdg, qubit)
|
|
32
|
+
circuit.gate_history.append(f"S† on qubit {qubit}")
|
|
33
|
+
|
|
34
|
+
def t(circuit, qubit):
|
|
35
|
+
T = np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]])
|
|
36
|
+
circuit._apply_single_qubit_gate(T, qubit)
|
|
37
|
+
circuit.gate_history.append(f"T on qubit {qubit}")
|
|
38
|
+
|
|
39
|
+
def tdg(circuit, qubit):
|
|
40
|
+
Tdg = np.array([[1, 0], [0, np.exp(-1j * np.pi / 4)]])
|
|
41
|
+
circuit._apply_single_qubit_gate(Tdg, qubit)
|
|
42
|
+
circuit.gate_history.append(f"T† on qubit {qubit}")
|
|
43
|
+
|
|
44
|
+
def rx(circuit, qubit, theta):
|
|
45
|
+
cos = np.cos(theta / 2)
|
|
46
|
+
sin = np.sin(theta / 2)
|
|
47
|
+
RX = np.array([[cos, -1j * sin], [-1j * sin, cos]])
|
|
48
|
+
circuit._apply_single_qubit_gate(RX, qubit)
|
|
49
|
+
circuit.gate_history.append(f"Rx({theta:.2f}) on qubit {qubit}")
|
|
50
|
+
|
|
51
|
+
def ry(circuit, qubit, theta):
|
|
52
|
+
cos = np.cos(theta / 2)
|
|
53
|
+
sin = np.sin(theta / 2)
|
|
54
|
+
RY = np.array([[cos, -sin], [sin, cos]])
|
|
55
|
+
circuit._apply_single_qubit_gate(RY, qubit)
|
|
56
|
+
circuit.gate_history.append(f"Ry({theta:.2f}) on qubit {qubit}")
|
|
57
|
+
|
|
58
|
+
def rz(circuit, qubit, theta):
|
|
59
|
+
RZ = np.array([[np.exp(-1j * theta / 2), 0], [0, np.exp(1j * theta / 2)]])
|
|
60
|
+
circuit._apply_single_qubit_gate(RZ, qubit)
|
|
61
|
+
circuit.gate_history.append(f"Rz({theta:.2f}) on qubit {qubit}")
|
|
62
|
+
|
|
63
|
+
def cnot(circuit, control, target):
|
|
64
|
+
gate = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
|
|
65
|
+
circuit._apply_two_qubit_gate(gate, control, target)
|
|
66
|
+
circuit.gate_history.append(f"CNOT control {control} target {target}")
|
|
67
|
+
|
|
68
|
+
def cz(circuit, control, target):
|
|
69
|
+
gate = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]])
|
|
70
|
+
circuit._apply_two_qubit_gate(gate, control, target)
|
|
71
|
+
circuit.gate_history.append(f"CZ control {control} target {target}")
|
|
72
|
+
|
|
73
|
+
def cy(circuit, control, target):
|
|
74
|
+
gate = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]])
|
|
75
|
+
circuit._apply_two_qubit_gate(gate, control, target)
|
|
76
|
+
circuit.gate_history.append(f"CY control {control} target {target}")
|
|
77
|
+
|
|
78
|
+
def swap(circuit, qubit1, qubit2):
|
|
79
|
+
gate = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
|
|
80
|
+
circuit._apply_two_qubit_gate(gate, qubit1, qubit2)
|
|
81
|
+
circuit.gate_history.append(f"SWAP qubits {qubit1} and {qubit2}")
|
|
82
|
+
|
|
83
|
+
def toffoli(circuit, control1, control2, target):
|
|
84
|
+
if circuit.num_qubits < 3:
|
|
85
|
+
raise ValueError("Toffoli needs 3 qubits")
|
|
86
|
+
gate = np.eye(8, dtype=complex)
|
|
87
|
+
gate[6, 6] = 0
|
|
88
|
+
gate[6, 7] = 1
|
|
89
|
+
gate[7, 6] = 1
|
|
90
|
+
gate[7, 7] = 0
|
|
91
|
+
circuit._apply_three_qubit_gate(gate, control1, control2, target)
|
|
92
|
+
circuit.gate_history.append(f"Toffoli control {control1},{control2} target {target}")
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
class QuantumCircuit:
|
|
5
|
+
def __init__(self, num_qubits, backend_type="statevector"):
|
|
6
|
+
self.num_qubits = num_qubits
|
|
7
|
+
self.backend_type = backend_type.lower()
|
|
8
|
+
self._state = None
|
|
9
|
+
self.gate_history = []
|
|
10
|
+
|
|
11
|
+
def _allocate_state(self):
|
|
12
|
+
if self._state is None:
|
|
13
|
+
self._state = np.zeros(2**self.num_qubits, dtype=complex)
|
|
14
|
+
self._state[0] = 1.0
|
|
15
|
+
|
|
16
|
+
def get_state(self):
|
|
17
|
+
if self.backend_type == "statevector":
|
|
18
|
+
self._allocate_state()
|
|
19
|
+
return self._state
|
|
20
|
+
raise ValueError(f"get_state requires statevector backend, got {self.backend_type}")
|
|
21
|
+
|
|
22
|
+
def normalize(self):
|
|
23
|
+
if self.backend_type != "statevector" or self._state is None:
|
|
24
|
+
return
|
|
25
|
+
norm = np.sqrt(np.sum(np.abs(self._state)**2))
|
|
26
|
+
if norm > 0:
|
|
27
|
+
self._state /= norm
|
|
28
|
+
|
|
29
|
+
def _apply_single_qubit_gate(self, gate, qubit):
|
|
30
|
+
if qubit >= self.num_qubits:
|
|
31
|
+
raise ValueError("Bad qubit number!")
|
|
32
|
+
if self.backend_type == "statevector":
|
|
33
|
+
self._allocate_state()
|
|
34
|
+
full_gate = 1.0
|
|
35
|
+
for i in range(self.num_qubits):
|
|
36
|
+
if i == qubit:
|
|
37
|
+
full_gate = np.kron(full_gate, gate)
|
|
38
|
+
else:
|
|
39
|
+
full_gate = np.kron(full_gate, np.eye(2))
|
|
40
|
+
self._state = np.dot(full_gate, self._state)
|
|
41
|
+
self.normalize()
|
|
42
|
+
# For non-statevector, do nothing (history only)
|
|
43
|
+
|
|
44
|
+
def _apply_two_qubit_gate(self, gate, qubit1, qubit2):
|
|
45
|
+
if qubit1 == qubit2 or qubit1 >= self.num_qubits or qubit2 >= self.num_qubits:
|
|
46
|
+
raise ValueError("Bad qubit numbers!")
|
|
47
|
+
if self.backend_type == "statevector":
|
|
48
|
+
self._allocate_state()
|
|
49
|
+
qubits = sorted([qubit1, qubit2])
|
|
50
|
+
full_gate = 1.0
|
|
51
|
+
i = 0
|
|
52
|
+
while i < self.num_qubits:
|
|
53
|
+
if i == qubits[0]:
|
|
54
|
+
two_qubit_full = gate
|
|
55
|
+
for j in range(1, qubits[1] - qubits[0]):
|
|
56
|
+
two_qubit_full = np.kron(np.eye(2), two_qubit_full)
|
|
57
|
+
full_gate = np.kron(full_gate, two_qubit_full)
|
|
58
|
+
i = qubits[1] + 1
|
|
59
|
+
else:
|
|
60
|
+
full_gate = np.kron(full_gate, np.eye(2))
|
|
61
|
+
i += 1
|
|
62
|
+
self._state = np.dot(full_gate, self._state)
|
|
63
|
+
self.normalize()
|
|
64
|
+
# For non-statevector, do nothing
|
|
65
|
+
|
|
66
|
+
def _apply_three_qubit_gate(self, gate, qubit1, qubit2, qubit3):
|
|
67
|
+
if len(set([qubit1, qubit2, qubit3])) != 3 or max(qubit1, qubit2, qubit3) >= self.num_qubits:
|
|
68
|
+
raise ValueError("Bad qubit numbers!")
|
|
69
|
+
if self.backend_type == "statevector":
|
|
70
|
+
self._allocate_state()
|
|
71
|
+
qubits = sorted([qubit1, qubit2, qubit3])
|
|
72
|
+
full_gate = 1.0
|
|
73
|
+
i = 0
|
|
74
|
+
while i < self.num_qubits:
|
|
75
|
+
if i == qubits[0]:
|
|
76
|
+
three_qubit_full = gate
|
|
77
|
+
for j in range(1, qubits[2] - qubits[0]):
|
|
78
|
+
three_qubit_full = np.kron(np.eye(2), three_qubit_full)
|
|
79
|
+
full_gate = np.kron(full_gate, three_qubit_full)
|
|
80
|
+
i = qubits[2] + 1
|
|
81
|
+
else:
|
|
82
|
+
full_gate = np.kron(full_gate, np.eye(2))
|
|
83
|
+
i += 1
|
|
84
|
+
self._state = np.dot(full_gate, self._state)
|
|
85
|
+
self.normalize()
|
|
86
|
+
# For non-statevector, do nothing
|
|
87
|
+
|
|
88
|
+
def measure(self):
|
|
89
|
+
if self.backend_type != "statevector":
|
|
90
|
+
raise ValueError(f"Measure requires statevector backend, got {self.backend_type}")
|
|
91
|
+
self._allocate_state()
|
|
92
|
+
probs = np.abs(self._state)**2
|
|
93
|
+
outcome = np.random.choice(range(2**self.num_qubits), p=probs)
|
|
94
|
+
return outcome, probs
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from mpl_toolkits.mplot3d import Axes3D
|
|
5
|
+
|
|
6
|
+
def plot_histogram(circuit, shots=1024):
|
|
7
|
+
if circuit.backend_type != "statevector":
|
|
8
|
+
raise ValueError(f"Plot requires statevector backend, got {circuit.backend_type}")
|
|
9
|
+
if circuit.num_qubits > 10:
|
|
10
|
+
print("Warning: Large circuit, using low shots for plot.")
|
|
11
|
+
shots = 100
|
|
12
|
+
counts = {}
|
|
13
|
+
for _ in range(shots):
|
|
14
|
+
outcome, _ = circuit.measure()
|
|
15
|
+
state = f"{outcome:0{circuit.num_qubits}b}"
|
|
16
|
+
counts[state] = counts.get(state, 0) + 1
|
|
17
|
+
states = [f"|{i:0{circuit.num_qubits}b}⟩" for i in range(2**circuit.num_qubits)]
|
|
18
|
+
probs = [counts.get(f"{i:0{circuit.num_qubits}b}", 0) / shots for i in range(2**circuit.num_qubits)]
|
|
19
|
+
fig = plt.figure(figsize=(8, 6))
|
|
20
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
21
|
+
x = range(len(states))
|
|
22
|
+
y = [1] * len(states)
|
|
23
|
+
z = [0] * len(states)
|
|
24
|
+
dx = [0.4] * len(states)
|
|
25
|
+
dy = [0.4] * len(states)
|
|
26
|
+
dz = probs
|
|
27
|
+
colors = ['#FF9999', '#66B2FF', '#99FF99', '#FFCC99'][:len(states)]
|
|
28
|
+
ax.bar3d(x, y, z, dx, dy, dz, color=colors, alpha=0.8)
|
|
29
|
+
ax.set_xticks(x)
|
|
30
|
+
ax.set_xticklabels(states, rotation=45, ha='right')
|
|
31
|
+
ax.set_yticks([])
|
|
32
|
+
ax.set_zlabel('Probability', fontsize=12)
|
|
33
|
+
ax.set_title('PKTron Quantum Histogram', fontsize=14, color='darkblue')
|
|
34
|
+
ax.grid(True, linestyle='--', alpha=0.5)
|
|
35
|
+
plt.show()
|
|
36
|
+
return counts
|
|
37
|
+
|
|
38
|
+
def plot_bloch(circuit):
|
|
39
|
+
if circuit.backend_type != "statevector":
|
|
40
|
+
raise ValueError(f"Bloch requires statevector backend, got {circuit.backend_type}")
|
|
41
|
+
if circuit.num_qubits != 1:
|
|
42
|
+
raise ValueError("Bloch sphere is only for 1 qubit!")
|
|
43
|
+
psi = circuit.get_state()
|
|
44
|
+
x = 2 * np.real(psi[0] * np.conj(psi[1]))
|
|
45
|
+
y = 2 * np.imag(psi[0] * np.conj(psi[1]))
|
|
46
|
+
z = np.abs(psi[0])**2 - np.abs(psi[1])**2
|
|
47
|
+
fig = plt.figure(figsize=(6, 6))
|
|
48
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
49
|
+
u = np.linspace(0, 2 * np.pi, 20)
|
|
50
|
+
v = np.linspace(0, np.pi, 20)
|
|
51
|
+
x_sphere = np.outer(np.cos(u), np.sin(v))
|
|
52
|
+
y_sphere = np.outer(np.sin(u), np.sin(v))
|
|
53
|
+
z_sphere = np.outer(np.ones(np.size(u)), np.cos(v))
|
|
54
|
+
ax.plot_surface(x_sphere, y_sphere, z_sphere, color='b', alpha=0.1)
|
|
55
|
+
ax.scatter([x], [y], [z], color='red', s=100)
|
|
56
|
+
ax.plot([0, x], [0, y], [0, z], color='red', linewidth=2)
|
|
57
|
+
ax.set_xlabel('X')
|
|
58
|
+
ax.set_ylabel('Y')
|
|
59
|
+
ax.set_zlabel('Z')
|
|
60
|
+
ax.set_title('PKTron Bloch Sphere', fontsize=14, color='darkblue')
|
|
61
|
+
plt.show()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pktron
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A quantum circuit simulator with statevector, stabilizer, and MPS backends
|
|
5
|
+
Home-page: https://github.com/cetqap/pktron
|
|
6
|
+
Author: CETQAP
|
|
7
|
+
Author-email: info@thecetqap.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy>=1.21.0
|
|
15
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
16
|
+
Requires-Dist: quimb>=1.4.0
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# PKTron: Pakistan Tron Quantum Simulator
|
|
29
|
+
|
|
30
|
+
PKTron is a 100 Qubit quantum circuit simulator and Pakistan's 1st Quantum Simulator for 100 Qubits - Version 0.1.0 supporting statevector, stabilizer, and MPS backends. It provides tools for quantum circuit simulation, visualization, and quantum algorithms.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
```bash
|
|
34
|
+
pip install pktron
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
```python
|
|
39
|
+
from pktron import QuantumCircuit, execute, StatevectorSimulator
|
|
40
|
+
from pktron.gates import h, cnot
|
|
41
|
+
|
|
42
|
+
qc = QuantumCircuit(2, "statevector")
|
|
43
|
+
h(qc, 0)
|
|
44
|
+
cnot(qc, 0, 1)
|
|
45
|
+
result = execute(qc, StatevectorSimulator())
|
|
46
|
+
print(result.get_counts())
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
- Quantum circuit simulation with multiple backends
|
|
51
|
+
- Visualization of quantum states (histogram, Bloch sphere)
|
|
52
|
+
- Basic quantum algorithms (e.g., Quantum Treasure Hunt)
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
MIT License
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
pktron/__init__.py
|
|
5
|
+
pktron/algorithms.py
|
|
6
|
+
pktron/backend.py
|
|
7
|
+
pktron/gates.py
|
|
8
|
+
pktron/quantum.py
|
|
9
|
+
pktron/visualization.py
|
|
10
|
+
pktron.egg-info/PKG-INFO
|
|
11
|
+
pktron.egg-info/SOURCES.txt
|
|
12
|
+
pktron.egg-info/dependency_links.txt
|
|
13
|
+
pktron.egg-info/requires.txt
|
|
14
|
+
pktron.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pktron
|
pktron-0.1.0/setup.cfg
ADDED
pktron-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
from setuptools import setup, find_packages
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
setup(
|
|
6
|
+
name="pktron",
|
|
7
|
+
version="0.1.0",
|
|
8
|
+
packages=find_packages(),
|
|
9
|
+
install_requires=[
|
|
10
|
+
"numpy>=1.21.0",
|
|
11
|
+
"matplotlib>=3.4.0",
|
|
12
|
+
"quimb>=1.4.0",
|
|
13
|
+
],
|
|
14
|
+
author="CETQAP",
|
|
15
|
+
author_email="info@thecetqap.com",
|
|
16
|
+
description="A quantum circuit simulator with statevector, stabilizer, and MPS backends",
|
|
17
|
+
long_description=open("README.md").read() if os.path.exists("README.md") else "",
|
|
18
|
+
long_description_content_type="text/markdown",
|
|
19
|
+
url="https://github.com/cetqap/pktron",
|
|
20
|
+
classifiers=[
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
],
|
|
25
|
+
python_requires=">=3.6",
|
|
26
|
+
)
|