16#include "ns3/q2ns-qnode.h"
17#include "ns3/q2ns-qstate-registry.h"
18#include "ns3/q2ns-qstate.h"
19#include "ns3/q2ns-qubit.h"
27NS_LOG_COMPONENT_DEFINE(
"QProcessor");
30 : registry_(registry), owner_(owner) {}
42 if (!label.empty() &&
GetQubit(label)) {
44 "CreateQubit received a duplicate local label '"
46 <<
"'. A new qubit will still be created, but label-based lookup may be ambiguous.");
50 auto q = std::make_shared<Qubit>(
registry_, res.stateId, res.indices[0], label);
53 q->SetLocationNode(
owner_.GetId());
61 const std::string& label) {
63 NS_LOG_WARN(
"CreateQubit rejected: null state.");
67 if (!label.empty() &&
GetQubit(label)) {
68 NS_LOG_WARN(
"CreateQubit received a duplicate local label '"
69 << label <<
"'. Label-based lookup may be ambiguous.");
73 auto q = std::make_shared<Qubit>(
registry_, res.stateId, res.indices[0], label);
76 q->SetLocationNode(
owner_.GetId());
85 auto q0 = std::make_shared<Qubit>(
registry_, created.stateId, created.indices[0],
"bell0");
86 auto q1 = std::make_shared<Qubit>(
registry_, created.stateId, created.indices[1],
"bell1");
90 q0->SetLocationNode(
owner_.GetId());
91 q1->SetLocationNode(
owner_.GetId());
103 NS_LOG_WARN(
"GetQubit failed: label is empty.");
108 if (q && q->GetLabel() == label) {
113 NS_LOG_WARN(
"GetQubit failed: no qubit found in local qubits with label=" << label <<
".");
122 NS_LOG_WARN(
"GetQubit failed: no matching qubit.");
131 NS_LOG_WARN(
"GetQubit failed: no qubit found in local qubits with id=" <<
id <<
".");
145 NS_LOG_WARN(
"AdoptQubit rejected: null qubit.");
149 const auto loc = q->GetLocation();
151 NS_LOG_WARN(
"AdoptQubit rejected: qubit is lost.");
155 q->SetLocationNode(
owner_.GetId());
162 NS_LOG_WARN(
"GetState rejected: null qubit.");
172 NS_LOG_WARN(
"Apply rejected: empty qubit list.");
176 for (
const auto& q : qs) {
178 NS_LOG_WARN(
"Apply rejected: null qubit in target list.");
184 NS_LOG_WARN(
"Apply rejected: target qubit is not local to this node.");
193 NS_LOG_WARN(
"Apply failed: state merge did not produce a valid backend state.");
197 std::vector<q2ns::Index> targets;
198 targets.reserve(qs.size());
199 for (
const auto& q : qs) {
200 targets.push_back(q->GetIndexInState());
203 st->Apply(gate, targets);
211 NS_LOG_WARN(
"Measure rejected: null qubit.");
217 NS_LOG_WARN(
"Measure rejected: qubit is not local to this node.");
223 NS_LOG_WARN(
"Measure failed: could not retrieve the qubit's current state.");
231 std::sort(related.begin(), related.end(), [](
const auto& a,
const auto& b) {
232 return a->GetIndexInState() < b->GetIndexInState();
235 const auto removedIndex = q->GetIndexInState();
236 auto split = currentState->Measure(removedIndex, basis);
237 const int result =
static_cast<int>(split.outcome);
242 for (
const auto& r : related) {
251 q->SetStateId(newMeasured.stateId);
252 q->SetIndexInState(newMeasured.indices[0]);
258 if (split.survivors && split.survivors->NumQubits() > 0) {
262 unsigned int nextIdx = 0;
263 for (
const auto& r : related) {
264 if (r.get() == q.get()) {
271 r->SetStateId(survivorsRes.stateId);
272 r->SetIndexInState(survivorsRes.indices[nextIdx++]);
280 if (remaining.empty()) {
290 const std::shared_ptr<Qubit>& b) {
292 NS_LOG_WARN(
"MeasureBell rejected: null qubit.");
296 const auto locA = a->GetLocation();
298 NS_LOG_WARN(
"MeasureBell rejected: first qubit " << a->GetQubitId() <<
" is lost.");
302 const auto locB = b->GetLocation();
304 NS_LOG_WARN(
"MeasureBell rejected: second qubit " << b->GetQubitId() <<
" is lost.");
312 NS_LOG_WARN(
"MeasureBell rejected: qubits are not both local to this node.");
328 return {resultA, resultB};
Lightweight gate descriptor used by QState backends.
Main user-facing per-node API for quantum operations and transmission.
int Measure(const std::shared_ptr< Qubit > &qubit, q2ns::Basis basis=q2ns::Basis::Z)
Measure a single, local qubit in the given basis (default Z).
std::pair< int, int > MeasureBell(const std::shared_ptr< Qubit > &a, const std::shared_ptr< Qubit > &b)
Perform a Bell-state measurement on two local qubits.
void AdoptQubit(const std::shared_ptr< Qubit > &q)
Adopt a qubit into this processor's owning node.
QProcessor(QStateRegistry ®istry, QNode &owner)
Construct a processor bound to a registry and owning node.
std::shared_ptr< QState > GetState(const std::shared_ptr< Qubit > &q) const
Get the current state of the qubit.
std::pair< std::shared_ptr< Qubit >, std::shared_ptr< Qubit > > CreateBellPair()
Create a local Bell pair in |Phi+>
QNode & owner_
Owning QNode.
std::shared_ptr< Qubit > GetQubit(const std::string &label) const
Lookup a local qubit by application label.
const QNode & GetOwnerNode() const
Get owning node.
std::shared_ptr< Qubit > CreateQubit(const std::string &label="")
Create a new local qubit in |0>.
bool Apply(const QGate &gate, const std::vector< std::shared_ptr< Qubit > > &qs)
Apply a gate to one or more local qubits.
QStateRegistry & registry_
Quantum state registry.
std::vector< std::shared_ptr< Qubit > > GetLocalQubits() const
Return the qubits currently located at the owning node.
Internal registry that owns backend states and tracks qubit membership and location.
void RemoveState(StateId id)
Remove a backend state and its membership tracking.
void Register(const std::shared_ptr< Qubit > &q)
Register a qubit handle as a member of its current state.
void SetLocation(const std::shared_ptr< Qubit > &q, Location loc)
Set the tracked location for a qubit handle.
CreateStateResult CreateState(unsigned int n)
Create a new state with n qubits initialized in the |0...0> state.
std::shared_ptr< QState > GetState(StateId stateId) const
Get a backend state by state id.
void UnregisterEverywhere(const std::shared_ptr< Qubit > &q)
Remove a qubit handle from membership lists across all states.
std::vector< std::shared_ptr< Qubit > > GetLocalQubits(uint32_t nodeId) const
Return qubit handles currently located at a given node.
CreateStateResult CreateStateFromExisting(const std::shared_ptr< QState > &state)
Register an already-constructed backend state object.
std::shared_ptr< Qubit > GetQubitHandle(QubitId id) const
Return a tracked qubit handle by qubit id.
Location GetLocation(const std::shared_ptr< Qubit > &q) const
Get the tracked location for a qubit handle.
std::shared_ptr< QState > MergeStates(const std::vector< std::shared_ptr< Qubit > > &qs)
Ensure the provided qubits belong to a single backend state.
std::vector< std::shared_ptr< Qubit > > QubitsOf(StateId stateId) const
Return qubit handles that currently belong to a given state.
std::uint64_t QubitId
Stable identifier for a registered qubit handle.
Basis
Measurement basis for single-qubit projective measurement.
@ Node
Qubit is local to a node identified by node id.
@ Lost
Qubit was lost and is no longer accessible.
QGate H(ns3::Time d=ns3::Seconds(0))
Return the Hadamard gate descriptor.
QGate CNOT(ns3::Time d=ns3::Seconds(0))
Return the CNOT gate descriptor.
Declares q2ns::QProcessor, a per-node processor that handles local quantum state operations.