sequence 0.8.3.dev260767962__tar.gz → 0.8.5__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.
Files changed (118) hide show
  1. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/PKG-INFO +41 -13
  2. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/README.md +35 -10
  3. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/pyproject.toml +16 -1
  4. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/app/request_app.py +17 -11
  5. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/bsm.py +4 -4
  6. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/detector.py +2 -2
  7. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/interferometer.py +2 -2
  8. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/memory.py +29 -23
  9. sequence-0.8.5/sequence/constants.py +58 -0
  10. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/entanglement_protocol.py +0 -1
  11. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/generation/barret_kok.py +1 -2
  12. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/generation/generation_base.py +7 -9
  13. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/generation/single_heralded.py +30 -28
  14. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/purification/bbpssw_bds.py +3 -4
  15. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/purification/bbpssw_protocol.py +7 -10
  16. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/app.py +0 -2
  17. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/eventlist.py +10 -12
  18. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/quantum_manager.py +6 -8
  19. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/quantum_state.py +18 -27
  20. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/quantum_utils.py +33 -26
  21. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/timeline.py +1 -6
  22. sequence-0.8.5/sequence/network_management/__init__.py +4 -0
  23. sequence-0.8.5/sequence/network_management/forwarding.py +107 -0
  24. sequence-0.8.5/sequence/network_management/memory_timecard.py +85 -0
  25. sequence-0.8.5/sequence/network_management/network_manager.py +269 -0
  26. sequence-0.8.5/sequence/network_management/reservation.py +79 -0
  27. sequence-0.8.5/sequence/network_management/routing_distributed.py +801 -0
  28. sequence-0.8.5/sequence/network_management/routing_static.py +79 -0
  29. sequence-0.8.5/sequence/network_management/rsvp.py +246 -0
  30. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/protocol.py +4 -2
  31. sequence-0.8.5/sequence/resource_management/action_condition_set.py +485 -0
  32. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/resource_management/resource_manager.py +177 -37
  33. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/resource_management/rule_manager.py +10 -6
  34. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/dqc_net_topo.py +2 -2
  35. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/node.py +35 -26
  36. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/router_net_topo.py +48 -22
  37. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/topology.py +5 -5
  38. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/utils/config_generator.py +1 -1
  39. sequence-0.8.3.dev260767962/sequence/constants.py +0 -36
  40. sequence-0.8.3.dev260767962/sequence/network_management/__init__.py +0 -4
  41. sequence-0.8.3.dev260767962/sequence/network_management/network_manager.py +0 -191
  42. sequence-0.8.3.dev260767962/sequence/network_management/reservation.py +0 -823
  43. sequence-0.8.3.dev260767962/sequence/network_management/routing.py +0 -117
  44. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/__init__.py +0 -0
  45. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/app/__init__.py +0 -0
  46. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/app/random_request.py +0 -0
  47. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/app/teleport_app.py +0 -0
  48. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/__init__.py +0 -0
  49. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/beam_splitter.py +0 -0
  50. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/circuit.py +0 -0
  51. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/fiber_stretcher.py +0 -0
  52. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/light_source.py +0 -0
  53. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/mirror.py +0 -0
  54. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/optical_channel.py +0 -0
  55. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/photon.py +0 -0
  56. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/spdc_lens.py +0 -0
  57. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/switch.py +0 -0
  58. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/transducer.py +0 -0
  59. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/components/transmon.py +0 -0
  60. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/__init__.py +0 -0
  61. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/generation/__init__.py +0 -0
  62. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/generation/generation_message.py +0 -0
  63. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/purification/__init__.py +0 -0
  64. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/purification/bbpssw_circuit.py +0 -0
  65. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/swapping.py +0 -0
  66. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/entanglement_management/teleportation.py +0 -0
  67. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/__init__.py +0 -0
  68. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/argonne.png +0 -0
  69. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/attributions_req +0 -0
  70. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/bsmnode.png +0 -0
  71. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/detector.png +0 -0
  72. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/logo.png +0 -0
  73. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/photonsource.png +0 -0
  74. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/quantum.png +0 -0
  75. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/repeater.png +0 -0
  76. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/router.png +0 -0
  77. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/sequence.jpg +0 -0
  78. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/bsmnode.svg +0 -0
  79. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/detector.svg +0 -0
  80. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/photonsource.svg +0 -0
  81. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/quantum.svg +0 -0
  82. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/repeater.svg +0 -0
  83. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/router.svg +0 -0
  84. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/svg/temp.svg +0 -0
  85. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/assets/temp.png +0 -0
  86. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/css_styles.py +0 -0
  87. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/default_params.json +0 -0
  88. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/default_templates.json +0 -0
  89. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/graph_comp.py +0 -0
  90. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/layout.py +0 -0
  91. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/menus.py +0 -0
  92. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/run_gui.py +0 -0
  93. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/simulator_bindings.py +0 -0
  94. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/starlight.json +0 -0
  95. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/test.txt +0 -0
  96. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/gui/user_templates.json +0 -0
  97. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/__init__.py +0 -0
  98. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/entity.py +0 -0
  99. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/event.py +0 -0
  100. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/kernel/process.py +0 -0
  101. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/message.py +0 -0
  102. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qkd/BB84.py +0 -0
  103. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qkd/__init__.py +0 -0
  104. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qkd/cascade.py +0 -0
  105. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qlan/correction.py +0 -0
  106. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qlan/graph_gen.py +0 -0
  107. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/qlan/measurement.py +0 -0
  108. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/resource_management/__init__.py +0 -0
  109. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/resource_management/memory_manager.py +0 -0
  110. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/__init__.py +0 -0
  111. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/qkd_topo.py +0 -0
  112. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/qlan/client.py +0 -0
  113. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/qlan/orchestrator.py +0 -0
  114. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/topology/qlan_star_topo.py +0 -0
  115. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/utils/__init__.py +0 -0
  116. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/utils/encoding.py +0 -0
  117. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/utils/log.py +0 -0
  118. {sequence-0.8.3.dev260767962 → sequence-0.8.5}/sequence/utils/noise.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sequence
