diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 9b4d1a97..ca92b307 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -30,5 +30,5 @@ jobs:
git clone https://github.com/vutuanhai237/qsee.git
- name: Run testcases
run: |
- cd test
+ cd tests
python -m pytest
\ No newline at end of file
diff --git a/codes/circuit.svg b/codes/circuit.svg
new file mode 100644
index 00000000..bc3b7b2b
--- /dev/null
+++ b/codes/circuit.svg
@@ -0,0 +1,563 @@
+
+
+
diff --git a/codes/demos/AME_state.ipynb b/codes/demos/AME_state.ipynb
index 2c1f8f2c..8fcda80c 100644
--- a/codes/demos/AME_state.ipynb
+++ b/codes/demos/AME_state.ipynb
@@ -81,7 +81,7 @@
"qng_compiler = QuantumCompilation(\n",
" u = ansatz.polygongraph(num_qubits, num_layers),\n",
" vdagger = state.ame(num_qubits).inverse(),\n",
- " optimizer = 'qng_fubini_study'\n",
+ " optimizer = constant.OptimizerName.QNG_FUBINI_STUDY.value\n",
").fit()"
]
},
@@ -149,7 +149,7 @@
"sgd_compiler = QuantumCompilation(\n",
" u = ansatz.polygongraph(num_qubits, num_layers),\n",
" vdagger = state.ame(num_qubits).inverse(),\n",
- " optimizer = 'sgd'\n",
+ " optimizer = constant.OptimizerName.SGD.value\n",
").fit()\n",
"sgd_compiler.plot()"
]
diff --git a/codes/qsp.ipynb b/codes/qsp.ipynb
index 08f7c08d..67cd5a96 100644
--- a/codes/qsp.ipynb
+++ b/codes/qsp.ipynb
@@ -37,16 +37,26 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 58,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The autoreload extension is already loaded. To reload it, use:\n",
+ " %reload_ext autoreload\n"
+ ]
+ }
+ ],
"source": [
"import sys\n",
"sys.path.insert(0, '..')\n",
"from qsee.compilation.qsp import QuantumStatePreparation\n",
"from qsee.core import ansatz, state\n",
+ "from qsee.backend import constant, utilities\n",
"import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
+ "import numpy as np, qiskit\n",
"%load_ext autoreload\n",
"%autoreload 2"
]
@@ -67,92 +77,161 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": 125,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def custom_ansatz(num_qubits: int) -> qiskit.QuantumCircuit:\n",
+ " qc = qiskit.QuantumCircuit(num_qubits)\n",
+ " thetas = qiskit.circuit.ParameterVector(\n",
+ " 'theta', 2 * num_qubits)\n",
+ " j = 0\n",
+ " for i in range(num_qubits):\n",
+ " qc.rx(thetas[j], i)\n",
+ " qc.rz(thetas[j + 1], i)\n",
+ " j += 2\n",
+ " return qc\n",
+ "qsp = QuantumStatePreparation(\n",
+ " u=custom_ansatz(num_qubits = 3),\n",
+ " target_state=state.w(num_qubits = 3).inverse(),\n",
+ ").fit(\n",
+ " num_steps = 200, \n",
+ " optimizer='sgd', \n",
+ " metrics_func = [\n",
+ " 'loss_basic', \n",
+ " 'compilation_trace_fidelities'\n",
+ " ]\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 116,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
- "Step: 100%|██████████| 100/100 [00:03<00:00, 28.53it/s]\n"
+ "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/qiskit/visualization/circuit/matplotlib.py:266: FutureWarning: The default matplotlib drawer scheme will be changed to \"iqp\" in a following release. To silence this warning, specify the current default explicitly as style=\"clifford\", or the new default as style=\"iqp\".\n",
+ " self._style, def_font_ratio = load_style(self._style)\n"
]
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ "