Q2NS dev
ns-3 module
Loading...
Searching...
No Matches
q2ns-qmap.h
Go to the documentation of this file.
1/*-----------------------------------------------------------------------------
2 * Q2NS - Quantum Network Simulator
3 * Copyright (c) 2026 quantuminternet.it
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *---------------------------------------------------------------------------*/
9/**
10 * @file q2ns-qmap.h
11 * @brief Declares q2ns::QMap and standard channel-map models.
12 */
13
14#pragma once
15
16#include "ns3/nstime.h"
17#include "ns3/object.h"
18#include "ns3/ptr.h"
19#include "ns3/random-variable-stream.h"
20
21#include "ns3/q2ns-types.h"
22
23#include <cmath>
24#include <functional>
25#include <memory>
26#include <vector>
27
28namespace q2ns {
29
30class QNode;
31class QGate;
32class Qubit;
33
34/**
35 * @struct QMapContext
36 * @brief Optional per-sample context passed to QMaps.
37 *
38 * This is intentionally small today, but can be extended later with additional
39 * context such as distance, wavelength, or metadata about a traversed link.
40 */
42 ns3::Time elapsedTime{ns3::Seconds(0)}; //!< Elapsed time that this map is applied over
43};
44
45/**
46 * @ingroup q2ns_qmap
47 * @class QMap
48 * @brief Abstract base class for channel map models.
49 *
50 * A QMap does not directly mutate a qubit when the channel is configured.
51 * Instead, it samples a per-transmission QMapInstance that is carried alongside
52 * the transmitted qubit and later executed by the receiving QNode after the
53 * qubit becomes local there.
54 *
55 * Most probabilistic QMaps share two common knobs:
56 * - Probability: direct per-transmission application probability
57 * - Rate: Poisson event rate in 1/s, converted to a per-flight probability
58 *
59 * If Rate is greater than zero, it overrides Probability using the current
60 * flight time in the provided QMapContext.
61 *
62 * @see QMapInstance
63 * @see QNode
64 */
65class QMap : public ns3::Object {
66public:
67 /**
68 * @brief Get the ns-3 TypeId.
69 * @return TypeId for q2ns::QMap.
70 */
71 static ns3::TypeId GetTypeId();
72
73 /**
74 * @brief Virtual destructor.
75 */
76 ~QMap() override = default;
77
78 /**
79 * @brief Sample a per-transmission QMapInstance.
80 *
81 * The returned callable is later executed at the receiving node after the
82 * qubit has become local there.
83 *
84 * @param u Uniform random source to use for sampling.
85 * @param ctx Optional per-transmission context.
86 * @return Per-transmission QMapInstance. An empty callable represents the
87 * identity map.
88 */
89 virtual QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
90 const QMapContext& ctx = QMapContext{}) const = 0;
91
92 /**
93 * @brief Compose two QMaps into one sequential composite QMap.
94 *
95 * The resulting map applies the sampled instance of a first, then the sampled
96 * instance of b. If either step marks the qubit lost, later steps are not run.
97 *
98 * @param a First QMap in the sequence.
99 * @param b Second QMap in the sequence.
100 * @return Composite QMap object.
101 *
102 * @see Compose(const std::vector<ns3::Ptr<QMap>>&)
103 */
104 static ns3::Ptr<QMap> Compose(const ns3::Ptr<QMap>& a, const ns3::Ptr<QMap>& b);
105
106 /**
107 * @brief Compose a sequence of QMaps into one sequential composite QMap.
108 *
109 * Maps are applied left to right in the order provided.
110 *
111 * @param maps Sequence of maps to compose.
112 * @return Composite QMap object.
113 *
114 * @see Compose(const ns3::Ptr<QMap>&, const ns3::Ptr<QMap>&)
115 */
116 static ns3::Ptr<QMap> Compose(const std::vector<ns3::Ptr<QMap>>& maps);
117
118 /**
119 * @brief Build a QMap from a simple lambda.
120 *
121 * The lambda is executed at the receiving node and receives only the node and
122 * qubit handle.
123 *
124 * @param f User-provided callable.
125 * @return QMap wrapping the callable.
126 *
127 * @see FromLambda(std::function<void(QNode&, std::shared_ptr<Qubit>&,
128 * ns3::Ptr<ns3::UniformRandomVariable>, const QMapContext&)>)
129 */
130 static ns3::Ptr<QMap> FromLambda(std::function<void(QNode&, std::shared_ptr<Qubit>&)> f);
131
132 /**
133 * @brief Build a QMap from an advanced lambda.
134 *
135 * The lambda is executed at the receiving node and also receives the random
136 * source and sampled transmission context.
137 *
138 * @param f User-provided callable.
139 * @return QMap wrapping the callable.
140 *
141 * @see FromLambda(std::function<void(QNode&, std::shared_ptr<Qubit>&)>)
142 */
143 static ns3::Ptr<QMap>
144 FromLambda(std::function<void(QNode&, std::shared_ptr<Qubit>&,
145 ns3::Ptr<ns3::UniformRandomVariable>, const QMapContext&)>
146 f);
147
148 /**
149 * @brief Convert a Poisson rate and elapsed time into an event probability.
150 *
151 * This returns the probability of at least one event in time t under a
152 * Poisson process with rate rate_per_s.
153 *
154 * @param rate_per_s Event rate in 1/s.
155 * @param t Elapsed time.
156 * @return Probability in [0, 1].
157 */
158 static inline double RateToProb(double rate_per_s, const ns3::Time& t) {
159 const double s = t.GetSeconds();
160 if (rate_per_s <= 0.0 || s <= 0.0) {
161 return 0.0;
162 }
163 const double p = 1.0 - std::exp(-rate_per_s * s);
164 return (p < 0.0) ? 0.0 : (p > 1.0 ? 1.0 : p);
165 }
166
167protected:
168 /**
169 * @brief Return the effective application probability for this transmission.
170 * @param ctx Per-transmission context.
171 * @return Probability in [0, 1].
172 */
173 double GetProb_(const QMapContext& ctx) const {
174 return (rate_ > 0.0) ? RateToProb(rate_, ctx.elapsedTime) : p_;
175 }
176
177 /**
178 * @brief Perform one Bernoulli trial using the effective probability.
179 * @param u Uniform random source.
180 * @param ctx Per-transmission context.
181 * @return True if the event occurs, false otherwise.
182 */
183 bool Bernoulli_(ns3::Ptr<ns3::UniformRandomVariable> u, const QMapContext& ctx) const {
184 const double p = GetProb_(ctx);
185 if (p <= 0.0) {
186 return false;
187 }
188 if (p >= 1.0) {
189 return true;
190 }
191 return u->GetValue(0.0, 1.0) < p;
192 }
193
194 /**
195 * @brief Mark a qubit lost through the standard registry-backed location path.
196 * @param q Qubit handle.
197 */
198 static void SetLost_(Qubit& q);
199
200 double p_ = 0.0; //!< Direct per-transmission probability.
201 double rate_ = 0.0; //!< Poisson event rate in 1/s. Overrides p_ when positive.
202};
203
204/**
205 * @ingroup q2ns_qmap
206 * @class LambdaQMap
207 * @brief QMap implementation that wraps a user-provided lambda.
208 *
209 * LambdaQMap can store either:
210 * - a simple callable that receives only node and qubit
211 * - an advanced callable that also receives the RNG source and QMapContext
212 *
213 * If both are unset, sampling returns the identity map.
214 *
215 * @see QMap::FromLambda
216 */
217class LambdaQMap final : public QMap {
218public:
219 /**
220 * @brief Simple callable type.
221 */
222 using SimpleFn = std::function<void(QNode&, std::shared_ptr<Qubit>&)>;
223
224 /**
225 * @brief Advanced callable type.
226 */
227 using AdvancedFn = std::function<void(QNode&, std::shared_ptr<Qubit>&,
228 ns3::Ptr<ns3::UniformRandomVariable>, const QMapContext&)>;
229
230 /**
231 * @brief Get the ns-3 TypeId.
232 * @return TypeId for q2ns::LambdaQMap.
233 */
234 static ns3::TypeId GetTypeId();
235
236 /**
237 * @brief Default constructor.
238 */
239 LambdaQMap() = default;
240
241 /**
242 * @brief Construct from a simple callable.
243 * @param f Simple callable.
244 */
245 explicit LambdaQMap(SimpleFn f);
246
247 /**
248 * @brief Construct from an advanced callable.
249 * @param f Advanced callable.
250 */
251 explicit LambdaQMap(AdvancedFn f);
252
253 /**
254 * @brief Sample a per-transmission QMapInstance.
255 * @param u Uniform random source.
256 * @param ctx Per-transmission context.
257 * @return Sampled instance, or identity if no callable is configured.
258 */
259 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
260 const QMapContext& ctx = QMapContext{}) const override;
261
262 /**
263 * @brief Replace the stored callable with a simple callable.
264 * @param f Simple callable.
265 */
266 void Set(SimpleFn f);
267
268 /**
269 * @brief Replace the stored callable with an advanced callable.
270 * @param f Advanced callable.
271 */
272 void Set(AdvancedFn f);
273
274private:
275 SimpleFn simple_{}; //!< Simple callable, if configured.
276 AdvancedFn advanced_{}; //!< Advanced callable, if configured.
277};
278
279/**
280 * @ingroup q2ns_qmap
281 * @class ConditionalQMap
282 * @brief QMap wrapper that conditionally applies another QMap.
283 *
284 * The wrapped QMap is sampled normally, but its sampled instance is only
285 * executed if the configured predicate returns true.
286 */
287class ConditionalQMap final : public QMap {
288public:
289 /**
290 * @brief Predicate type controlling whether the wrapped map is applied.
291 */
292 using Condition = std::function<bool(const std::shared_ptr<Qubit>&, const QMapContext&)>;
293
294 /**
295 * @brief Get the ns-3 TypeId.
296 * @return TypeId for q2ns::ConditionalQMap.
297 */
298 static ns3::TypeId GetTypeId();
299
300 /**
301 * @brief Set the wrapped QMap.
302 * @param qmap Wrapped QMap.
303 */
304 void SetQMap(ns3::Ptr<QMap> qmap);
305
306 /**
307 * @brief Set the condition predicate.
308 * @param pred Predicate controlling application.
309 */
310 void SetCondition(Condition pred);
311
312 /**
313 * @brief Sample a per-transmission QMapInstance.
314 * @param u Uniform random source.
315 * @param ctx Per-transmission context.
316 * @return Sampled conditional instance.
317 */
318 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
319 const QMapContext& ctx = QMapContext{}) const override;
320
321private:
322 ns3::Ptr<QMap> qmap_; //!< Wrapped QMap.
323 Condition cond_; //!< Application predicate.
324};
325
326/**
327 * @ingroup q2ns_qmap
328 * @class DephasingQMap
329 * @brief Dephasing noise model that applies Z with probability p.
330 */
331class DephasingQMap final : public QMap {
332public:
333 /**
334 * @brief Get the ns-3 TypeId.
335 * @return TypeId for q2ns::DephasingQMap.
336 */
337 static ns3::TypeId GetTypeId();
338
339 /**
340 * @brief Sample a per-transmission QMapInstance.
341 * @param u Uniform random source.
342 * @param ctx Per-transmission context.
343 * @return Sampled dephasing instance.
344 */
345 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
346 const QMapContext& ctx = QMapContext{}) const override;
347};
348
349/**
350 * @ingroup q2ns_qmap
351 * @class DepolarizingQMap
352 * @brief Trajectory-style depolarizing model that applies a random Pauli from
353 * {X, Y, Z} with probability p.
354 */
355class DepolarizingQMap final : public QMap {
356public:
357 /**
358 * @brief Get the ns-3 TypeId.
359 * @return TypeId for q2ns::DepolarizingQMap.
360 */
361 static ns3::TypeId GetTypeId();
362
363 /**
364 * @brief Sample a per-transmission QMapInstance.
365 * @param u Uniform random source.
366 * @param ctx Per-transmission context.
367 * @return Sampled depolarizing instance.
368 */
369 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
370 const QMapContext& ctx = QMapContext{}) const override;
371};
372
373/**
374 * @ingroup q2ns_qmap
375 * @class LossQMap
376 * @brief Erasure model that marks the qubit lost with probability p.
377 */
378class LossQMap final : public QMap {
379public:
380 /**
381 * @brief Get the ns-3 TypeId.
382 * @return TypeId for q2ns::LossQMap.
383 */
384 static ns3::TypeId GetTypeId();
385
386 /**
387 * @brief Sample a per-transmission QMapInstance.
388 * @param u Uniform random source.
389 * @param ctx Per-transmission context.
390 * @return Sampled loss instance.
391 */
392 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
393 const QMapContext& ctx = QMapContext{}) const override;
394};
395
396/**
397 * @ingroup q2ns_qmap
398 * @class RandomGateQMap
399 * @brief QMap that samples one gate from a weighted distribution and applies it.
400 *
401 * The sampled gate is chosen once per transmission. As with other probabilistic
402 * QMaps, the overall application event may itself be gated by Probability or Rate.
403 */
404class RandomGateQMap final : public QMap {
405public:
406 /**
407 * @brief Get the ns-3 TypeId.
408 * @return TypeId for q2ns::RandomGateQMap.
409 */
410 static ns3::TypeId GetTypeId();
411
412 /**
413 * @brief Replace the weighted gate distribution.
414 * @param gates Candidate gates.
415 * @param weights Non-negative weights associated with the gates.
416 */
417 void SetDistribution(std::vector<QGate> gates, std::vector<double> weights);
418
419 /**
420 * @brief Append one weighted gate to the distribution.
421 * @param gate Gate to add.
422 * @param weight Non-negative selection weight.
423 */
424 void AddGate(const QGate& gate, double weight);
425
426 /**
427 * @brief Clear the weighted gate distribution.
428 */
429 void Clear();
430
431 /**
432 * @brief Sample a per-transmission QMapInstance.
433 * @param u Uniform random source.
434 * @param ctx Per-transmission context.
435 * @return Sampled random-gate instance.
436 */
437 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
438 const QMapContext& ctx = QMapContext{}) const override;
439
440private:
441 /**
442 * @brief Pick one gate index from the configured weighted distribution.
443 * @param u Uniform random source.
444 * @return Selected gate index.
445 */
446 std::size_t PickIndex_(ns3::Ptr<ns3::UniformRandomVariable> u) const;
447
448 std::vector<QGate> gates_; //!< Candidate gates.
449 std::vector<double> weights_; //!< Selection weights.
450 double totalWeight_ = 0.0; //!< Sum of all selection weights.
451};
452
453/**
454 * @ingroup q2ns_qmap
455 * @class RandomUnitaryQMap
456 * @brief QMap that applies one Haar-random single-qubit SU(2) unitary.
457 *
458 * The unitary is sampled once per transmission if the overall application event
459 * occurs.
460 */
461class RandomUnitaryQMap final : public QMap {
462public:
463 /**
464 * @brief Get the ns-3 TypeId.
465 * @return TypeId for q2ns::RandomUnitaryQMap.
466 */
467 static ns3::TypeId GetTypeId();
468
469 /**
470 * @brief Sample a per-transmission QMapInstance.
471 * @param u Uniform random source.
472 * @param ctx Per-transmission context.
473 * @return Sampled random-unitary instance.
474 */
475 QMapInstance Sample(ns3::Ptr<ns3::UniformRandomVariable> u,
476 const QMapContext& ctx = QMapContext{}) const override;
477
478private:
479 /**
480 * @brief Sample a Haar-random SU(2) matrix.
481 * @param u Uniform random source.
482 * @return Sampled 2x2 unitary matrix.
483 */
484 static Matrix SampleHaarSU2_(ns3::Ptr<ns3::UniformRandomVariable> u);
485};
486
487} // namespace q2ns
QMap wrapper that conditionally applies another QMap.
Definition q2ns-qmap.h:287
void SetQMap(ns3::Ptr< QMap > qmap)
Set the wrapped QMap.
Definition q2ns-qmap.cc:220
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:232
Condition cond_
Application predicate.
Definition q2ns-qmap.h:323
std::function< bool(const std::shared_ptr< Qubit > &, const QMapContext &)> Condition
Predicate type controlling whether the wrapped map is applied.
Definition q2ns-qmap.h:292
void SetCondition(Condition pred)
Set the condition predicate.
Definition q2ns-qmap.cc:226
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:210
ns3::Ptr< QMap > qmap_
Wrapped QMap.
Definition q2ns-qmap.h:322
Dephasing noise model that applies Z with probability p.
Definition q2ns-qmap.h:331
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:251
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:261
Trajectory-style depolarizing model that applies a random Pauli from {X, Y, Z} with probability p.
Definition q2ns-qmap.h:355
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:275
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:285
QMap implementation that wraps a user-provided lambda.
Definition q2ns-qmap.h:217
AdvancedFn advanced_
Advanced callable, if configured.
Definition q2ns-qmap.h:276
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:157
void Set(SimpleFn f)
Replace the stored callable with a simple callable.
Definition q2ns-qmap.cc:175
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:189
std::function< void(QNode &, std::shared_ptr< Qubit > &, ns3::Ptr< ns3::UniformRandomVariable >, const QMapContext &)> AdvancedFn
Advanced callable type.
Definition q2ns-qmap.h:228
LambdaQMap()=default
Default constructor.
std::function< void(QNode &, std::shared_ptr< Qubit > &)> SimpleFn
Simple callable type.
Definition q2ns-qmap.h:222
SimpleFn simple_
Simple callable, if configured.
Definition q2ns-qmap.h:275
Erasure model that marks the qubit lost with probability p.
Definition q2ns-qmap.h:378
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:322
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:312
Lightweight gate descriptor used by QState backends.
Definition q2ns-qgate.h:68
Abstract base class for channel map models.
Definition q2ns-qmap.h:65
~QMap() override=default
Virtual destructor.
static ns3::Ptr< QMap > Compose(const ns3::Ptr< QMap > &a, const ns3::Ptr< QMap > &b)
Compose two QMaps into one sequential composite QMap.
Definition q2ns-qmap.cc:122
double GetProb_(const QMapContext &ctx) const
Return the effective application probability for this transmission.
Definition q2ns-qmap.h:173
static double RateToProb(double rate_per_s, const ns3::Time &t)
Convert a Poisson rate and elapsed time into an event probability.
Definition q2ns-qmap.h:158
static void SetLost_(Qubit &q)
Mark a qubit lost through the standard registry-backed location path.
Definition q2ns-qmap.cc:55
static ns3::Ptr< QMap > FromLambda(std::function< void(QNode &, std::shared_ptr< Qubit > &)> f)
Build a QMap from a simple lambda.
Definition q2ns-qmap.cc:140
double p_
Direct per-transmission probability.
Definition q2ns-qmap.h:200
double rate_
Poisson event rate in 1/s. Overrides p_ when positive.
Definition q2ns-qmap.h:201
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:35
bool Bernoulli_(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx) const
Perform one Bernoulli trial using the effective probability.
Definition q2ns-qmap.h:183
virtual QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const =0
Sample a per-transmission QMapInstance.
Main user-facing per-node API for quantum operations and transmission.
Definition q2ns-qnode.h:63
Lightweight handle for one qubit inside a registry-managed state.
Definition q2ns-qubit.h:48
QMap that samples one gate from a weighted distribution and applies it.
Definition q2ns-qmap.h:404
std::size_t PickIndex_(ns3::Ptr< ns3::UniformRandomVariable > u) const
Pick one gate index from the configured weighted distribution.
Definition q2ns-qmap.cc:379
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:336
void SetDistribution(std::vector< QGate > gates, std::vector< double > weights)
Replace the weighted gate distribution.
Definition q2ns-qmap.cc:363
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:396
void AddGate(const QGate &gate, double weight)
Append one weighted gate to the distribution.
Definition q2ns-qmap.cc:354
double totalWeight_
Sum of all selection weights.
Definition q2ns-qmap.h:450
void Clear()
Clear the weighted gate distribution.
Definition q2ns-qmap.cc:346
std::vector< QGate > gates_
Candidate gates.
Definition q2ns-qmap.h:448
std::vector< double > weights_
Selection weights.
Definition q2ns-qmap.h:449
QMap that applies one Haar-random single-qubit SU(2) unitary.
Definition q2ns-qmap.h:461
QMapInstance Sample(ns3::Ptr< ns3::UniformRandomVariable > u, const QMapContext &ctx=QMapContext{}) const override
Sample a per-transmission QMapInstance.
Definition q2ns-qmap.cc:458
static Matrix SampleHaarSU2_(ns3::Ptr< ns3::UniformRandomVariable > u)
Sample a Haar-random SU(2) matrix.
Definition q2ns-qmap.cc:432
static ns3::TypeId GetTypeId()
Get the ns-3 TypeId.
Definition q2ns-qmap.cc:418
Eigen::MatrixXcd Matrix
Dynamic complex matrix type used for custom gates and matrix-based states.
Definition q2ns-types.h:43
std::function< void(QNode &, std::shared_ptr< Qubit > &)> QMapInstance
Per-transmission quantum map callable applied to a received qubit.
Definition q2ns-types.h:71
Optional per-sample context passed to QMaps.
Definition q2ns-qmap.h:41
ns3::Time elapsedTime
Elapsed time that this map is applied over.
Definition q2ns-qmap.h:42