3
- Version: 0.8.3.dev260767962
3
+ Version: 0.8.5
4
4
  Summary: Simulator of QUantum Network Communication (SeQUeNCe) is an open-source tool that allows modeling of quantum networks including photonic network components, control protocols, and applications.
5
5
  Keywords: quantum,network,discrete,event,simulator
6
6
  Author: Xiaoliang Wu, Joaquin Chung, Alexander Kolar, Alexander Kiefer, Eugene Wang, Tian Zhong, Rajkumar Kettimuthu, Martin Suchara, Robert Hayek, Ansh Singal, Caitao Zhan
@@ -22,19 +22,22 @@ Requires-Dist: matplotlib>=3.10.7
22
22
  Requires-Dist: networkx>=3.6.1
23
23
  Requires-Dist: numpy>=2.3.5
24
24
  Requires-Dist: pandas>=2.3.3
25
+ Requires-Dist: pandas-stubs~=2.3.3
25
26
  Requires-Dist: plotly>=6.5.0
26
27
  Requires-Dist: pytest>=9.0.2
27
28
  Requires-Dist: qutip>=5.2.2
28
29
  Requires-Dist: qutip-qip>=0.4.1
29
30
  Requires-Dist: scipy>=1.16.3
31
+ Requires-Dist: scipy-stubs~=1.16.3
32
+ Requires-Dist: seaborn>=0.13.2
30
33
  Requires-Dist: tqdm>=4.67.1
31
34
  Maintainer: Caitao Zhan, Robert Hayek
32
35
  Maintainer-email: Caitao Zhan <czhan@anl.gov>, Robert Hayek <rhayek@anl.gov>
33
36
  Requires-Python: >=3.11, <3.15
34
- Project-URL: Changelog, https://github.com/sequence-toolbox/SeQUeNCe/blob/master/CHANGELOG.md
35
- Project-URL: Documentation, https://sequence-rtd-tutorial.readthedocs.io/
36
37
  Project-URL: Homepage, https://github.com/sequence-toolbox/SeQUeNCe
38
+ Project-URL: Documentation, https://sequence-rtd-tutorial.readthedocs.io/
37
39
  Project-URL: Issues, https://github.com/sequence-toolbox/SeQUeNCe/issues
40
+ Project-URL: Changelog, https://github.com/sequence-toolbox/SeQUeNCe/blob/master/CHANGELOG.md
38
41
  Description-Content-Type: text/markdown
39
42
 
40
43
  <p align="center">
@@ -75,22 +78,46 @@ SeQUeNCe is an open source, discrete-event simulator for quantum networks. As de
75
78
 
76
79
  These modules can be edited by users to define additional functionality and test protocol schemes, or may be used as-is to test network parameters and topologies.
77
80
 
