{"id":18207651,"url":"https://github.com/d-markey/qartvm","last_synced_at":"2025-09-03T04:34:50.735Z","repository":{"id":39745814,"uuid":"450940828","full_name":"d-markey/qartvm","owner":"d-markey","description":"Quantum computing simulation in Dart-land","archived":false,"fork":false,"pushed_at":"2023-05-13T23:18:01.000Z","size":3161,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-02T04:02:31.665Z","etag":null,"topics":["dart","quantum","quantum-computing"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/qartvm","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d-markey.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-22T21:32:36.000Z","updated_at":"2024-05-10T03:18:34.000Z","dependencies_parsed_at":"2025-02-13T21:39:43.465Z","dependency_job_id":null,"html_url":"https://github.com/d-markey/qartvm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/d-markey/qartvm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-markey%2Fqartvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-markey%2Fqartvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-markey%2Fqartvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-markey%2Fqartvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d-markey","download_url":"https://codeload.github.com/d-markey/qartvm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-markey%2Fqartvm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273392155,"owners_count":25097255,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","quantum","quantum-computing"],"created_at":"2024-11-03T13:03:49.412Z","updated_at":"2025-09-03T04:34:50.644Z","avatar_url":"https://github.com/d-markey.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"qartvm (pronounced '*kar-toom*', like the capital of Sudan) is a quantum computing simulation package for Dart \u0026 Flutter.\n\n# Features\n\n* Quantum circuit definition\n\n* Built-in quantum gates:\n  * Hadamard\n  * Pauli X (NOT), Y, Z\n  * Phase S, T \u0026 custom\n  * Rotations\n  * Higher-level gates:\n    * swap\n    * Toffoli (CC-NOT)\n    * Fredkin (C-SWAP)\n    * Quantum Fourrier Transform (QFT) and inverse QFT\n* Gates acting on a single qubit can be parallelized\n* Gates can be controlled by one or several qubits\n\n* Custom quantum gates\n\n* Quantum register (n-qubits)\n\n# Examples\n\nSome examples are provided in the [`/example`](https://github.com/d-markey/qartvm/tree/main/example) folder.\n\n## [Bell State](https://github.com/d-markey/qartvm/blob/main/example/bell_state.dart)\n\n```dart\n  final circuit = QCircuit(size: 2);\n  circuit.hadamard(0);\n  circuit.controlledNot(0, 1);\n\n  describe(circuit);\n  draw(circuit);\n\n  final qreg = QRegister.zero(2);\n  print('Initial states');\n  print(' * amplitudes:    ${amplInfo(qreg.amplitudes, fractionDigits: 6)}');\n  print(' * probabilities: ${probInfo(qreg.probabilities, fractionDigits: 2)}');\n  circuit.execute(qreg);\n  print('Final states');\n  print(' * amplitudes:    ${amplInfo(qreg.amplitudes, fractionDigits: 6)}');\n  print(' * probabilities: ${probInfo(qreg.probabilities, fractionDigits: 2)}');\n```\n\nOutput:\n\n```\n * hadamard on [0]\n * pauliX on [1] controlled by [0]\n          ---\n   0 ----| H |---- X ------\n          ---\n                 -----\n   1 -----------| NOT |----\n                 -----\nInitial states\n * amplitudes:    00 (1.000000)\n * probabilities: 00 (100.00 %)\nFinal states\n * amplitudes:    00 (0.707107), 11 (0.707107)\n * probabilities: 00 (50.00 %), 11 (50.00 %)\n```\n\n## [Qubit Full Adder](https://github.com/d-markey/qartvm/blob/main/example/one_qubit_full_adder.dart)\n\n```dart\n  final circuit = QCircuit(size: 4);\n  circuit.toffoli(0, 1, 3);\n  circuit.controlledNot(0, 1);\n  circuit.toffoli(1, 2, 3);\n  circuit.controlledNot(1, 2);\n  circuit.controlledNot(0, 1);\n\n  describe(circuit);\n  draw(circuit);  \n\n  for (var a = 0; a \u003c= 1; a++) {\n    for (var b = 0; b \u003c= 1; b++) {\n      final qreg = QRegister([\n        if (a == 1) Qbit.one else Qbit.zero,\n        if (b == 1) Qbit.one else Qbit.zero,\n        Qbit.zero,\n        Qbit.zero\n      ]);\n\n      print('[$a/$b] Initial: ${stateInfo(qreg.probabilities)}');\n\n      circuit.execute(qreg);\n\n      print('[$a/$b] Outcome: ${stateInfo(qreg.probabilities)}');\n\n      final result = qreg.read(qubits: [3, 2]);\n\n      print('[$a/$b] $a + $b = $result');\n    }\n  }\n```\n\nOutput:\n\n```\n * toffoli on [3] controlled by [0, 1]\n * pauliX on [1] controlled by [0]\n * toffoli on [3] controlled by [1, 2]\n * pauliX on [2] controlled by [1]\n * pauliX on [1] controlled by [0]\n\n   0 ======= X ======== X =========================== X ======\n\n                      -----                         -----\n   1 ======= X ======| NOT |===== X ======== X ====| NOT |====\n                      -----                         -----\n                                           -----\n   2 ============================ X ======| NOT |=============\n                                           -----\n          --------             --------\n   3 ====| CC-NOT |===========| CC-NOT |======================\n          --------             --------\n[0/0] Initial: 0000 (100 %)\n[0/0] Outcome: 0000 (100 %)\n[0/0] 0 + 0 = 0\n[0/1] Initial: 0100 (100 %)\n[0/1] Outcome: 0110 (100 %)\n[0/1] 0 + 1 = 1\n[1/0] Initial: 1000 (100 %)\n[1/0] Outcome: 1010 (100 %)\n[1/0] 1 + 0 = 1\n[1/1] Initial: 1100 (100 %)\n[1/1] Outcome: 1101 (100 %)\n[1/1] 1 + 1 = 2\n```\n\n## [Addition of 2 2-qubit registers](https://github.com/d-markey/qartvm/blob/main/example/two_qubit_full_adder.dart)\n\n```dart\n  // qubit #   =  input bit /  result bit\n  //    0      =      a0    /    (a+b)0\n  //    1      =      a1    /    (a+b)1\n  //    2      =      a2    /    (a+b)2 (carry)\n  //    3      =      b0    /      b0\n  //    4      =      b1    /      b1\n  //    5      =      |0\u003e                           (suppressed as this qubit is useless)\n  final circuit = QCircuit(size: 5);\n\n  circuit.qft([2, 1, 0]);\n\n  // circuit.controlledPhase(5, 2, math.pi); // suppressed because qubit 5 is always |0\u003e\n  circuit.controlledPhase(4, 2, math.pi / 2);\n  circuit.controlledPhase(3, 2, math.pi / 4);\n\n  circuit.controlledPhase(4, 1, math.pi);\n  circuit.controlledPhase(3, 1, math.pi / 2);\n\n  circuit.controlledPhase(3, 0, math.pi);\n\n  circuit.invQft([2, 1, 0]);\n\n  describe(circuit);\n  draw(circuit);\n\n  final sw = Stopwatch();\n\n  sw.start();\n  verifyAddition(circuit);\n  sw.stop();\n  print('Completed in ${sw.elapsed} before compilation, total executions = $_nbExec (${sw.elapsedMicroseconds.toDouble() / _nbExec} µs/execution)');\n\n  circuit.compile();\n\n  describe(circuit);\n  draw(circuit);\n\n  sw.reset();\n  sw.start();\n  verifyAddition(circuit);\n  sw.stop();\n  print('Completed in ${sw.elapsed} after compilation, total executions = $_nbExec (${sw.elapsedMicroseconds.toDouble() / _nbExec} µs/execution)');\n```\n\nOutput:\n\n```\n * qft on [2, 1, 0]\n * phase 0.5 pi on [2] controlled by [4]\n * phase 0.25 pi on [2] controlled by [3]\n * phase 1.0 pi on [1] controlled by [4]\n * phase 0.5 pi on [1] controlled by [3]\n * phase 1.0 pi on [0] controlled by [3]\n * invqft on [2, 1, 0]\n          -----                                                                 -----------    ---------     \n   0 ----| QFT |---------------------------------------------------------------| P(1.0 pi) |--| INV-QFT |----\n         |     |                                                                -----------   |         |    \n         |     |                                  -----------    -----------                  |         |    \n   1 ----| QFT |---------------------------------| P(1.0 pi) |--| P(0.5 pi) |-----------------| INV-QFT |----\n         |     |                                  -----------    -----------                  |         |    \n         |     |   -----------    ------------                                                |         |    \n   2 ----| QFT |--| P(0.5 pi) |--| P(0.25 pi) |-----------------------------------------------| INV-QFT |----\n          -----    -----------    ------------                                                 ---------\n\n   3 --------------------------------- X ---------------------------- X ------------ X ----------------------\n\n\n   4 ------------------ X ---------------------------- X ----------------------------------------------------\n\n[0/0] Outcome: 0 + 0 = {0: 100}\n[0/1] Outcome: 0 + 1 = {1: 100}\n[0/2] Outcome: 0 + 2 = {2: 100}\n[0/3] Outcome: 0 + 3 = {3: 100}\n[1/0] Outcome: 1 + 0 = {1: 100}\n[1/1] Outcome: 1 + 1 = {2: 100}\n[1/2] Outcome: 1 + 2 = {3: 100}\n[1/3] Outcome: 1 + 3 = {4: 100}\n[2/0] Outcome: 2 + 0 = {2: 100}\n[2/1] Outcome: 2 + 1 = {3: 100}\n[2/2] Outcome: 2 + 2 = {4: 100}\n[2/3] Outcome: 2 + 3 = {5: 100}\n[3/0] Outcome: 3 + 0 = {3: 100}\n[3/1] Outcome: 3 + 1 = {4: 100}\n[3/2] Outcome: 3 + 2 = {5: 100}\n[3/3] Outcome: 3 + 3 = {6: 100}\n[4/0] Outcome: 4 + 0 = {4: 100}\n[4/1] Outcome: 4 + 1 = {5: 100}\n[4/2] Outcome: 4 + 2 = {6: 100}\n[4/3] Outcome: 4 + 3 = {7: 100}\nCompleted in 0:00:01.382940 before compilation, total executions = 12000 (115.245 µs/execution)\n * qft on [2, 1, 0] followed by phase 0.5 pi on [2] controlled by [4] followed by phase 0.25 pi on [2] controlled by [3] followed by phase 1.0 pi on [1] controlled by [4] followed by phase 0.5 pi on [1] controlled by [3] followed by phase 1.0 pi on [0] controlled by [3] followed by invqft on [2, 1, 0]\n          ----------\n   0 ----| COMPILED |----\n         |          |\n         |          |\n   1 ----| COMPILED |----\n         |          |\n         |          |\n   2 ----| COMPILED |----\n          ----------\n\n   3 -------- X ---------\n\n\n   4 -------- X ---------\n\n[0/0] Outcome: 0 + 0 = {0: 100}\n[0/1] Outcome: 0 + 1 = {1: 100}\n[0/2] Outcome: 0 + 2 = {2: 100}\n[0/3] Outcome: 0 + 3 = {3: 100}\n[1/0] Outcome: 1 + 0 = {1: 100}\n[1/1] Outcome: 1 + 1 = {2: 100}\n[1/2] Outcome: 1 + 2 = {3: 100}\n[1/3] Outcome: 1 + 3 = {4: 100}\n[2/0] Outcome: 2 + 0 = {2: 100}\n[2/1] Outcome: 2 + 1 = {3: 100}\n[2/2] Outcome: 2 + 2 = {4: 100}\n[2/3] Outcome: 2 + 3 = {5: 100}\n[3/0] Outcome: 3 + 0 = {3: 100}\n[3/1] Outcome: 3 + 1 = {4: 100}\n[3/2] Outcome: 3 + 2 = {5: 100}\n[3/3] Outcome: 3 + 3 = {6: 100}\n[4/0] Outcome: 4 + 0 = {4: 100}\n[4/1] Outcome: 4 + 1 = {5: 100}\n[4/2] Outcome: 4 + 2 = {6: 100}\n[4/3] Outcome: 4 + 3 = {7: 100}\nCompleted in 0:00:00.425942 after compilation, total executions = 12000 (35.49516666666667 µs/execution)\n```\n\n## [Qubit Teleportation](https://github.com/d-markey/qartvm/blob/main/example/qubit_teleportation.dart)\n\n```dart\n  final circuit = QCircuit(size: 3);\n  circuit.hadamard(1);\n  circuit.controlledNot(1, 2);\n  circuit.controlledNot(0, 1);\n  circuit.hadamard(0);\n  circuit.measure(qubits: {0});\n  circuit.measure(qubits: {1});\n  circuit.controlledNot(1, 2);\n  circuit.controlledPauliZ(0, 2);\n\n  print('');\n  print('Verification before compilation');\n  describe(circuit);\n  draw(circuit);\n  checkTeleportation(circuit);\n\n  circuit.compile();\n\n  print('');\n  print('Verification after compilation');\n  describe(circuit);\n  draw(circuit);\n  checkTeleportation(circuit);\n```\n\nOutput:\n\n```\nVerification before compilation\n * hadamard on [1]\n * pauliX on [2] controlled by [1]\n * pauliX on [1] controlled by [0]\n * hadamard on [0]\n * measure [0]\n * measure [1]\n * pauliX on [2] controlled by [1]\n * pauliZ on [2] controlled by [0]\n                                   ---\n   0 ---------------------- X ----| H |---[ / ]---------------------- X -----\n                                   ---\n          ---             -----\n   1 ----| H |---- X ----| NOT |-------------------[ / ]----- X -------------\n          ---             -----\n                 -----                                      -----    ---\n   2 -----------| NOT |------------------------------------| NOT |--| Z |----\n                 -----                                      -----    ---\nInitial states: 000 (0.467916 + 0.773411 i), 100 (-0.427065 + 0.022487 i)\n   Alice: 0 (81.71 %) / 1 (18.29 %)\nFinal states: 100 (0.467916 + 0.773411 i), 101 (-0.427065 + 0.022487 i)\n   Bob  : 0 (81.71 %) / 1 (18.29 %)\n\nVerification after compilation\n * hadamard on [1] followed by pauliX on [2] controlled by [1] followed by pauliX on [1] controlled by [0] followed by hadamard on [0]\n * measure [0, 1]\n * pauliX on [2] controlled by [1] followed by pauliZ on [2] controlled by [0]\n          ----------\n   0 ----| COMPILED |---[ / ]------- X ---------\n         |          |\n         |          |\n   1 ----| COMPILED |---[ / ]------- X ---------\n         |          |\n         |          |            ----------\n   2 ----| COMPILED |-----------| COMPILED |----\n          ----------             ----------\nInitial states: 000 (-0.131496 + 0.329310 i), 100 (0.892845 + 0.277653 i)\n   Alice: 0 (12.57 %) / 1 (87.43 %)\nFinal states: 000 (-0.131496 + 0.329310 i), 001 (0.892845 + 0.277653 i)\n   Bob  : 0 (12.57 %) / 1 (87.43 %)\n```\n\n## [Custom Gate (Fredkin example)](https://github.com/d-markey/qartvm/blob/main/example/fredkin_implementation.dart)\n\n```dart\n  print('');\n  print('USING STANDARD GATES');\n\n  final fredkinCircuitWithStandardGates = QCircuit(size: 3);\n  fredkinCircuitWithStandardGates.controlledNot(2, 1);\n  fredkinCircuitWithStandardGates.toffoli(0, 1, 2);\n  fredkinCircuitWithStandardGates.controlledNot(2, 1);\n\n  describe(fredkinCircuitWithStandardGates);\n  draw(fredkinCircuitWithStandardGates);\n  verifyFredkin(fredkinCircuitWithStandardGates);\n\n  print('');\n  print('USING CUSTOM GATE');\n\n  final cnot21 = QGates.controlled(3).not(2, 1);\n  final toffoli012 = QGates.highLevel(3).toffoli(0, 1, 2);\n  // Here, the custom Fredkin gate matrix is computed by multiplying\n  // the matrices of the standard gates that make it up.\n  // The Fredkin matrix (hard-coded) could have been provided as well.\n  final myFredkinGate = cnot21 * toffoli012 * cnot21;\n  final fredkinType = QGateType('My Fredkin gate', 'MY-C-SWAP');\n  final fredkinCircuitWithCustomGate = QCircuit(size: 3);\n  fredkinCircuitWithCustomGate.custom({1, 2}, myFredkinGate, controls: {0}, type: fredkinType);\n\n  print(myFredkinGate.toStringIndent(1));\n  describe(fredkinCircuitWithCustomGate);\n  draw(fredkinCircuitWithCustomGate);\n  verifyFredkin(fredkinCircuitWithCustomGate);\n\n  print('');\n  print('USING BUILT-IN GATE');\n\n  final fredkinCircuitWithBuiltInGate = QCircuit(size: 3);\n  fredkinCircuitWithBuiltInGate.fredkin(0, 1, 2);\n\n  describe(fredkinCircuitWithBuiltInGate);\n  draw(fredkinCircuitWithBuiltInGate);\n  verifyFredkin(fredkinCircuitWithBuiltInGate);\n```\n\nOutput:\n\n```\nUSING STANDARD GATES\n * pauliX on [1] controlled by [2]       \n * toffoli on [2] controlled by [0, 1]   \n * pauliX on [1] controlled by [2]       \n\n   0 ================ X =================\n\n          -----                -----\n   1 ====| NOT |===== X ======| NOT |====\n          -----                -----\n                   --------\n   2 ====== X ====| CC-NOT |==== X ======\n                   --------\nInitial: 000 (100 %) =\u003e Outcome: 000 (100 %): OK\nInitial: 001 (100 %) =\u003e Outcome: 001 (100 %): OK\nInitial: 010 (100 %) =\u003e Outcome: 010 (100 %): OK\nInitial: 011 (100 %) =\u003e Outcome: 011 (100 %): OK\nInitial: 100 (100 %) =\u003e Outcome: 100 (100 %): OK\nInitial: 101 (100 %) =\u003e Outcome: 110 (100 %): OK\nInitial: 110 (100 %) =\u003e Outcome: 101 (100 %): OK\nInitial: 111 (100 %) =\u003e Outcome: 111 (100 %): OK\n\nUSING CUSTOM GATE\n   [\n      [1, 0, 0, 0, 0, 0, 0, 0],\n      [0, 1, 0, 0, 0, 0, 0, 0],\n      [0, 0, 1, 0, 0, 0, 0, 0],\n      [0, 0, 0, 1, 0, 0, 0, 0],\n      [0, 0, 0, 0, 1, 0, 0, 0],\n      [0, 0, 0, 0, 0, 0, 1, 0],\n      [0, 0, 0, 0, 0, 1, 0, 0],\n      [0, 0, 0, 0, 0, 0, 0, 1]\n   ]\n * My Fredkin gate on [1, 2] controlled by [0]\n\n   0 ========= X =========\n\n          -----------\n   1 ====| MY-C-SWAP |====\n         |           |    \n         |           |\n   2 ====| MY-C-SWAP |====\n          -----------\nInitial: 000 (100 %) =\u003e Outcome: 000 (100 %): OK\nInitial: 001 (100 %) =\u003e Outcome: 001 (100 %): OK\nInitial: 010 (100 %) =\u003e Outcome: 010 (100 %): OK\nInitial: 011 (100 %) =\u003e Outcome: 011 (100 %): OK\nInitial: 100 (100 %) =\u003e Outcome: 100 (100 %): OK\nInitial: 101 (100 %) =\u003e Outcome: 110 (100 %): OK\nInitial: 110 (100 %) =\u003e Outcome: 101 (100 %): OK\nInitial: 111 (100 %) =\u003e Outcome: 111 (100 %): OK\n\nUSING BUILT-IN GATE\n * fredkin on [1, 2] controlled by [0]\n\n   0 ======= X ========\n\n          --------\n   1 ====| C-SWAP |====\n         |        |\n         |        |\n   2 ====| C-SWAP |====\n          --------\nInitial: 000 (100 %) =\u003e Outcome: 000 (100 %): OK\nInitial: 001 (100 %) =\u003e Outcome: 001 (100 %): OK\nInitial: 010 (100 %) =\u003e Outcome: 010 (100 %): OK\nInitial: 011 (100 %) =\u003e Outcome: 011 (100 %): OK\nInitial: 100 (100 %) =\u003e Outcome: 100 (100 %): OK\nInitial: 101 (100 %) =\u003e Outcome: 110 (100 %): OK\nInitial: 110 (100 %) =\u003e Outcome: 101 (100 %): OK\nInitial: 111 (100 %) =\u003e Outcome: 111 (100 %): OK\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-markey%2Fqartvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd-markey%2Fqartvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-markey%2Fqartvm/lists"}