fqkit 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.
fqkit-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Felix
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fqkit-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,237 @@
1
+ Metadata-Version: 2.4
2
+ Name: fqkit
3
+ Version: 0.1.0
4
+ Summary: A lightweight Python framework for building and simulating quantum circuits.
5
+ Author-email: Felix <felixo6996@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Felixowusu20/Fqkit
8
+ Keywords: quantum,quantum-computing,simulator,education,qiskit
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering :: Physics
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: numpy>=1.21
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Provides-Extra: ibm
26
+ Requires-Dist: qiskit>=1.3; extra == "ibm"
27
+ Requires-Dist: qiskit-ibm-runtime>=0.30; extra == "ibm"
28
+ Provides-Extra: braket
29
+ Requires-Dist: amazon-braket-sdk>=1.88; extra == "braket"
30
+ Provides-Extra: hardware
31
+ Requires-Dist: qiskit>=1.3; extra == "hardware"
32
+ Requires-Dist: qiskit-ibm-runtime>=0.30; extra == "hardware"
33
+ Requires-Dist: amazon-braket-sdk>=1.88; extra == "hardware"
34
+ Dynamic: license-file
35
+
36
+ # FQkit
37
+
38
+ FQkit is a small Python framework for building and simulating quantum
39
+ circuits. The source stays short on purpose, so you can learn how a quantum
40
+ computer works by reading it and changing it.
41
+
42
+ > **Documentation website:** the full docs live in [`website/`](website): a
43
+ > Next.js + Nextra site. Run it locally with `cd website && npm install && npm
44
+ > run dev`, or deploy it for free on Vercel (see the
45
+ > [website README](website/README.md)).
46
+
47
+ ## Features
48
+
49
+ - Qubits and parameterized gates (`H`, `RX`, `RY`, `RZ`)
50
+ - Multi-qubit gates: `CNOT`, `CZ`, `SWAP`, `Toffoli`
51
+ - Circuit construction with `QuantumCircuit`
52
+ - Parameter binding for variational circuits
53
+ - A statevector simulator that returns the final state
54
+ - Measurement with shot-based sampling
55
+ - Export to OpenQASM 2.0: run your circuits on real IBM hardware via Qiskit
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install fqkit
61
+ ```
62
+
63
+ FQkit needs Python 3.9 or newer. NumPy is installed with it.
64
+
65
+ To work on the source, clone the repository and install it in editable mode:
66
+
67
+ ```bash
68
+ git clone https://github.com/Felixowusu20/Fqkit.git
69
+ cd Fqkit
70
+ pip install -e ".[dev]"
71
+ pytest
72
+ ```
73
+
74
+ ## Quick start
75
+
76
+ Build a Bell state, an entangled pair of qubits, and measure it:
77
+
78
+ ```python
79
+ from fqkit import QuantumCircuit, Hadamard, CNOT, run, measure_all
80
+
81
+ qc = QuantumCircuit(2)
82
+ qc.add_gate(Hadamard(), [0]) # put qubit 0 into superposition
83
+ qc.add_gate(CNOT(), [0, 1]) # entangle qubit 1 with qubit 0
84
+
85
+ state = run(qc) # -> array([0.707, 0, 0, 0.707])
86
+ counts = measure_all(state, shots=1024)
87
+
88
+ print("State :", state)
89
+ print("Counts:", counts) # -> {'00': ~512, '11': ~512}
90
+ ```
91
+
92
+ ## Variational circuits
93
+
94
+ Gates can take symbolic `Parameter`s that you bind to numbers later: the basis
95
+ of variational algorithms like VQE and QAOA:
96
+
97
+ ```python
98
+ from fqkit import QuantumCircuit, Hadamard, RX, Parameter, bind_parameters, run, measure_all
99
+
100
+ theta = Parameter("theta")
101
+
102
+ qc = QuantumCircuit(2)
103
+ qc.add_gate(Hadamard(), [0])
104
+ qc.add_gate(RX(theta), [1])
105
+
106
+ bind_parameters(qc, {"theta": 3.14159})
107
+
108
+ counts = measure_all(run(qc), shots=1024)
109
+ print(counts)
110
+ ```
111
+
112
+ ## Export to OpenQASM: run on real hardware
113
+
114
+ Any circuit can be exported to OpenQASM 2.0, the open standard that Qiskit
115
+ reads. That means a circuit you build in fqkit can run on a **real quantum
116
+ computer** through IBM Quantum's free tier: no hardware of your own needed.
117
+ Everything in this pipeline (OpenQASM, Qiskit, the IBM free tier) costs nothing.
118
+
119
+ ```python
120
+ from fqkit import QuantumCircuit, Hadamard, CNOT
121
+
122
+ qc = QuantumCircuit(2)
123
+ qc.add_gate(Hadamard(), [0])
124
+ qc.add_gate(CNOT(), [0, 1])
125
+
126
+ print(qc.to_qasm()) # or: to_qasm(qc)
127
+ ```
128
+
129
+ ```
130
+ OPENQASM 2.0;
131
+ include "qelib1.inc";
132
+ qreg q[2];
133
+ creg c[2];
134
+ h q[0];
135
+ cx q[0], q[1];
136
+ measure q -> c;
137
+ ```
138
+
139
+ ### Load it in Qiskit (free)
140
+
141
+ `pip install qiskit` (free and open source), then:
142
+
143
+ ```python
144
+ from qiskit import QuantumCircuit as QiskitCircuit
145
+ from qiskit.quantum_info import Statevector
146
+
147
+ qiskit_qc = QiskitCircuit.from_qasm_str(qc.to_qasm(measure=False))
148
+ print(Statevector.from_instruction(qiskit_qc).probabilities_dict())
149
+ # {'00': 0.5, '11': 0.5}
150
+ ```
151
+
152
+ ### Run on real hardware
153
+
154
+ `run()` stays on your computer. Hardware jobs go through `fqkit.hardware`,
155
+ which calls the vendor SDK, waits on the queue, and returns counts in fqkit
156
+ bit order (qubit 0 on the left). The vendor packages are optional, so a normal
157
+ install still depends only on NumPy.
158
+
159
+ ```bash
160
+ pip install "fqkit[ibm]" # IBM Quantum, through Qiskit Runtime
161
+ pip install "fqkit[braket]" # IonQ, Rigetti, IQM, and AQT, through Amazon Braket
162
+ pip install "fqkit[hardware]" # both
163
+ ```
164
+
165
+ ```python
166
+ from fqkit.hardware import providers, submit
167
+
168
+ providers() # ibm, ionq, rigetti, iqm, aqt
169
+
170
+ job = submit(qc, "ibm", shots=1024)
171
+ print(job.job_id, job.status()) # QUEUED, RUNNING, COMPLETED, CANCELLED, FAILED
172
+ print(job.counts()) # waits for the device
173
+
174
+ job = submit(qc, "ionq", shots=100)
175
+ job = submit(qc, "rigetti", shots=100)
176
+ ```
177
+
178
+ IBM needs a free account at https://quantum.cloud.ibm.com. Save the token once
179
+ with `QiskitRuntimeService.save_account`, or pass `token=` to `submit`. With
180
+ no backend name, fqkit picks the least busy real device. Pass
181
+ `backend="ibm_..."` to choose one, or `backends("ibm", live=True)` to list
182
+ the devices that are up.
183
+
184
+ IonQ, Rigetti, IQM, and AQT are one Amazon Braket account. Those QPU tasks are
185
+ billed by AWS. `submit(qc, "ionq")` targets IonQ Forte-1. Pass `backend=` as a
186
+ full device ARN when you need a different chip. `job.status()` returns
187
+ immediately. `job.counts()` blocks until the machine finishes. `get_job(machine,
188
+ job_id)` reconnects to a job you already submitted.
189
+
190
+ The lessons in the browser keep using the local simulator. A hardware token
191
+ stays in your own Python process.
192
+
193
+ ## Project layout
194
+
195
+ ```
196
+ fqkit/
197
+ core/
198
+ qubit.py # Qubit: an index into Hilbert space
199
+ parameter.py # Parameter: a symbolic variable
200
+ gate.py # Gate + H, RX, RY, RZ, CNOT, CZ, SWAP, Toffoli
201
+ operation.py # Operation: a gate applied to specific qubits
202
+ circuit.py # QuantumCircuit: an ordered list of operations
203
+ parameter_binding.py # bind_parameters: substitute symbols -> numbers
204
+ simulator.py # run: apply gates to a statevector
205
+ measurement.py # measure_all: sample |amplitude|^2
206
+ qasm.py # to_qasm: export circuits to OpenQASM 2.0
207
+ hardware/
208
+ ibm.py # IBM Quantum via Qiskit Runtime
209
+ braket.py # IonQ, Rigetti, IQM, AQT via Amazon Braket
210
+ ```
211
+
212
+ ## Convention
213
+
214
+ FQkit uses **big-endian** qubit ordering: qubit 0 is the most significant bit
215
+ of the state-vector index, and the first qubit passed to a multi-qubit gate is
216
+ its most significant qubit (for `CNOT`, the control).
217
+
218
+ ## Testing
219
+
220
+ FQkit ships with a `pytest` suite covering the simulator, every gate, parameter
221
+ binding, measurement, input validation, and the OpenQASM export, including
222
+ round-trip tests that load an exported circuit into Qiskit and check that the
223
+ statevectors match fqkit's own simulator.
224
+
225
+ ```bash
226
+ pip install -e ".[dev]" # installs pytest
227
+ pytest -v # 46 tests
228
+ ```
229
+
230
+ The Qiskit round-trip tests are skipped automatically if Qiskit is not
231
+ installed. Install it (free) with `pip install qiskit` to run those too.
232
+
233
+ | Test file | Covers |
234
+ |---|---|
235
+ | `tests/test_fqkit.py` | Single- and multi-qubit gates, entanglement (Bell states), reversed and non-adjacent controls, parameter binding, unbound-parameter errors, measurement statistics, and input validation |
236
+ | `tests/test_qasm.py` | OpenQASM string output, gate-name mapping, error handling, and Qiskit round-trip equivalence |
237
+ | `tests/test_hardware.py` | Machine selection, OpenQASM 3 for Braket, Runtime and Braket submission with stand-in SDKs, job status, and bit order |
fqkit-0.1.0/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # FQkit
2
+
3
+ FQkit is a small Python framework for building and simulating quantum
4
+ circuits. The source stays short on purpose, so you can learn how a quantum
5
+ computer works by reading it and changing it.
6
+
7
+ > **Documentation website:** the full docs live in [`website/`](website): a
8
+ > Next.js + Nextra site. Run it locally with `cd website && npm install && npm
9
+ > run dev`, or deploy it for free on Vercel (see the
10
+ > [website README](website/README.md)).
11
+
12
+ ## Features
13
+
14
+ - Qubits and parameterized gates (`H`, `RX`, `RY`, `RZ`)
15
+ - Multi-qubit gates: `CNOT`, `CZ`, `SWAP`, `Toffoli`
16
+ - Circuit construction with `QuantumCircuit`
17
+ - Parameter binding for variational circuits
18
+ - A statevector simulator that returns the final state
19
+ - Measurement with shot-based sampling
20
+ - Export to OpenQASM 2.0: run your circuits on real IBM hardware via Qiskit
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ pip install fqkit
26
+ ```
27
+
28
+ FQkit needs Python 3.9 or newer. NumPy is installed with it.
29
+
30
+ To work on the source, clone the repository and install it in editable mode:
31
+
32
+ ```bash
33
+ git clone https://github.com/Felixowusu20/Fqkit.git
34
+ cd Fqkit
35
+ pip install -e ".[dev]"
36
+ pytest
37
+ ```
38
+
39
+ ## Quick start
40
+
41
+ Build a Bell state, an entangled pair of qubits, and measure it:
42
+
43
+ ```python
44
+ from fqkit import QuantumCircuit, Hadamard, CNOT, run, measure_all
45
+
46
+ qc = QuantumCircuit(2)
47
+ qc.add_gate(Hadamard(), [0]) # put qubit 0 into superposition
48
+ qc.add_gate(CNOT(), [0, 1]) # entangle qubit 1 with qubit 0
49
+
50
+ state = run(qc) # -> array([0.707, 0, 0, 0.707])
51
+ counts = measure_all(state, shots=1024)
52
+
53
+ print("State :", state)
54
+ print("Counts:", counts) # -> {'00': ~512, '11': ~512}
55
+ ```
56
+
57
+ ## Variational circuits
58
+
59
+ Gates can take symbolic `Parameter`s that you bind to numbers later: the basis
60
+ of variational algorithms like VQE and QAOA:
61
+
62
+ ```python
63
+ from fqkit import QuantumCircuit, Hadamard, RX, Parameter, bind_parameters, run, measure_all
64
+
65
+ theta = Parameter("theta")
66
+
67
+ qc = QuantumCircuit(2)
68
+ qc.add_gate(Hadamard(), [0])
69
+ qc.add_gate(RX(theta), [1])
70
+
71
+ bind_parameters(qc, {"theta": 3.14159})
72
+
73
+ counts = measure_all(run(qc), shots=1024)
74
+ print(counts)
75
+ ```
76
+
77
+ ## Export to OpenQASM: run on real hardware
78
+
79
+ Any circuit can be exported to OpenQASM 2.0, the open standard that Qiskit
80
+ reads. That means a circuit you build in fqkit can run on a **real quantum
81
+ computer** through IBM Quantum's free tier: no hardware of your own needed.
82
+ Everything in this pipeline (OpenQASM, Qiskit, the IBM free tier) costs nothing.
83
+
84
+ ```python
85
+ from fqkit import QuantumCircuit, Hadamard, CNOT
86
+
87
+ qc = QuantumCircuit(2)
88
+ qc.add_gate(Hadamard(), [0])
89
+ qc.add_gate(CNOT(), [0, 1])
90
+
91
+ print(qc.to_qasm()) # or: to_qasm(qc)
92
+ ```
93
+
94
+ ```
95
+ OPENQASM 2.0;
96
+ include "qelib1.inc";
97
+ qreg q[2];
98
+ creg c[2];
99
+ h q[0];
100
+ cx q[0], q[1];
101
+ measure q -> c;
102
+ ```
103
+
104
+ ### Load it in Qiskit (free)
105
+
106
+ `pip install qiskit` (free and open source), then:
107
+
108
+ ```python
109
+ from qiskit import QuantumCircuit as QiskitCircuit
110
+ from qiskit.quantum_info import Statevector
111
+
112
+ qiskit_qc = QiskitCircuit.from_qasm_str(qc.to_qasm(measure=False))
113
+ print(Statevector.from_instruction(qiskit_qc).probabilities_dict())
114
+ # {'00': 0.5, '11': 0.5}
115
+ ```
116
+
117
+ ### Run on real hardware
118
+
119
+ `run()` stays on your computer. Hardware jobs go through `fqkit.hardware`,
120
+ which calls the vendor SDK, waits on the queue, and returns counts in fqkit
121
+ bit order (qubit 0 on the left). The vendor packages are optional, so a normal
122
+ install still depends only on NumPy.
123
+
124
+ ```bash
125
+ pip install "fqkit[ibm]" # IBM Quantum, through Qiskit Runtime
126
+ pip install "fqkit[braket]" # IonQ, Rigetti, IQM, and AQT, through Amazon Braket
127
+ pip install "fqkit[hardware]" # both
128
+ ```
129
+
130
+ ```python
131
+ from fqkit.hardware import providers, submit
132
+
133
+ providers() # ibm, ionq, rigetti, iqm, aqt
134
+
135
+ job = submit(qc, "ibm", shots=1024)
136
+ print(job.job_id, job.status()) # QUEUED, RUNNING, COMPLETED, CANCELLED, FAILED
137
+ print(job.counts()) # waits for the device
138
+
139
+ job = submit(qc, "ionq", shots=100)
140
+ job = submit(qc, "rigetti", shots=100)
141
+ ```
142
+
143
+ IBM needs a free account at https://quantum.cloud.ibm.com. Save the token once
144
+ with `QiskitRuntimeService.save_account`, or pass `token=` to `submit`. With
145
+ no backend name, fqkit picks the least busy real device. Pass
146
+ `backend="ibm_..."` to choose one, or `backends("ibm", live=True)` to list
147
+ the devices that are up.
148
+
149
+ IonQ, Rigetti, IQM, and AQT are one Amazon Braket account. Those QPU tasks are
150
+ billed by AWS. `submit(qc, "ionq")` targets IonQ Forte-1. Pass `backend=` as a
151
+ full device ARN when you need a different chip. `job.status()` returns
152
+ immediately. `job.counts()` blocks until the machine finishes. `get_job(machine,
153
+ job_id)` reconnects to a job you already submitted.
154
+
155
+ The lessons in the browser keep using the local simulator. A hardware token
156
+ stays in your own Python process.
157
+
158
+ ## Project layout
159
+
160
+ ```
161
+ fqkit/
162
+ core/
163
+ qubit.py # Qubit: an index into Hilbert space
164
+ parameter.py # Parameter: a symbolic variable
165
+ gate.py # Gate + H, RX, RY, RZ, CNOT, CZ, SWAP, Toffoli
166
+ operation.py # Operation: a gate applied to specific qubits
167
+ circuit.py # QuantumCircuit: an ordered list of operations
168
+ parameter_binding.py # bind_parameters: substitute symbols -> numbers
169
+ simulator.py # run: apply gates to a statevector
170
+ measurement.py # measure_all: sample |amplitude|^2
171
+ qasm.py # to_qasm: export circuits to OpenQASM 2.0
172
+ hardware/
173
+ ibm.py # IBM Quantum via Qiskit Runtime
174
+ braket.py # IonQ, Rigetti, IQM, AQT via Amazon Braket
175
+ ```
176
+
177
+ ## Convention
178
+
179
+ FQkit uses **big-endian** qubit ordering: qubit 0 is the most significant bit
180
+ of the state-vector index, and the first qubit passed to a multi-qubit gate is
181
+ its most significant qubit (for `CNOT`, the control).
182
+
183
+ ## Testing
184
+
185
+ FQkit ships with a `pytest` suite covering the simulator, every gate, parameter
186
+ binding, measurement, input validation, and the OpenQASM export, including
187
+ round-trip tests that load an exported circuit into Qiskit and check that the
188
+ statevectors match fqkit's own simulator.
189
+
190
+ ```bash
191
+ pip install -e ".[dev]" # installs pytest
192
+ pytest -v # 46 tests
193
+ ```
194
+
195
+ The Qiskit round-trip tests are skipped automatically if Qiskit is not
196
+ installed. Install it (free) with `pip install qiskit` to run those too.
197
+
198
+ | Test file | Covers |
199
+ |---|---|
200
+ | `tests/test_fqkit.py` | Single- and multi-qubit gates, entanglement (Bell states), reversed and non-adjacent controls, parameter binding, unbound-parameter errors, measurement statistics, and input validation |
201
+ | `tests/test_qasm.py` | OpenQASM string output, gate-name mapping, error handling, and Qiskit round-trip equivalence |
202
+ | `tests/test_hardware.py` | Machine selection, OpenQASM 3 for Braket, Runtime and Braket submission with stand-in SDKs, job status, and bit order |
@@ -0,0 +1,59 @@
1
+ """
2
+ FQkit — a lightweight quantum circuit framework for learning and simulation.
3
+
4
+ Quick start
5
+ -----------
6
+ from fqkit import QuantumCircuit, Hadamard, CNOT, run, measure_all
7
+
8
+ qc = QuantumCircuit(2)
9
+ qc.add_gate(Hadamard(), [0])
10
+ qc.add_gate(CNOT(), [0, 1])
11
+
12
+ state = run(qc)
13
+ counts = measure_all(state, shots=1024)
14
+ """
15
+
16
+ from fqkit.core import (
17
+ Qubit,
18
+ Parameter,
19
+ Gate,
20
+ Hadamard,
21
+ RX,
22
+ RY,
23
+ RZ,
24
+ CNOT,
25
+ CZ,
26
+ SWAP,
27
+ Toffoli,
28
+ Operation,
29
+ QuantumCircuit,
30
+ bind_parameters,
31
+ run,
32
+ apply_gate,
33
+ measure_all,
34
+ to_qasm,
35
+ )
36
+
37
+ __version__ = "0.1.0"
38
+
39
+ __all__ = [
40
+ "Qubit",
41
+ "Parameter",
42
+ "Gate",
43
+ "Hadamard",
44
+ "RX",
45
+ "RY",
46
+ "RZ",
47
+ "CNOT",
48
+ "CZ",
49
+ "SWAP",
50
+ "Toffoli",
51
+ "Operation",
52
+ "QuantumCircuit",
53
+ "bind_parameters",
54
+ "run",
55
+ "apply_gate",
56
+ "measure_all",
57
+ "to_qasm",
58
+ "__version__",
59
+ ]
@@ -0,0 +1,42 @@
1
+ """fqkit.core — the building blocks of an fqkit quantum circuit."""
2
+
3
+ from fqkit.core.qubit import Qubit
4
+ from fqkit.core.parameter import Parameter
5
+ from fqkit.core.gate import (
6
+ Gate,
7
+ Hadamard,
8
+ RX,
9
+ RY,
10
+ RZ,
11
+ CNOT,
12
+ CZ,
13
+ SWAP,
14
+ Toffoli,
15
+ )
16
+ from fqkit.core.operation import Operation
17
+ from fqkit.core.circuit import QuantumCircuit
18
+ from fqkit.core.parameter_binding import bind_parameters
19
+ from fqkit.core.simulator import run, apply_gate
20
+ from fqkit.core.measurement import measure_all
21
+ from fqkit.core.qasm import to_qasm
22
+
23
+ __all__ = [
24
+ "Qubit",
25
+ "Parameter",
26
+ "Gate",
27
+ "Hadamard",
28
+ "RX",
29
+ "RY",
30
+ "RZ",
31
+ "CNOT",
32
+ "CZ",
33
+ "SWAP",
34
+ "Toffoli",
35
+ "Operation",
36
+ "QuantumCircuit",
37
+ "bind_parameters",
38
+ "run",
39
+ "apply_gate",
40
+ "measure_all",
41
+ "to_qasm",
42
+ ]
@@ -0,0 +1,40 @@
1
+ from fqkit.core.operation import Operation
2
+ from fqkit.core.qubit import Qubit
3
+ from fqkit.core.qasm import to_qasm as _to_qasm
4
+
5
+ class QuantumCircuit:
6
+ def __init__(self , num_qubits:int):
7
+ if num_qubits <= 0:
8
+ raise ValueError("A circuit needs at least one qubit.")
9
+ self.num_qubits = num_qubits
10
+ self.qubits = [Qubit(i) for i in range(num_qubits)]
11
+ self.operations = []
12
+
13
+ def add_gate(self, gate, target_qubits):
14
+ # Convert Qubit objects to indices automatically
15
+ target_qubits = [q.index if isinstance(q, Qubit) else q for q in target_qubits]
16
+
17
+ if len(target_qubits) != gate.num_qubits:
18
+ raise ValueError(f"Gate {gate.name} requires {gate.num_qubits} qubits, "
19
+ f"but {len(target_qubits)} were provided.")
20
+ if min(target_qubits) < 0:
21
+ raise ValueError("Target qubit index cannot be negative")
22
+ if max(target_qubits) >= self.num_qubits:
23
+ raise ValueError("Target qubit index exceeds circuit size")
24
+ if len(set(target_qubits)) != len(target_qubits):
25
+ raise ValueError(f"Gate {gate.name} was given a repeated target qubit: "
26
+ f"{target_qubits}")
27
+
28
+ op = Operation(gate, target_qubits)
29
+ self.operations.append(op)
30
+
31
+ def to_qasm(self, measure=True):
32
+ """Return this circuit as an OpenQASM 2.0 string.
33
+
34
+ See fqkit.core.qasm.to_qasm for details.
35
+ """
36
+ return _to_qasm(self, measure=measure)
37
+
38
+ def __repr__(self):
39
+ op_str = '\n'.join([str(op) for op in self.operations])
40
+ return f"QuantumCircuit({self.num_qubits}, [\n{op_str}\n])"
@@ -0,0 +1,76 @@
1
+ # Gates (unitary operators)
2
+ # A gate is a unitary matrix: U such that U†U = I.
3
+ # Some gates are parameterized.
4
+
5
+ # BASE GATE CLASS
6
+
7
+ class Gate:
8
+ def __init__(self ,name:str ,num_qubits:int ,matrix = None ,params = None):
9
+ self.name = name
10
+ self.num_qubits = num_qubits
11
+ self.matrix = matrix
12
+ self.params = params or []
13
+
14
+ def __repr__(self):
15
+ if self.params:
16
+ params = ', '.join([str(p) for p in self.params])
17
+ return f"{self.name}({params})"
18
+ else:
19
+ return f"{self.name}"
20
+
21
+
22
+
23
+ # # let try creating some gates (Hadamard, CNOT, RX , Toffoli , swap and the rest will be added)
24
+ def Hadamard():
25
+ return Gate(name="H", num_qubits=1, matrix=[[1/2**0.5, 1/2**0.5], [1/2**0.5, -1/2**0.5]])
26
+
27
+
28
+ # def CNOT():
29
+ # return Gate(name="CNOT", num_quibits=2, matrix=[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
30
+ def RX(theta):
31
+ return Gate(name="RX", num_qubits=1, params=[theta])
32
+
33
+
34
+ def RY(theta):
35
+ return Gate(name="RY", num_qubits=1, params=[theta])
36
+
37
+
38
+ def RZ(theta):
39
+ return Gate(name="RZ", num_qubits=1, params=[theta])
40
+ def CNOT():
41
+ return Gate(name="CNOT", num_qubits=2, matrix=[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
42
+
43
+
44
+ # You can add more gates as needed
45
+ # For example, CZ, SWAP, Toffoli, etc.
46
+
47
+ def CZ():
48
+ return Gate(
49
+ name="CZ",
50
+ num_qubits=2,
51
+ matrix=[[1, 0, 0, 0], [0, 1, 0, 0],
52
+ [0, 0, 1, 0], [0, 0, 0, -1]])
53
+ def SWAP():
54
+ return Gate(
55
+ name="SWAP",
56
+ num_qubits=2,
57
+ matrix=[[1, 0, 0, 0], [0, 0, 1, 0],
58
+ [0, 1, 0, 0], [0, 0, 0, 1]])
59
+ def Toffoli():
60
+ return Gate(
61
+ name="Toffoli",
62
+ num_qubits=3,
63
+ matrix=[
64
+ [1, 0, 0, 0, 0, 0, 0, 0],
65
+ [0, 1, 0, 0, 0, 0, 0, 0],
66
+ [0, 0, 1, 0, 0, 0, 0, 0],
67
+ [0, 0, 0, 1, 0, 0, 0, 0],
68
+ [0, 0, 0, 0, 1, 0, 0, 0],
69
+ [0, 0, 0, 0, 0, 1, 0, 0],
70
+ [0, 0, 0, 0, 0, 0, 0, 1],
71
+ [0, 0, 0, 0, 0, 0, 1, 0]
72
+ ]
73
+ )
74
+
75
+
76
+