78
- ## Installing
79
- SeQUeNCe requires [Python](https://www.python.org/downloads/) 3.11 or later. You can simply install SeQUeNCe using `pip`:
81
+ ## Installation
82
+ ### For Users
83
+ SeQUeNCe requires [Python](https://www.python.org/downloads/) 3.11 or later. You can install SeQUeNCe using `pip`:
80
84
  ```
81
85
  pip install sequence
82
86
  ```
83
87
 
84
- If you wish to make your own edits to the codebase, SeQUeNCe should be installed in [development mode](https://setuptools.pypa.io/en/latest/userguide/development_mode.html) (a.k.a. editable install).
85
- To do so, clone and install the simulator as follows:
88
+ ### Development Environment Setup
89
+ If you wish to modify the source code, use an editable installation with [uv](https://docs.astral.sh/uv/):
90
+
91
+ #### Install uv ([Astral Instructions](https://docs.astral.sh/uv/getting-started/installation/))
92
+ ```bash
93
+ # macOS/Linux
94
+ curl -LsSf https://astral.sh/uv/install.sh | sh
95
+
96
+ # Windows
97
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
86
98
  ```
99
+
100
+ #### Clone the repository and create the virtual environment
101
+ Here we clone the repository and let uv configure the development environment with the target python version.
102
+ ```bash
87
103
  git clone https://github.com/sequence-toolbox/SeQUeNCe.git
88
- cd SeQUeNCe
89
- pip install --editable . --config-settings editable_mode=strict
104
+ cd sequence
105
+ uv sync
90
106
  ```
91
107
 
92
- For Linux and Mac users, you could use `make install_editable` instead of `pip install --editable . --config-settings editable_mode=strict`
108
+ #### Activate the virtual environment
109
+ Now that the virtual environment is created with all dependencies installed, you can activate it using the following command.
110
+
111
+ ```bash
112
+ source .venv/bin/activate # macOS/Linux
113
+ source .venv\Scripts\activate # Windows
114
+ ```
93
115
 
116
+ #### Running the test suite
117
+ SeQUeNCe includes a comprehensive test suite, this can be ran with the following command
118
+ ```
119
+ uv run pytest tests
120
+ ```
94
121
 
95
122
  ## Citation
96
123
  Please cite us, thank you!
@@ -111,7 +138,7 @@ publisher = {IOP Publishing},
111
138
  <!-- * X. Wu, A. Kolar, J. Chung, D. Jin, T. Zhong, R. Kettimuthu and M. Suchara. "SeQUeNCe: Simulator of QUantum Network Communication." GitHub repository, https://github.com/sequence-toolbox/SeQUeNCe, 2021. -->
112
139
 
113
140
  ## Running the GUI
114
- Once SeQUeNCe has been installed as described above, simply run the `gui.py` script found in the root of the project directory
141
+ Once SeQUeNCe has been installed as described above, run the `gui.py` script found in the root of the project directory
115
142
  ```
116
143
  python gui.py
117
144
  ```
@@ -122,9 +149,9 @@ Many examples of SeQUeNCe in action can be found in the [example](/example) fold
122
149
  ## Additional Tools
123
150
 
124
151
  ### Network Visualization
125
- The example directory contains an example json file `starlight.json` to specify a network topology, and the utils directory contains the script `draw_topo.py` to visualize json files. To use this script, the Graphviz library must be installed. Installation information can be found on the [Graphviz website](https://www.graphviz.org/download/).
152
+ The example directory contains an example .json file `starlight.json` to specify a network topology, and the utils directory contains the script `draw_topo.py` to visualize json files. To use this script, the Graphviz library must be installed. Installation information can be found on the [Graphviz website](https://www.graphviz.org/download/).
126
153
 
127
- To view a network, simply run the script and specify the relative location of your json file:
154
+ To view a network, run the script and specify the relative location of your .json file:
128
155
  ```
129
156
  python utils/draw_topo.py example/starlight.json
130
157
  ```
@@ -159,5 +186,6 @@ If you have questions, please contact [Caitao Zhan](https://caitaozhan.github.io
159
186
 
160
187
  * C. Zhan et al., ["Design and Simulation of the Adaptive Continuous Entanglement Generation Protocol"](https://arxiv.org/abs/2502.01964), QCNC 2025. [GitHub Repository](https://github.com/caitaozhan/adaptive-continuous)
161
188
 
189
+ * H. Miller et al., ["Simulation of a Heterogeneous Quantum Network"](https://arxiv.org/abs/2512.04211), arXiv preprint, 2025
162
190
 
163
191
  Please do a Pull Request to add your paper here!
@@ -36,22 +36,46 @@ SeQUeNCe is an open source, discrete-event simulator for quantum networks. As de
36
36
 
37
37
  These modules can be edited by users to define additional functionality and test protocol schemes, or may be used as-is to test network parameters and topologies.
38
38
 
39
- ## Installing
40
- SeQUeNCe requires [Python](https://www.python.org/downloads/) 3.11 or later. You can simply install SeQUeNCe using `pip`:
39
+ ## Installation
40
+ ### For Users
41
+ SeQUeNCe requires [Python](https://www.python.org/downloads/) 3.11 or later. You can install SeQUeNCe using `pip`:
41
42
  ```
42
43
  pip install sequence
43
44
  ```
44
45
 
45
- If you wish to make your own edits to the codebase, SeQUeNCe should be installed in [development mode](https://setuptools.pypa.io/en/latest/userguide/development_mode.html) (a.k.a. editable install).
46
- To do so, clone and install the simulator as follows:
46
+ ### Development Environment Setup
47
+ If you wish to modify the source code, use an editable installation with [uv](https://docs.astral.sh/uv/):
48
+
49
+ #### Install uv ([Astral Instructions](https://docs.astral.sh/uv/getting-started/installation/))
50
+ ```bash
51
+ # macOS/Linux
52
+ curl -LsSf https://astral.sh/uv/install.sh | sh
53
+
54
+ # Windows
55
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
47
56
  ```
57
+
58
+ #### Clone the repository and create the virtual environment
59
+ Here we clone the repository and let uv configure the development environment with the target python version.
60
+ ```bash
48
61
  git clone https://github.com/sequence-toolbox/SeQUeNCe.git
49
- cd SeQUeNCe
50
- pip install --editable . --config-settings editable_mode=strict
62
+ cd sequence
63
+ uv sync
51
64
  ```
52
65
 
53
- For Linux and Mac users, you could use `make install_editable` instead of `pip install --editable . --config-settings editable_mode=strict`
66
+ #### Activate the virtual environment
67
+ Now that the virtual environment is created with all dependencies installed, you can activate it using the following command.
54
68
 
69
+ ```bash
70
+ source .venv/bin/activate # macOS/Linux
71
+ source .venv\Scripts\activate # Windows
72
+ ```
73
+
74
+ #### Running the test suite
75
+ SeQUeNCe includes a comprehensive test suite, this can be ran with the following command
76
+ ```
77
+ uv run pytest tests
78
+ ```
55
79
 
56
80
  ## Citation
57
81
  Please cite us, thank you!
@@ -72,7 +96,7 @@ publisher = {IOP Publishing},
72
96
  <!-- * X. Wu, A. Kolar, J. Chung, D. Jin, T. Zhong, R. Kettimuthu and M. Suchara. "SeQUeNCe: Simulator of QUantum Network Communication." GitHub repository, https://github.com/sequence-toolbox/SeQUeNCe, 2021. -->
73
97
 
74
98
  ## Running the GUI
75
- Once SeQUeNCe has been installed as described above, simply run the `gui.py` script found in the root of the project directory
99
+ Once SeQUeNCe has been installed as described above, run the `gui.py` script found in the root of the project directory
76
100
  ```
77
101
  python gui.py
78
102
  ```
@@ -83,9 +107,9 @@ Many examples of SeQUeNCe in action can be found in the [example](/example) fold
83
107
  ## Additional Tools
84
108
 
85
109
  ### Network Visualization
86
- The example directory contains an example json file `starlight.json` to specify a network topology, and the utils directory contains the script `draw_topo.py` to visualize json files. To use this script, the Graphviz library must be installed. Installation information can be found on the [Graphviz website](https://www.graphviz.org/download/).
110
+ The example directory contains an example .json file `starlight.json` to specify a network topology, and the utils directory contains the script `draw_topo.py` to visualize json files. To use this script, the Graphviz library must be installed. Installation information can be found on the [Graphviz website](https://www.graphviz.org/download/).
87
111
 
88
- To view a network, simply run the script and specify the relative location of your json file:
112
+ To view a network, run the script and specify the relative location of your .json file:
89
113
  ```
90
114
  python utils/draw_topo.py example/starlight.json
91
115
  ```
@@ -120,5 +144,6 @@ If you have questions, please contact [Caitao Zhan](https://caitaozhan.github.io
120
144
 
121
145
  * C. Zhan et al., ["Design and Simulation of the Adaptive Continuous Entanglement Generation Protocol"](https://arxiv.org/abs/2502.01964), QCNC 2025. [GitHub Repository](https://github.com/caitaozhan/adaptive-continuous)
122
146
 
147
+ * H. Miller et al., ["Simulation of a Heterogeneous Quantum Network"](https://arxiv.org/abs/2512.04211), arXiv preprint, 2025
123
148
 
124
149
  Please do a Pull Request to add your paper here!
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sequence"
3
- version = "0.8.3.dev260767962"
3
+ version = "0.8.5"
4
4
  authors = [
5
5
  { name = "Xiaoliang Wu, Joaquin Chung, Alexander Kolar, Alexander Kiefer, Eugene Wang, Tian Zhong, Rajkumar Kettimuthu, Martin Suchara, Robert Hayek, Ansh Singal, Caitao Zhan", email = "czhan@anl.gov" }
6
6
  ]
@@ -32,11 +32,14 @@ dependencies = [
32
32
  "networkx>=3.6.1",
33
33
  "numpy>=2.3.5",
34
34
  "pandas>=2.3.3",
35
+ "pandas-stubs~=2.3.3",
35
36
  "plotly>=6.5.0",
36
37
  "pytest>=9.0.2",
37
38
  "qutip>=5.2.2",
38
39
  "qutip-qip>=0.4.1",
39
40
  "scipy>=1.16.3",
41
+ "scipy-stubs~=1.16.3",
42
+ "seaborn>=0.13.2",
40
43
  "tqdm>=4.67.1",
41
44
  ]
42
45
 
@@ -51,6 +54,18 @@ module-name = "sequence"
51
54
  [tool.setuptools.package-data]
52
55
  sequence = ["gui/user_templates.json", "gui/default_params.json", "gui/starlight.json"]
53
56
 
57
+ [tool.pytest.ini_options]
58
+ markers = [
59
+ "unit: Marks tests as unit tests",
60
+ ]
61
+
62
+ [dependency-groups]
63
+ dev = [
64
+ "coverage>=7.13.4",
65
+ "ruff>=0.15.1",
66
+ "ty>=0.0.16",
67
+ ]
68
+
54
69
  [project.urls]
55
70
  Homepage = "https://github.com/sequence-toolbox/SeQUeNCe"
56
71
  Documentation = "https://sequence-rtd-tutorial.readthedocs.io/"
@@ -84,6 +84,17 @@ class RequestApp:
84
84
  self.schedule_reservation(reservation)
85
85
  log.logger.info(f"Successful reservation of resources for request app on node {self.node.name}")
86
86
 
87
+ def get_other_reservation(self, reservation: Reservation) -> None:
88
+ """Method to add the approved reservation that is requested by other nodes. The responder will call this method
89
+
90
+ Args:
91
+ reservation (Reservation): reservation that uses the node of an application as the responder
92
+
93
+ Side Effects:
94
+ Will add calls to `add_memo_reservation_map` and `remove_memo_reservation_map` methods.
95
+ """
96
+ self.schedule_reservation(reservation)
97
+
87
98
  def add_memo_reservation_map(self, index: int, reservation: Reservation) -> None:
88
99
  """Maps memory index to the corresponding reservation.
89
100
 
@@ -132,23 +143,18 @@ class RequestApp:
132
143
  def get_throughput(self) -> float:
133
144
  return self.memory_counter / (self.end_t - self.start_t) * 1e12
134
145
 
135
- def get_other_reservation(self, reservation: Reservation) -> None:
136
- """Method to add the approved reservation that is requested by other nodes. The responder will call this method
137
146
 
138
- Args:
139
- reservation (Reservation): reservation that uses the node of application as the responder
147
+ def schedule_reservation(self, reservation: Reservation) -> None:
148
+ """Calling the `add_memo_reservation_map` and `remove_memo_reservation_map` methods at the
149
+ reservation's start_time and end_time for all timecards (memory) involved in the reservation.
140
150
 
141
- Side Effects:
142
- Will add calls to `add_memo_reservation_map` and `remove_memo_reservation_map` methods.
151
+ Args:
152
+ reservation (Reservation): reservation to schedule
143
153
  """
144
- self.schedule_reservation(reservation)
145
-
146
- def schedule_reservation(self, reservation: Reservation) -> None:
147
154
  if reservation.initiator == self.node.name:
148
155
  self.path = reservation.path
149
156
 
150
- reservation_protocol = self.node.network_manager.protocol_stack[1]
151
- for card in reservation_protocol.timecards:
157
+ for card in self.node.network_manager.get_timecards():
152
158
  if reservation in card.reservations:
153
159
  process = Process(self, "add_memo_reservation_map", [card.memory_index, reservation])
154
160
  event = Event(reservation.start_time, process)
@@ -166,9 +166,9 @@ class BSM(Entity):
166
166
  photon (Photon): photon to measure.
167
167
  """
168
168
 
169
- assert photon.encoding_type["name"] == self.encoding, \
170
- "BSM expecting photon with encoding '{}' received photon with encoding '{}'".format(
171
- self.encoding, photon.encoding_type["name"])
169
+ assert photon.encoding_type["name"] == self.encoding, (
170
+ f"BSM expecting photon with encoding '{self.encoding}' "
171
+ f"received photon with encoding '{photon.encoding_type['name']}'")
172
172
 
173
173
  # check if photon arrived later than current photon
174
174
  if self.photon_arrival_time < self.timeline.now():
@@ -678,8 +678,8 @@ class SingleHeraldedBSM(BSM):
678
678
  log.logger.debug(f'{self.name}: photonic BSM failed')
679
679
  else:
680
680
  p0, p1 = self.photons
681
- # if both memory successfully emit the photon in this round (consider memory emission inefficiency)
682
681
  if self.get_generator().random() > p0.loss and self.get_generator().random() > p1.loss:
682
+ # if both photons successfully arrive (not lost in memory or optical fiber) and the BSM is successful
683
683
  for idx, photon in enumerate(self.photons):
684
684
  detector = self.detectors[idx]
685
685
  detector.get(photon)
@@ -518,8 +518,8 @@ class QSDetectorFockInterference(QSDetector):
518
518
  arrival_time = self.timeline.now()
519
519
  self.arrival_times[input_port].append(arrival_time)
520
520
  # record in temporary photon list
521
- assert not self.temporary_photon_info[input_port], \
522
- "At most 1 Photon instance should arrive at an input port at a time."
521
+ assert not self.temporary_photon_info[input_port], (
522
+ "At most 1 Photon instance should arrive at an input port at a time.")
523
523
  self.temporary_photon_info[input_port]["photon"] = photon
524
524
  self.temporary_photon_info[input_port]["time"] = arrival_time
525
525
 
@@ -61,8 +61,8 @@ class Interferometer(Entity):
61
61
  May call get method of one attached receiver from the receivers attribute.
62
62
  """
63
63
 
64
- assert photon.encoding_type["name"] == "time_bin", \
65
- "Invalid photon encoding {} received by interferometer".format(photon.encoding_type["name"])
64
+ assert photon.encoding_type["name"] == "time_bin", (
65
+ "Invalid photon encoding {} received by interferometer".format(photon.encoding_type["name"]))
66
66
  if photon.use_qm:
67
67
  raise NotImplementedError("Interferometer usage not configured for quantum manager.")
68
68
 
@@ -4,10 +4,10 @@ This module defines the Memory class to simulate single atom memories as well as
4
4
  Memories will attempt to send photons through the `send_qubit` interface of nodes.
5
5
  Photons should be routed to a BSM device for entanglement generation, or through optical hardware for purification and swapping.
6
6
  """
7
-
7
+ from __future__ import annotations
8
8
  from copy import copy
9
9
  from math import inf
10
- from typing import Any, TYPE_CHECKING
10
+ from typing import Any, TYPE_CHECKING, Iterator
11
11
  from collections.abc import Callable
12
12
  from numpy import exp, array
13
13
  from scipy import stats
@@ -46,7 +46,7 @@ class MemoryArray(Entity):
46
46
 
47
47
  def __init__(self, name: str, timeline: "Timeline", num_memories=10,
48
48
  fidelity=0.85, frequency=80e6, efficiency=1, coherence_time=-1, wavelength=500,
49
- decoherence_errors: list[float] = None, cutoff_ratio = 1):
49
+ decoherence_errors: list[float] = None, cutoff_ratio: float = 1, cutoff_flag: bool = True):
50
50
  """Constructor for the Memory Array class.
51
51
 
52
52
  Args:
@@ -60,15 +60,16 @@ class MemoryArray(Entity):
60
60
  wavelength (int): wavelength (in nm) of photons emitted by memories (default 500).
61
61
  decoherence_errors (list[int]): pauli decoherence errors. Passed to memory object.
62
62
  cutoff_ratio (float): the ratio between cutoff time and memory coherence time (default 1, should be between 0 and 1).
63
+ cutoff_flag (bool): Flag to enable or disable expiry events
63
64
  """
64
65
 
65
66
  Entity.__init__(self, name, timeline)
66
- self.memories = []
67
+ self.memories: list[Memory] = []
67
68
  self.memory_name_to_index = {}
68
69
 
69
70
  if decoherence_errors is not None:
70
- assert QuantumManager.get_active_formalism() == BELL_DIAGONAL_STATE_FORMALISM, \
71
- "Decoherence errors can only be set when formalism is Bell Diagonal"
71
+ assert QuantumManager.get_active_formalism() == BELL_DIAGONAL_STATE_FORMALISM, (
72
+ "Decoherence errors can only be set when formalism is Bell Diagonal")
72
73
 
73
74
  # Set the default pauli errors if BDS formalism
74
75
  if QuantumManager.get_active_formalism() == BELL_DIAGONAL_STATE_FORMALISM and decoherence_errors is None:
@@ -77,7 +78,7 @@ class MemoryArray(Entity):
77
78
  for i in range(num_memories):
78
79
  memory_name = self.name + f"[{i}]"
79
80
  self.memory_name_to_index[memory_name] = i
80
- memory = Memory(memory_name, timeline, fidelity, frequency, efficiency, coherence_time, wavelength, decoherence_errors, cutoff_ratio)
81
+ memory = Memory(memory_name, timeline, fidelity, frequency, efficiency, coherence_time, wavelength, decoherence_errors, cutoff_ratio, cutoff_flag)
81
82
  memory.attach(self)
82
83
  self.memories.append(memory)
83
84
  memory.set_memory_array(self)
@@ -91,6 +92,9 @@ class MemoryArray(Entity):
91
92
  def __len__(self) -> int:
92
93
  return len(self.memories)
93
94
 
95
+ def __iter__(self) -> Iterator[Memory]:
96
+ return iter(self.memories)
97
+
94
98
  def init(self):
95
99
  """Implementation of Entity interface (see base class).
96
100
 
@@ -127,7 +131,7 @@ class MemoryArray(Entity):
127
131
 
128
132
  Args:
129
133
  name (str): name of memory
130
- Return:
134
+ Returns:
131
135
  (Memory): the memory object
132
136
  """
133
137
  index = self.memory_name_to_index.get(name, -1)
@@ -187,7 +191,7 @@ class Memory(Entity):
187
191
  """
188
192
 
189
193
  def __init__(self, name: str, timeline: "Timeline", fidelity: float, frequency: float,
190
- efficiency: float, coherence_time: float, wavelength: int, decoherence_errors: list[float] = None, cutoff_ratio: float = 1):
194
+ efficiency: float, coherence_time: float, wavelength: int, decoherence_errors: list[float] = None, cutoff_ratio: float = 1, cutoff_flag: bool = True):
191
195
  """Constructor for the Memory class.
192
196
 
193
197
  Args:
@@ -202,7 +206,8 @@ class Memory(Entity):
202
206
  decoherence_errors (list[float]): assuming the memory (qubit) decoherence channel being Pauli channel,
203
207
  probability distribution of X, Y, Z Pauli errors
204
208
  (default value is None, meaning not using BDS or further density matrix representation)
205
- cutoff_ratio (float): the ratio between cutoff time and memory coherence time (default 1, should be between 0 and 1).
209
+ cutoff_ratio (float): the ratio between cutoff time and memory coherence time (default 1, should be > 0).
210
+ cutoff_flag (bool): Flag for the cutoff behavior
206
211
  """
207
212
 
208
213
  super().__init__(name, timeline)
@@ -221,10 +226,11 @@ class Memory(Entity):
221
226
 
222
227
  self.decoherence_errors = decoherence_errors
223
228
  if self.decoherence_errors is not None:
224
- assert len(self.decoherence_errors) == 3 and abs(sum(self.decoherence_errors) - 1) < EPSILON, \
225
- "Decoherence errors refer to probabilities for each Pauli error to happen if an error happens, thus should be normalized."
229
+ error_msg = "Decoherence errors refer to probabilities for each Pauli error to happen if an error happens, thus should be normalized."
230
+ assert len(self.decoherence_errors) == 3 and abs(sum(self.decoherence_errors) - 1) < EPSILON, error_msg
231
+ self.cutoff_flag = cutoff_flag
226
232
  self.cutoff_ratio = cutoff_ratio
227
- assert 0 < self.cutoff_ratio <= 1, "Ratio of cutoff time and coherence time should be between 0 and 1"
233
+ assert 0 < self.cutoff_ratio, "Ratio of cutoff time and coherence time should be greater than 0."
228
234
  self.generation_time = -1
229
235
  self.last_update_time = -1
230
236
  self.is_in_application = False
@@ -359,7 +365,7 @@ class Memory(Entity):
359
365
  self.entangled_memory = {'node_id': None, 'memo_id': None}
360
366
 
361
367
  # schedule expiration
362
- if self.coherence_time > 0:
368
+ if self.coherence_time > 0 and self.cutoff_flag:
363
369
  self._schedule_expiration()
364
370
 
365
371
  def bds_decohere(self) -> None:
@@ -380,13 +386,13 @@ class Memory(Entity):
380
386
  time = (self.timeline.now() - self.last_update_time) * 1e-12 # duration of memory idling (in s)
381
387
  if time > 0 and self.last_update_time > 0: # time > 0 means time has progressed, self.last_update_time > 0 means the memory has not been reset
382
388
 
383
- x_rate, y_rate, z_rate = self.decoherence_rate * self.decoherence_errors[0], \
384
- self.decoherence_rate * self.decoherence_errors[1], \
385
- self.decoherence_rate * self.decoherence_errors[2]
386
- p_I, p_X, p_Y, p_Z = _p_id(x_rate, y_rate, z_rate, time), \
387
- _p_xerr(x_rate, y_rate, z_rate, time), \
388
- _p_yerr(x_rate, y_rate, z_rate, time), \
389
- _p_zerr(x_rate, y_rate, z_rate, time)
389
+ x_rate = self.decoherence_rate * self.decoherence_errors[0]
390
+ y_rate = self.decoherence_rate * self.decoherence_errors[1]
391
+ z_rate = self.decoherence_rate * self.decoherence_errors[2]
392
+ p_I = _p_id(x_rate, y_rate, z_rate, time)
393
+ p_X = _p_xerr(x_rate, y_rate, z_rate, time)
394
+ p_Y = _p_yerr(x_rate, y_rate, z_rate, time)
395
+ p_Z = _p_zerr(x_rate, y_rate, z_rate, time)
390
396
 
391
397
  state_now = self.timeline.quantum_manager.states[self.qstate_key].state # current diagonal elements
392
398
  transform_mtx = array([[p_I, p_Z, p_X, p_Y],
@@ -443,7 +449,7 @@ class Memory(Entity):
443
449
  for observer in self._observers:
444
450
  observer.memory_expire(self)
445
451
 
446
- def detach(self, observer: 'EntanglementProtocol'): # observer could be a MemoryArray
452
+ def detach(self, observer: "EntanglementProtocol | MemoryArray"): # observer could be a MemoryArray
447
453
  if observer in self._observers:
448
454
  self._observers.remove(observer)
449
455
 
@@ -460,7 +466,7 @@ class Memory(Entity):
460
466
  def get_bds_fidelity(self) -> float:
461
467
  """Will get the fidelity from the BDS state
462
468
 
463
- Return:
469
+ Returns:
464
470
  (float): the fidelity of the BDS state
465
471
  """
466
472
  state_obj = self.timeline.quantum_manager.get(self.qstate_key)
@@ -0,0 +1,58 @@
1
+ """Shared constants used across SeQUeNCe.
2
+
3
+ This module centralizes immutable values that are reused by simulation and
4
+ network components, including:
5
+
6
+ - Physical constants (for example, speed of light in meters per picosecond).
7
+ - Canonical quantum state vectors (basis states and Bell states).
8
+ - Numerical tolerances (`EPSILON`) for floating-point comparisons.
9
+ - Time unit conversion factors in picoseconds (`NANOSECOND` to `SECOND`).
10
+ - Built-in formalism and protocol identifier strings.
11
+ """
12
+
13
+ from typing import Final
14
+
15
+ #: Speed of light in meters per picosecond.
16
+ SPEED_OF_LIGHT: Final = 2e-4
17
+
18
+ #: Qubit computational basis state |0>.
19
+ KET0: Final = (1, 0)
20
+ #: Qubit computational basis state |1>.
21
+ KET1: Final = (0, 1)
22
+
23
+ #: Normalization factor 1/sqrt(2) used by Bell states.
24
+ SQRT_HALF: Final = 0.5 ** 0.5
25
+ #: Bell state |Phi+>.
26
+ PHI_PLUS: Final = (SQRT_HALF, 0, 0, SQRT_HALF)
27
+ #: Bell state |Phi->.
28
+ PHI_MINUS: Final = (SQRT_HALF, 0, 0, -SQRT_HALF)
29
+ #: Bell state |Psi+>.
30
+ PSI_PLUS: Final = (0, SQRT_HALF, SQRT_HALF, 0)
31
+ #: Bell state |Psi->.
32
+ PSI_MINUS: Final = (0, SQRT_HALF, -SQRT_HALF, 0)
33
+
34
+ #: Small tolerance value for floating-point comparisons.
35
+ EPSILON: Final = 1e-8
36
+
37
+ #: Number of picoseconds in one nanosecond.
38
+ NANOSECOND: Final = 10**3
39
+ #: Number of picoseconds in one microsecond.
40
+ MICROSECOND: Final = 10**6
41
+ #: Number of picoseconds in one millisecond.
42
+ MILLISECOND: Final = 10**9
43
+ #: Number of picoseconds in one second.
44
+ SECOND: Final = 10**12
45
+
46
+ #: Built-in ket-vector formalism identifier.
47
+ KET_STATE_FORMALISM: Final = "ket_vector"
48
+ #: Built-in density-matrix formalism identifier.
49
+ DENSITY_MATRIX_FORMALISM: Final = "density_matrix"
50
+ #: Built-in Fock density-matrix formalism identifier.
51
+ FOCK_DENSITY_MATRIX_FORMALISM: Final = "fock_density"
52
+ #: Built-in Bell-diagonal-state formalism identifier.
53
+ BELL_DIAGONAL_STATE_FORMALISM: Final = "bell_diagonal"
54
+
55
+ #: Built-in Barrett-Kok generation protocol identifier.
56
+ BARRET_KOK: Final = 'barret_kok'
57
+ #: Built-in single-heralded generation protocol identifier.
58
+ SINGLE_HERALDED: Final = 'single_heralded'
@@ -25,7 +25,6 @@ class EntanglementProtocol(Protocol):
25
25
  def __init__(self, owner: "Node", name: str):
26
26
  super().__init__(owner, name)
27
27
  self.rule = None
28
- self.protocol_type = None
29
28
  self.memories = []
30
29
 
31
30
  @abstractmethod
@@ -180,8 +180,7 @@ class BarretKokA(EntanglementGenerationA, QuantumCircuitMixin):
180
180
 
181
181
  # schedule emit
182
182
  emit_time = self.owner.schedule_qubit(self.middle, msg.emit_time)
183
- assert emit_time == msg.emit_time, \
184
- f"Invalid eg emit times {emit_time} {msg.emit_time} {self.owner.timeline.now()}"
183
+ assert emit_time == msg.emit_time, f"Invalid eg emit times {emit_time} {msg.emit_time} {self.owner.timeline.now()}"
185
184
 
186
185
  process = Process(self, "emit_event", [])
187
186
  event = Event(msg.emit_time, process)
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from math import sqrt
3
- from typing import TYPE_CHECKING, List, Dict, Type, Any
3
+ from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from .generation_message import EntanglementGenerationMessage, GenerationMsgType
6
6
  from ...resource_management.memory_manager import MemoryInfo
@@ -30,7 +30,7 @@ class EntanglementGenerationA(EntanglementProtocol, ABC):
30
30
  This class provides a framework for implementing entanglement generation protocols
31
31
 
32
32
  Class Attributes:
33
- _registry (dict[str, Type['EntanglementGenerationA']]): A registry mapping protocol names to their corresponding classes.
33
+ _registry (dict[str, type['EntanglementGenerationA']]): A registry mapping protocol names to their corresponding classes.
34
34
  _global_type (str): The globally set protocol type used when creating new instances. Defaults to BARRET_KOK, other options: SINGLE_HERALDED
35
35
 
36
36
  Instance Attributes:
@@ -39,14 +39,14 @@ class EntanglementGenerationA(EntanglementProtocol, ABC):
39
39
  remote_node_name (str): The name of the remote node involved in the protocol.
40
40
  remote_protocol_name (str): The name of the remote protocol instance paired to this protocol.
41
41
  memory (Memory): The memory managed by this protocol.
42
- memories (List[Memory]): A list containing the single memory managed by this protocol.
42
+ memories (list[Memory]): A list containing the single memory managed by this protocol.
43
43
  remote_memo_id (str): The identifier (name) of the remote memory used in the protocol.
44
44
  qc_delay (int): The quantum channel delay to the middle node (in ps).
45
45
  expected_time (int): expected time for middle BSM node to receive the photon (in ps).
46
46
  fidelity (float): The fidelity of the entangled state produced by the protocol.
47
47
  ent_round (int): The current round of entanglement generation (total two rounds in Barrett-Kok).
48
- bsm_res (List[int]): The result of the Bell State Measurement (BSM), initialized to [-1, -1].
49
- scheduled_events (List[Event]): A list of scheduled events for the protocol.
48
+ bsm_res (list[int]): The result of the Bell State Measurement (BSM), initialized to [-1, -1].
49
+ scheduled_events (list[Event]): A list of scheduled events for the protocol.
50
50
  primary (bool): Indicates if this node is the primary node in the protocol (based on lexicographical order of node names).
51
51
  _qstate_key (int): The key of the quantum states associated with the memory used in the protocol.
52
52
  """
@@ -121,8 +121,7 @@ class EntanglementGenerationA(EntanglementProtocol, ABC):
121
121
  return list(cls._registry.keys())
122
122
 
123
123
  def set_others(self, protocol: str, node: str, memories: list[str]) -> None:
124
- assert self.remote_protocol_name == '', \
125
- "Remote protocol name has been set before, cannot set again."
124
+ assert self.remote_protocol_name == '', "Remote protocol name has been set before, cannot set again."
126
125
 
127
126
  self.remote_protocol_name = protocol
128
127
  self.remote_memo_id = memories[0]
@@ -169,8 +168,7 @@ class EntanglementGenerationA(EntanglementProtocol, ABC):
169
168
  return self.remote_protocol_name != ''
170
169
 
171
170
  def memory_expire(self, memory: "Memory") -> None:
172
- assert memory == self.memory, \
173
- "Memory to expire does not match the protocol's memory"
171
+ assert memory == self.memory, "Memory to expire does not match the protocol's memory"
174
172
  self.update_resource_manager(memory, MemoryInfo.RAW)
175
173
  for event in self.scheduled_events:
176
174
  if event.time >= self.owner.timeline.now():