diff --git a/.project b/.project new file mode 100644 index 000000000..0f4eb150e --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + quisp + + + + + + + + diff --git a/quisp/.cproject b/quisp/.cproject index 9992fc358..f708e1696 100644 --- a/quisp/.cproject +++ b/quisp/.cproject @@ -1,210 +1,106 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/quisp/.tmp16996 b/quisp/.tmp16996 new file mode 100644 index 000000000..e6fbd2402 --- /dev/null +++ b/quisp/.tmp16996 @@ -0,0 +1 @@ +out/clang-release//channels/QuantumChannel.o out/clang-release//modules/dummyModule.o out/clang-release//modules/Application/Application.o out/clang-release//modules/Common/Queue.o out/clang-release//modules/Common/Router.o out/clang-release//modules/PhysicalConnection/BSA/BellStateAnalyzer.o out/clang-release//modules/PhysicalConnection/BSA/HoMController.o out/clang-release//modules/PhysicalConnection/EPPS/EntangledPhotonPairSource.o out/clang-release//modules/PhysicalConnection/EPPS/SPDC_Controller.o out/clang-release//modules/QNIC/PhotonicSwitch/PhotonicSwitch.o out/clang-release//modules/QNIC/StationaryQubit/StationaryQubit.o out/clang-release//modules/QRSA/ConnectionManager/ConnectionManager.o out/clang-release//modules/QRSA/HardwareMonitor/HardwareMonitor.o out/clang-release//modules/QRSA/RealTimeController/RealTimeController.o out/clang-release//modules/QRSA/RoutingDaemon/RoutingDaemon.o out/clang-release//modules/QRSA/RuleEngine/BellPairStore.o out/clang-release//modules/QRSA/RuleEngine/RuleEngine.o out/clang-release//rules/Condition.o out/clang-release//rules/example.o out/clang-release//rules/Rule.o out/clang-release//rules/RuleSet.o out/clang-release//rules/actions/Action.o out/clang-release//rules/actions/DoublePurifyAction.o out/clang-release//rules/actions/DoubleSelectionAction.o out/clang-release//rules/actions/DoubleSelectionDualAction.o out/clang-release//rules/actions/DoubleSelectionDualActionSecond.o out/clang-release//rules/actions/GeneralizedSwappingAction.o out/clang-release//rules/actions/PurifyAction.o out/clang-release//rules/actions/RandomMeasureAction.o out/clang-release//rules/actions/SimultaneousSwappingAction.o out/clang-release//rules/actions/SwappingAction.o out/clang-release//rules/clauses/EnoughResourceClause.o out/clang-release//rules/clauses/FidelityClause.o out/clang-release//rules/clauses/MeasureCountClause.o out/clang-release//rules/clauses/PurificationCountClause.o out/clang-release//rules/clauses/WaitClause.o out/clang-release//test_utils/Gate.o out/clang-release//test_utils/QNode.o out/clang-release//test_utils/Simulation.o out/clang-release//test_utils/StaticEnv.o out/clang-release//test_utils/UtilFunctions.o out/clang-release//utils/ComponentProvider.o out/clang-release//utils/DefaultComponentProviderStrategy.o out/clang-release//PhotonicQubit_m.o out/clang-release//messages/base_messages_m.o out/clang-release//messages/connection_setup_messages_m.o out/clang-release//messages/entanglement_swapping_messages_m.o out/clang-release//messages/HoM_ipc_messages_m.o out/clang-release//messages/link_generation_messages_m.o out/clang-release//messages/purification_messages_m.o out/clang-release//messages/QNode_ipc_messages_m.o out/clang-release//messages/tomography_messages_m.o diff --git a/quisp/.tmplib16996 b/quisp/.tmplib16996 new file mode 100644 index 000000000..72af404a2 Binary files /dev/null and b/quisp/.tmplib16996 differ diff --git a/quisp/messages/connection_setup_messages.msg b/quisp/messages/connection_setup_messages.msg index d8d7d360c..5fec21f52 100644 --- a/quisp/messages/connection_setup_messages.msg +++ b/quisp/messages/connection_setup_messages.msg @@ -24,6 +24,8 @@ packet ConnectionSetupRequest extends Header int stack_of_QNodeIndexes[]; int stack_of_linkCosts[]; QNIC_pair_info stack_of_QNICs[]; + + int number_of_clients; } packet RejectConnectionSetupRequest extends Header @@ -41,4 +43,7 @@ packet ConnectionSetupResponse extends Header RuleSetField RuleSet; int application_type; int stack_of_QNodeIndexes[]; + + bool isMultipartite; + string label; } diff --git a/quisp/messages/entanglement_swapping_messages.msg b/quisp/messages/entanglement_swapping_messages.msg index f3134aeea..6cc387f62 100644 --- a/quisp/messages/entanglement_swapping_messages.msg +++ b/quisp/messages/entanglement_swapping_messages.msg @@ -76,3 +76,21 @@ packet SimultaneousSwappingResult extends Header{ int index_in_path; int path_length_exclude_IR; } + +packet GeneralizedSwappingResult extends Header{ + unsigned long RuleSet_id; + unsigned long Rule_id; + int action_index; + bool is_for_root; //maybe soon to be obsolete + + int measurement_result; + int number_of_corr; + int correction_type; + string label; + + //Used only for internal communication + int size_of_arrays; + int responder_dests[]; + int responder_number_of_corr[]; + int measurement_results[]; +} diff --git a/quisp/modules/Application/Application.cc b/quisp/modules/Application/Application.cc index 669193047..b13a82874 100644 --- a/quisp/modules/Application/Application.cc +++ b/quisp/modules/Application/Application.cc @@ -23,6 +23,7 @@ Application::Application() : provider(utils::ComponentProvider{this}) {} */ void Application::initialize() { // Since we only need this module in EndNode, delete it otherwise. + if (!gate("toRouter")->isConnected()) { deleteThisModule *msg = new deleteThisModule("DeleteThisModule"); scheduleAt(simTime(), msg); @@ -36,6 +37,7 @@ void Application::initialize() { WATCH_VECTOR(other_end_node_addresses); storeEndNodeAddresses(); + if (!is_e2e_connection) { return; } @@ -70,7 +72,30 @@ void Application::initialize() { scheduleAt(simTime() + 0.00001 * my_address, pk); return; } - + /* + Simple GHZ distribution setup, not logic to have number_of_clients sent by clients. + The Lone initiator should send a message to itself to define the number of clients, + clients should send a setup request with a bool (and not a int) specifying the connection + is multipartite. This is to ensure, QNIC are locked not in the setup phase but on the response phase. + */ + if (traffic_pattern == 3) { + int initiator_adress = par("LoneInitiatorAddress"); + int number_of_clients = par("NumberOfClients"); + if (my_address != initiator_adress) { + + EV_INFO << "My multipartite connection setup request will be sent from " << my_address << " to " << initiator_adress << "\n"; + EV_INFO << number_of_clients; + ConnectionSetupRequest *pk = createMultiConnectionSetupRequest(initiator_adress, number_of_resources, number_of_clients); + // delay to avoid conflict + scheduleAt(simTime() + 0.00001 * my_address, pk); + } else { + EV_INFO << "Initiator setup" << "\n"; + ConnectionSetupRequest *pk = createMultiConnectionSetupRequest(initiator_adress, number_of_resources, number_of_clients); + // delay to avoid conflict + scheduleAt(simTime() + 0.00001 * my_address, pk); + } + return; + } error("Invalid TrafficPattern specified."); } @@ -86,9 +111,22 @@ ConnectionSetupRequest *Application::createConnectionSetupRequest(int dest_addr, pk->setSrcAddr(my_address); pk->setNum_measure(num_measure); pk->setKind(7); + pk->setNumber_of_clients(1); //CM return pk; } +//CM +ConnectionSetupRequest *Application::createMultiConnectionSetupRequest(int dest_addr, int num_of_required_resources, int number_of_clients) { + ConnectionSetupRequest *pk = new ConnectionSetupRequest("ConnSetupRequest"); + pk->setActual_srcAddr(my_address); + pk->setActual_destAddr(dest_addr); + pk->setDestAddr(my_address); + pk->setSrcAddr(my_address); + pk->setNum_measure(num_measure); + pk->setKind(7); + pk->setNumber_of_clients(number_of_clients); // CM + return pk; +} /** * \brief Message handler * diff --git a/quisp/modules/Application/Application.h b/quisp/modules/Application/Application.h index 3c2e539cf..1fc33beb9 100644 --- a/quisp/modules/Application/Application.h +++ b/quisp/modules/Application/Application.h @@ -45,6 +45,7 @@ class Application : public IApplication { int getOneRandomEndNodeAddress(); messages::ConnectionSetupRequest *createConnectionSetupRequest(int dest_addr, int num_of_required_resources); + messages::ConnectionSetupRequest *createMultiConnectionSetupRequest(int dest_addr, int num_of_required_resources, int number_of_clients); utils::ComponentProvider provider; }; diff --git a/quisp/modules/Application/Application.ned b/quisp/modules/Application/Application.ned index 7cf2796ed..cecea4c4c 100644 --- a/quisp/modules/Application/Application.ned +++ b/quisp/modules/Application/Application.ned @@ -14,6 +14,8 @@ simple Application // int TrafficPattern = default(1); int TrafficPattern; int LoneInitiatorAddress; + int NumberOfResources = default(1); + int NumberOfClients; int distant_measure_count = default(7000); // Maybe don't have to set the default here. diff --git a/quisp/modules/Common/Router.cc b/quisp/modules/Common/Router.cc index 56d593854..ed78122b5 100644 --- a/quisp/modules/Common/Router.cc +++ b/quisp/modules/Common/Router.cc @@ -26,7 +26,7 @@ class Router : public cSimpleModule { protected: virtual void initialize(int stage) override; - virtual void handleMessage(cMessage *msg) override; + virtual void handleMessage(cMessage* msg) override; virtual int numInitStages() const override { return 1; }; }; @@ -37,13 +37,13 @@ void Router::initialize(int stage) { myAddress = getParentModule()->par("address"); // Topology creation for routing table - cTopology *topo = new cTopology("topo"); + cTopology* topo = new cTopology("topo"); topo->extractByParameter("includeInTopo", "\"yes\""); // Any node that has a parameter includeInTopo will be included in routing if (topo->getNumNodes() == 0 || topo == nullptr) { // If no node with the parameter & value found, do nothing. return; } - cTopology::Node *thisNode = topo->getNodeFor(getParentModule()); // The parent node with this specific router + cTopology::Node* thisNode = topo->getNodeFor(getParentModule()); // The parent node with this specific router int number_of_links_total = 0; @@ -80,7 +80,7 @@ void Router::initialize(int stage) { // Check the number of shortest paths towards the target node. This may be more than 1 if multiple paths have the same minimum cost. if (thisNode->getNumPaths() == 0) continue; // not connected - cGate *parentModuleGate = thisNode->getPath(0)->getLocalGate(); // Returns the next link/gate in the ith shortest paths towards the target node. + cGate* parentModuleGate = thisNode->getPath(0)->getLocalGate(); // Returns the next link/gate in the ith shortest paths towards the target node. int gateIndex = parentModuleGate->getIndex(); int address = topo->getNode(i)->getModule()->par("address"); rtable[address] = gateIndex; // Store gate index per destination from this node @@ -96,83 +96,87 @@ void Router::initialize(int stage) { delete topo; } -void Router::handleMessage(cMessage *msg) { +void Router::handleMessage(cMessage* msg) { // check the header of the received package - Header *pk = check_and_cast
(msg); + Header* pk = check_and_cast(msg); int destAddr = pk->getDestAddr(); // read destination from the packet int who_are_you = pk->getKind(); // read the type of packet // This might be better fixed + if (destAddr == myAddress && who_are_you == 1) { // If destination is this node: Path selection send(pk, "toApp"); // send to Application locally return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { // Timing for BSM + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { // Timing for BSM bubble("Timing Notifier from HoM (stand-alone or internal) received"); send(pk, "rePort$o"); // send to Application locally return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { // Timing for BSM + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { // Timing for BSM bubble("Timing Notifier from EPPS received"); send(pk, "rePort$o"); // send to Application locally return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Connection setup request received"); send(pk, "cmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Connection setup response received"); send(pk, "cmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Reject connection setup response received"); send(pk, "cmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Internal RuleSet Forwarding packet received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Internal RuleSet Forwarding Application packet received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Swapping Result packet received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Swapping Result packet received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Link tomography request received"); send(pk, "hmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Link tomography ack received"); send(pk, "hmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Link tomography rule set received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Link tomography result received"); send(pk, "hmPort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("Purification result received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("DoublePurification result received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("DS_DoublePurification result received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { bubble("DS_DoublePurificationSecond result received"); send(pk, "rePort$o"); return; - } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { + send(pk, "rePort$o"); + return; + } else if (destAddr == myAddress && dynamic_cast(msg) != nullptr) { send(pk, "rePort$o"); return; } diff --git a/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.cc b/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.cc index cff7f1084..2126dea7e 100644 --- a/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.cc +++ b/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.cc @@ -100,6 +100,8 @@ void BellStateAnalyzer::initialize() { error_rate = par("error_rate"); // duration = par("duration"); required_precision = par("required_precision"); + //CM Waiting for a better solution + //required_precision = 0.00001; left_arrived_at = -1; right_arrived_at = -1; left_last_photon_detected = false; @@ -348,8 +350,8 @@ void BellStateAnalyzer::forDEBUG_countErrorTypes(cMessage *msg) { count_I++; } count_total++; - EV << "Y%=" << (double)count_Y / (double)count_total << ", X%=" << (double)count_X / (double)count_total << ", Z%=" << (double)count_Z / (double)count_total - << ", L%=" << (double)count_L / (double)count_total << ", I% =" << (double)count_I / (double)count_total << "\n"; + //EV << "Y%=" << (double)count_Y / (double)count_total << ", X%=" << (double)count_X / (double)count_total << ", Z%=" << (double)count_Z / (double)count_total + // << ", L%=" << (double)count_L / (double)count_total << ", I% =" << (double)count_I / (double)count_total << "\n"; } bool BellStateAnalyzer::isPhotonLost(cMessage *msg) { diff --git a/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.ned b/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.ned index b4b394591..c51b8e82e 100644 --- a/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.ned +++ b/quisp/modules/PhysicalConnection/BSA/BellStateAnalyzer.ned @@ -7,7 +7,8 @@ simple BellStateAnalyzer double loss_rate = default(0); double error_rate = default(0); double duration = default(0); - double required_precision = default(1.5e-9); + // double required_precision = default(1.5e-9); CM + double required_precision = default(1.5e-5); int photon_detection_per_sec = default(10000); int address; @signal[Num_Bell_state](type=long); diff --git a/quisp/modules/QNIC/StationaryQubit/IQubit.h b/quisp/modules/QNIC/StationaryQubit/IQubit.h new file mode 100644 index 000000000..e69de29bb diff --git a/quisp/modules/QNIC/StationaryQubit/IStationaryQubit.h b/quisp/modules/QNIC/StationaryQubit/IStationaryQubit.h index 5b9c5d2eb..2fd655a08 100644 --- a/quisp/modules/QNIC/StationaryQubit/IStationaryQubit.h +++ b/quisp/modules/QNIC/StationaryQubit/IStationaryQubit.h @@ -6,16 +6,16 @@ namespace quisp { namespace types { enum class MeasureXResult : int { - NO_ERROR, - HAS_Z_ERROR, + NO_X_ERROR, + HAS_X_ERROR, }; enum class MeasureYResult : int { - NO_ERROR, + NO_Y_ERROR, HAS_XZ_ERROR, }; enum class MeasureZResult : int { - NO_ERROR, - HAS_X_ERROR, + NO_Z_ERROR, + HAS_Z_ERROR, }; } // namespace types @@ -169,6 +169,9 @@ class IStationaryQubit : public cSimpleModule { int qnic_address; int qnic_type; int qnic_index; + //CM + bool is_in_multipartite = false; + std::string label = ""; int action_index; bool no_density_matrix_nullptr_entangled_partner_ok; diff --git a/quisp/modules/QNIC/StationaryQubit/StationaryQubit.cc b/quisp/modules/QNIC/StationaryQubit/StationaryQubit.cc index f14fa9c67..1c29aaf7b 100644 --- a/quisp/modules/QNIC/StationaryQubit/StationaryQubit.cc +++ b/quisp/modules/QNIC/StationaryQubit/StationaryQubit.cc @@ -219,9 +219,9 @@ void StationaryQubit::setTwoQubitGateErrorCeilings(TwoQubitGateErrorModel &model MeasureXResult StationaryQubit::measure_X() { applySingleQubitGateError(Measurement_error); if (par("GOD_Zerror").boolValue()) { - return MeasureXResult::HAS_Z_ERROR; + return MeasureXResult::HAS_X_ERROR; } - return MeasureXResult::NO_ERROR; + return MeasureXResult::NO_X_ERROR; } MeasureYResult StationaryQubit::measure_Y() { @@ -236,15 +236,16 @@ MeasureYResult StationaryQubit::measure_Y() { if (error) { return MeasureYResult::HAS_XZ_ERROR; } - return MeasureYResult::NO_ERROR; + return MeasureYResult::NO_Y_ERROR; + return MeasureYResult::NO_Y_ERROR; } MeasureZResult StationaryQubit::measure_Z() { applySingleQubitGateError(Measurement_error); if (par("GOD_Xerror")) { - return MeasureZResult::HAS_X_ERROR; + return MeasureZResult::HAS_Z_ERROR; } - return MeasureZResult::NO_ERROR; + return MeasureZResult::NO_Z_ERROR; } // Convert X to Z, and Z to X error. Therefore, Y error stays as Y. @@ -539,7 +540,7 @@ bool StationaryQubit::Xpurify(IStationaryQubit *resource_qubit /*Controlled*/) { applyMemoryError(); check_and_cast(resource_qubit)->applyMemoryError(); /*Target qubit*/ this->CNOT_gate(resource_qubit /*controlled qubit*/); - bool meas = this->measure_Z() == MeasureZResult::NO_ERROR; + bool meas = this->measure_Z() == MeasureZResult::NO_Z_ERROR; return meas; } @@ -549,7 +550,7 @@ bool StationaryQubit::Zpurify(IStationaryQubit *resource_qubit /*Target*/) { check_and_cast(resource_qubit)->applyMemoryError(); /*Target qubit*/ resource_qubit->CNOT_gate(this /*controlled qubit*/); this->Hadamard_gate(); - bool meas = this->measure_Z() == MeasureZResult::NO_ERROR; + bool meas = this->measure_Z() == MeasureZResult::NO_Z_ERROR; return meas; } diff --git a/quisp/modules/QNode.ned b/quisp/modules/QNode.ned index 5698b3d8a..64a106ce6 100644 --- a/quisp/modules/QNode.ned +++ b/quisp/modules/QNode.ned @@ -33,6 +33,12 @@ module QNode submodules: app: Application { parameters: + //CM Begin + TrafficPattern = 3; + LoneInitiatorAddress = 10000; + NumberOfClients = 4; + + //CM End address = address;//share the same address within all inner modules @display("p=30,43"); } diff --git a/quisp/modules/QRSA/ConnectionManager/ConnectionManager.cc b/quisp/modules/QRSA/ConnectionManager/ConnectionManager.cc index f1b2ead77..0b99c0435 100644 --- a/quisp/modules/QRSA/ConnectionManager/ConnectionManager.cc +++ b/quisp/modules/QRSA/ConnectionManager/ConnectionManager.cc @@ -30,7 +30,6 @@ void ConnectionManager::initialize() { simultaneous_es_enabled = par("simultaneous_es_enabled"); es_with_purify = par("entanglement_swapping_with_purification"); num_remote_purification = par("num_remote_purification"); - if (simultaneous_es_enabled && es_with_purify) { error("Currently, simultaneous entanglement swapping cannot be simulated with purification"); } @@ -86,16 +85,23 @@ void ConnectionManager::handleMessage(cMessage *msg) { int initiator_addr = resp->getActual_destAddr(); int responder_addr = resp->getActual_srcAddr(); - if (initiator_addr == my_address || responder_addr == my_address) { - // this node is not a swapper - storeRuleSetForApplication(resp); + if (resp->getIsMultipartite() == false) + { + if (initiator_addr == my_address || responder_addr == my_address) { + // this node is not a swapper + storeRuleSetForApplication(resp); + } else { + // this node is a swapper (intermediate node) + // currently, destinations are separated. (Not accumulated.) + storeRuleSet(resp); + } + delete msg; + return; } else { - // this node is a swapper (intermediate node) - // currently, destinations are separated. (Not accumulated.) - storeRuleSet(resp); + storeRuleSetForApplication(resp); + //QNIC reservation ? } - delete msg; - return; + } if (dynamic_cast(msg) != nullptr) { @@ -217,6 +223,13 @@ void ConnectionManager::respondToRequest(ConnectionSetupRequest *req) { int actual_dst = req->getActual_destAddr(); int actual_src = req->getActual_srcAddr(); // initiator address (to get input qnic) + // CM BEGIN + // Should be check multipartite bool + if (req->getNumber_of_clients() != 1) { + handleMultipartiteRequest(req, actual_dst, actual_src); + return; + } + // CM END // This must be -1 int local_qnic_address_to_actual_dst = routing_daemon->return_QNIC_address_to_destAddr(actual_dst); if (local_qnic_address_to_actual_dst != -1) { @@ -557,6 +570,189 @@ QNIC_id ConnectionManager::getQnicInterface(int owner_address, int partner_addre return qnic_interface; } + +// CM To refactor +void ConnectionManager::handleMultipartiteRequest(ConnectionSetupRequest *req, int actual_dst, int actual_src) { + static int number_of_received_connection = 0; + static int number_of_incoming_connections = 0; + int current_node; + int path_size_without_end; + QNIC_pair_info current_qnic_info; + + if (actual_src == my_address) { + number_of_incoming_connections = req->getNumber_of_clients(); + return; + } + + int local_qnic_address_to_actual_dst = routing_daemon->return_QNIC_address_to_destAddr(actual_dst); + if (local_qnic_address_to_actual_dst != -1) { + error("something error happen!"); + } + + // TODO: premise only one connection allowed btw, two nodes. + int local_qnic_address_to_actual_src = routing_daemon->return_QNIC_address_to_destAddr(actual_src); + if (local_qnic_address_to_actual_src == -1) { + error("This shouldn't happen!"); + } + + auto dst_info = std::make_unique(NULL_CONNECTION_SETUP_INFO); + auto src_info = hardware_monitor->findConnectionInfoByQnicAddr(local_qnic_address_to_actual_src); + if (src_info == nullptr) { + error("src_info not found"); + } + QNIC_pair_info pair_info = {.fst = src_info->qnic, .snd = dst_info->qnic}; + + bool is_src_qnic_reserved = isQnicBusy(src_info->qnic.address); + bool is_dst_qnic_reserved = isQnicBusy(dst_info->qnic.address); + + // the number of steps + int hop_count = req->getStack_of_QNodeIndexesArraySize(); + + // path from source to destination + std::vector path; + for (int i = 0; i < hop_count; i++) + { + path.push_back(req->getStack_of_QNodeIndexes(i)); + } + path.push_back(my_address); + path_size_without_end = path.size() - 2; + + int qnic_array_size = req->getStack_of_QNICsArraySize(); + req->setStack_of_QNICsArraySize(qnic_array_size + 1); + req->setStack_of_QNICs(qnic_array_size, pair_info); + + std::vector qnics = {}; + for (int i = qnic_array_size - 1; i >= 0; i--) { + qnics.push_back(req->getStack_of_QNICs(i)); + } + + if (number_of_received_connection == 0) + { + tree_path_test.clear(); + } + + + while (path.size() > 1) + { + current_node = path.back(); + current_qnic_info = qnics.back(); + path.pop_back(); + qnics.pop_back(); + if (tree_path_test.find(current_node) == tree_path_test.end()) + { + PathLink new_path_link = { + path.back(), + current_qnic_info, + actual_src + }; + EV_INFO << "actual src: " << actual_src << "\n"; + std::vector child = {new_path_link}; + tree_path_test.insert(std::make_pair(current_node, child)); + } + else + { + bool is_in_child = false; + std::vector *current_childs = &tree_path_test.at(current_node); + for (auto it = current_childs->begin(); it != current_childs->end(); ++it) + { + if (it->children == path.back()) + { + is_in_child = true; + break; + } + } + if (is_in_child == false) + { + PathLink new_path_link = { + path.back(), + current_qnic_info, + actual_src + }; + current_childs->push_back(new_path_link); + } + } + } + current_node = path.back(); + correction_number_for_node.insert(std::make_pair(current_node, path_size_without_end)); + std::vector child = {}; + tree_path_test.insert(std::make_pair(current_node, child)); + + number_of_received_connection += 1; + if (number_of_received_connection == number_of_incoming_connections) + { + number_of_received_connection = 0; + int size_of_tree = 0; + for (auto it = tree_path_test.begin(); it != tree_path_test.end(); ++it) { + PathLink father = getFather(it->first); + if (!(father.children == -1 || it->second.size() == 0)) { + size_of_tree++; + } + } + EV_INFO << "Size of the Leafless tree " << size_of_tree << "\n"; + for (auto it = tree_path_test.begin(); it != tree_path_test.end(); ++it) { + auto *pkr = new ConnectionSetupResponse("ConnSetupResponse(GHZDistrib)"); + + RuleSet *rule = generateGeneralizedEntanglementSwappingRuleSet(it->first, it->second, size_of_tree); + if (rule != nullptr) + { + pkr->setRuleSet(rule); + pkr->setDestAddr(it->first); + pkr->setSrcAddr(my_address); + pkr->setKind(2); + pkr->setIsMultipartite(true); + pkr->setActual_srcAddr(path.at(0)); + pkr->setActual_destAddr(my_address); + pkr->setApplication_type(0); + send(pkr, "RouterPort$o"); + } + + } + if (actual_dst != my_address) { + reserveQnic(src_info->qnic.address); + reserveQnic(dst_info->qnic.address); + } else { + reserveQnic(src_info->qnic.address); + } + number_of_state_initiated++; + } + +} + + +//To refactor in one method +PathLink ConnectionManager::getFather(int node) { + for (auto it = tree_path_test.begin(); it != tree_path_test.end(); ++it) { + auto childs = it->second; + + for (auto path_link_it = childs.begin(); path_link_it != childs.end(); ++path_link_it) { + if (path_link_it->children == node) { + //EV_INFO << "Found father link with " << path_link_it->children << " and QNIC address " << path_link_it->QNIC_pair.fst.address << " and " + //<< path_link_it->QNIC_pair.snd.address + //<< "\n"; + return (*path_link_it); + } + } + } + //EV_INFO << "Did not found father address\n"; + PathLink default_path_link; + default_path_link.children = -1; + return (default_path_link); +} + +int ConnectionManager::getFatherAdress(int node) { + for (auto it = tree_path_test.begin(); it != tree_path_test.end(); ++it) { + auto childs = it->second; + + for (auto path_link_it = childs.begin(); path_link_it != childs.end(); ++path_link_it) { + if (path_link_it->children == node) { + //EV_INFO << "Found father address " << it->first << "\n"; + return (it->first); + } + } + } + return (-1); +} + /** * This function is for selecting the order of entanglement swapping * \param swapper_address node address; could be any intermediate in the path (not an end point) @@ -776,9 +972,11 @@ void ConnectionManager::tryRelayRequestToNextHop(ConnectionSetupRequest *req) { QNIC_pair_info pair_info = {.fst = inbound_info->qnic, .snd = outbound_info->qnic}; req->setStack_of_QNICs(num_accumulated_pair_info, pair_info); - reserveQnic(inbound_info->qnic.address); - reserveQnic(outbound_info->qnic.address); - + // CM For now we do not lock QNIC at all in multipartite, should lock them in the response phase + if (req->getNumber_of_clients() == 1) { + reserveQnic(inbound_info->qnic.address); + reserveQnic(outbound_info->qnic.address); + } send(req, "RouterPort$o"); } @@ -938,31 +1136,104 @@ std::unique_ptr ConnectionManager::swappingRule(SwappingConfig conf, unsig return rule_entanglement_swapping; } -std::unique_ptr ConnectionManager::simultaneousSwappingRule(SwappingConfig conf, std::vector path, unsigned long ruleset_id, unsigned long rule_id) { - // From @poramet implementations - std::vector partners = {conf.left_partner, conf.right_partner}; - std::string rule_name = "Simultaneous Entanglement Swapping with " + std::to_string(conf.left_partner) + " : " + std::to_string(conf.right_partner); - int index_in_path = conf.index; - int path_length_exclude_IR = path.size() - 2; - auto rule_simultaneous_entanglement_swapping = std::make_unique(ruleset_id, rule_id, rule_name, partners); +//CM +RuleSet *ConnectionManager::generateGeneralizedEntanglementSwappingRuleSet(int node, std::vector children_link, int size_of_tree) { + unsigned long ruleset_id = createUniqueId(); + int rule_index = 0; + PathLink father = getFather(node); + int father_address = getFatherAdress(node); + std::string label = "GHZ_" + std::to_string(my_address) + "_" + std::to_string(number_of_state_initiated); + std::vector clauses; + std::vector config_partners; + std::vector config_associated_end_nodes; + std::vector config_types; + std::vector config_ids; + std::vector config_addresses; + std::vector config_self_ids; + std::vector config_self_types; + std::vector config_resource; Condition *condition = new Condition(); - Clause *resource_clause_left = new EnoughResourceClause(conf.left_partner, 1); - Clause *resource_clause_right = new EnoughResourceClause(conf.right_partner, 1); - condition->addClause(resource_clause_left); - condition->addClause(resource_clause_right); - - quisp::rules::Action *action = new SimultaneousSwappingAction( - ruleset_id, rule_id, conf.left_partner, conf.lqnic_type, conf.lqnic_index, conf.lqnic_address, conf.lres, conf.right_partner, conf.rqnic_type, conf.rqnic_index, - conf.rqnic_address, conf.rres, conf.self_left_qnic_index, conf.self_left_qnic_type, conf.self_right_qnic_index, conf.self_right_qnic_type, conf.initiator, - conf.initiator_qnic_type, conf.initiator_qnic_index, conf.initiator_qnic_address, conf.initiator_res, conf.responder, conf.responder_qnic_type, conf.responder_qnic_index, - conf.responder_qnic_address, conf.responder_res, index_in_path, path_length_exclude_IR); - rule_simultaneous_entanglement_swapping->setCondition(condition); - rule_simultaneous_entanglement_swapping->setAction(action); - return rule_simultaneous_entanglement_swapping; + if (father.children == -1 || children_link.size() == 0) { + return (nullptr); + } + else { + EV_INFO << "Label we put in ruleset " << label << "\n"; + for (auto link_it = children_link.begin(); link_it != children_link.end(); ++link_it) { + config_resource.push_back(1); + Clause *resource_clause = new EnoughResourceClause(link_it->children, config_resource.back()); + condition->addClause(resource_clause); + QNIC_id children_qnic = link_it->QNIC_pair.snd; + config_partners.push_back(link_it->children); + config_associated_end_nodes.push_back(link_it->end_node); + config_types.push_back(children_qnic.type); + config_ids.push_back(children_qnic.index); + config_addresses.push_back(children_qnic.address); + + QNIC_id self_qnic = link_it->QNIC_pair.fst; + config_self_ids.push_back(self_qnic.index); + config_self_types.push_back(self_qnic.type); + } + Clause *resource_clause = new EnoughResourceClause(father_address, config_resource.back()); + condition->addClause(resource_clause); + QNIC_id father_qnic = father.QNIC_pair.fst; + config_partners.push_back(father_address); + config_associated_end_nodes.push_back(my_address); + config_types.push_back(father_qnic.type); + // config_ids.push_back(father_qnic.index); It is curiously -1 + config_ids.push_back(0); + config_addresses.push_back(father_qnic.address); + + QNIC_id self_qnic = father.QNIC_pair.snd; + config_self_ids.push_back(self_qnic.index); + config_self_types.push_back(self_qnic.type); + + config_resource.push_back(1); + rules::Action *action = new rules::actions::GeneralizedSwappingAction(ruleset_id, rule_index, config_partners, config_associated_end_nodes, config_types, config_ids, + config_addresses, config_resource, config_self_ids, config_self_types, label, size_of_tree, correction_number_for_node); + auto rule = std::make_unique(ruleset_id, rule_index, "generalized entanglement swapping", config_partners); + rule->setCondition(condition); + rule->setAction(action); + + RuleSet *ruleset = new RuleSet(ruleset_id, node, config_partners); + ruleset->addRule(std::move(rule)); + + return ruleset; + } } + // RuleSet *ConnectionManager::generateSimultaneousEntanglementSwappingRuleSet(int owner, SwappingConfig conf, std::vector path) { + // unsigned long ruleset_id = createUniqueId(); + // int rule_index = 0; + + std::unique_ptr ConnectionManager::simultaneousSwappingRule(SwappingConfig conf, std::vector path, unsigned long ruleset_id, unsigned long rule_id) { + // From @poramet implementations + std::vector partners = {conf.left_partner, conf.right_partner}; + std::string rule_name = "Simultaneous Entanglement Swapping with " + std::to_string(conf.left_partner) + " : " + std::to_string(conf.right_partner); + + int index_in_path = conf.index; + int path_length_exclude_IR = path.size() - 2; + + auto rule_simultaneous_entanglement_swapping = std::make_unique(ruleset_id, rule_id, rule_name, partners); + Condition *condition = new Condition(); + Clause *resource_clause_left = new EnoughResourceClause(conf.left_partner, 1); + Clause *resource_clause_right = new EnoughResourceClause(conf.right_partner, 1); + condition->addClause(resource_clause_left); + condition->addClause(resource_clause_right); + + quisp::rules::Action *action = new SimultaneousSwappingAction( + ruleset_id, rule_id, conf.left_partner, conf.lqnic_type, conf.lqnic_index, conf.lqnic_address, conf.lres, conf.right_partner, conf.rqnic_type, conf.rqnic_index, + conf.rqnic_address, conf.rres, conf.self_left_qnic_index, conf.self_left_qnic_type, conf.self_right_qnic_index, conf.self_right_qnic_type, conf.initiator, + conf.initiator_qnic_type, conf.initiator_qnic_index, conf.initiator_qnic_address, conf.initiator_res, conf.responder, conf.responder_qnic_type, conf.responder_qnic_index, + conf.responder_qnic_address, conf.responder_res, index_in_path, path_length_exclude_IR); + + rule_simultaneous_entanglement_swapping->setCondition(condition); + rule_simultaneous_entanglement_swapping->setAction(action); + return (rule_simultaneous_entanglement_swapping); + } + + std::unique_ptr ConnectionManager::waitRule(int partner_address, int next_parter_address, unsigned long ruleset_id, unsigned long rule_id) { // This is used for waiting swapping result from partner std::vector partners = {partner_address}; diff --git a/quisp/modules/QRSA/ConnectionManager/ConnectionManager.h b/quisp/modules/QRSA/ConnectionManager/ConnectionManager.h index cf3cc3f4c..991c59b72 100644 --- a/quisp/modules/QRSA/ConnectionManager/ConnectionManager.h +++ b/quisp/modules/QRSA/ConnectionManager/ConnectionManager.h @@ -8,6 +8,7 @@ #ifndef MODULES_CONNECTIONMANAGER_H_ #define MODULES_CONNECTIONMANAGER_H_ +#include #include "IConnectionManager.h" using namespace omnetpp; @@ -17,6 +18,13 @@ using namespace quisp::rules; namespace quisp { namespace modules { + + typedef struct { + int children; + QNIC_pair_info QNIC_pair; + int end_node; + } PathLink; //CM + /** \class ConnectionManager ConnectionManager.cc * * \brief ConnectionManager @@ -50,11 +58,17 @@ class ConnectionManager : public IConnectionManager { int num_of_qnics; std::map> connection_setup_buffer; // key is qnic address std::map connection_retry_count; // key is qnic address + + std::map> tree_path_test; // CM: Taking both into a struct after + std::map> tree_path; + std::map correction_number_for_node; + std::map qnic_res_table; std::vector request_send_timing; // self message, notification for sending out request bool simultaneous_es_enabled; bool es_with_purify; int num_remote_purification; + int number_of_state_initiated = 0; // To label created states IRoutingDaemon *routing_daemon; IHardwareMonitor *hardware_monitor; @@ -69,7 +83,8 @@ class ConnectionManager : public IConnectionManager { void initiateApplicationRequest(int qnic_address); void scheduleRequestRetry(int qnic_address); void popApplicationRequest(int qnic_address); - + void handleMultipartiteRequest(ConnectionSetupRequest *req, int actual_dst, int actual_src); //CM + void relayRequestToNextHop(ConnectionSetupRequest *pk); void storeRuleSetForApplication(ConnectionSetupResponse *pk); void storeRuleSet(ConnectionSetupResponse *pk); @@ -100,8 +115,11 @@ class ConnectionManager : public IConnectionManager { unsigned long createUniqueId(); static int computePathDivisionSize(int l); static int fillPathDivision(std::vector path, int i, int l, int *link_left, int *link_right, int *swapper, int fill_start); -}; + PathLink getFather(int node); // CM + int getFatherAdress(int node); + RuleSet *generateGeneralizedEntanglementSwappingRuleSet(int node, std::vector children_link, int size_tree); // CM +}; } // namespace modules } // namespace quisp #endif /* MODULES_CONNECTIONMANAGER_H_ */ diff --git a/quisp/modules/QRSA/HardwareMonitor/HardwareMonitor.ned b/quisp/modules/QRSA/HardwareMonitor/HardwareMonitor.ned index 00495f41d..3857c802f 100644 --- a/quisp/modules/QRSA/HardwareMonitor/HardwareMonitor.ned +++ b/quisp/modules/QRSA/HardwareMonitor/HardwareMonitor.ned @@ -9,16 +9,16 @@ simple HardwareMonitor int number_of_qnics_rp; string ntable = ""; // XYZ --rdv defaults removed so that users will be asked; 200402 - // bool link_tomography = default(false); - // int initial_purification = default(0); - // int Purification_type = default(-1); - bool link_tomography; + bool link_tomography = default(false); + int initial_purification = default(0); + int Purification_type = default(-1); + // bool link_tomography; int num_measure = default(3000); string tomography_output_filename = default("default"); string file_dir_name = default("results/"); // purification control - int initial_purification; - int Purification_type; + //int initial_purification; + //int Purification_type; // these two are obsolete controls for purification bool X_purification = default(false); bool Z_purification = default(false); @@ -26,4 +26,4 @@ simple HardwareMonitor inout RuleEnginePort; inout RouterPort; -} \ No newline at end of file +} diff --git a/quisp/modules/QRSA/RuleEngine/RuleEngine.cc b/quisp/modules/QRSA/RuleEngine/RuleEngine.cc index c19596662..03e1f03d2 100644 --- a/quisp/modules/QRSA/RuleEngine/RuleEngine.cc +++ b/quisp/modules/QRSA/RuleEngine/RuleEngine.cc @@ -56,6 +56,8 @@ void RuleEngine::initialize() { tracker_accessible.push_back(true); } + generalized_results.clear(); // CM + // running_processes = new RuleSetPtr[QNIC_N];//One process per QNIC for now. No multiplexing. // WATCH(assigned); } @@ -97,6 +99,7 @@ void RuleEngine::handleMessage(cMessage *msg) { } else if (dynamic_cast(msg) != nullptr) { + EV_INFO << "Received combined\n"; // First, keep all the qubits that were successfully entangled, and reinitialize the failed ones. CombinedBSAresults *pk_result = check_and_cast(msg); BSMtimingNotifier *pk = check_and_cast(msg); @@ -164,7 +167,8 @@ void RuleEngine::handleMessage(cMessage *msg) { EV_DEBUG << "This BSA request is internal\n"; scheduleFirstPhotonEmission(pk, QNIC_R); } - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { bubble("EPPS"); error("EPPS is not implemented yet"); } @@ -186,7 +190,8 @@ void RuleEngine::handleMessage(cMessage *msg) { } else { error("Empty rule set..."); } - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { PurificationResult *pkt = check_and_cast(msg); process_id purification_id; purification_result pr; @@ -196,7 +201,8 @@ void RuleEngine::handleMessage(cMessage *msg) { pr.id = purification_id; pr.outcome = pkt->getOutput_is_plus(); storeCheck_Purification_Agreement(pr); - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { DoublePurificationResult *pkt = check_and_cast(msg); process_id purification_id; Doublepurification_result pr; @@ -207,7 +213,8 @@ void RuleEngine::handleMessage(cMessage *msg) { pr.Xpurification_outcome = pkt->getXOutput_is_plus(); pr.Zpurification_outcome = pkt->getZOutput_is_plus(); storeCheck_DoublePurification_Agreement(pr); - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { // std::cout<<"!!!!Purification result reveid!!! node["<(msg); // std::cout<<"Presult from node["<getSrcAddr()<<"]\n"; @@ -225,7 +232,8 @@ void RuleEngine::handleMessage(cMessage *msg) { // std::cout<<"Purification result is from node["<getSrcAddr()<<"] rid="<< pkt->getRuleset_id()<<"Must be qnic["<getEntangled_with()<<"in node["<node_address<<"] \n"; storeCheck_QuatroPurification_Agreement(pr); - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { // std::cout<<"!!!!Purification result reveid!!! node["<(msg); process_id purification_id; @@ -238,13 +246,13 @@ void RuleEngine::handleMessage(cMessage *msg) { pr.Zpurification_outcome = pkt->getZOutput_is_plus(); pr.DS_purification_outcome = pkt->getDS_Output_is_plus(); storeCheck_TriplePurification_Agreement(pr); - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { SwappingResult *pkt = check_and_cast(msg); process_id swapping_id; swapping_id.ruleset_id = pkt->getRuleSet_id(); // just in case swapping_id.rule_id = pkt->getRule_id(); swapping_id.index = pkt->getAction_index(); - swapping_result swapr; // result of entanglement swapping swapr.id = swapping_id; swapr.new_partner = pkt->getNew_partner(); @@ -287,6 +295,11 @@ void RuleEngine::handleMessage(cMessage *msg) { updateResources_SimultaneousEntanglementSwapping(swapr); } } + else if (dynamic_cast(msg) != nullptr) { + correction_GeneralizedEntanglementSwapping(check_and_cast(msg)); + return; + } + else if (dynamic_cast(msg) != nullptr) { InternalRuleSetForwarding *pkt = check_and_cast(msg); @@ -305,7 +318,8 @@ void RuleEngine::handleMessage(cMessage *msg) { } else { error("Empty rule set..."); } - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { InternalRuleSetForwarding_Application *pkt = check_and_cast(msg); // doing end to end tomography if (pkt->getApplication_type() == 0) { @@ -325,7 +339,8 @@ void RuleEngine::handleMessage(cMessage *msg) { } else { error("This application is not recognized yet"); } - } else if (dynamic_cast(msg) != nullptr) { + } + else if (dynamic_cast(msg) != nullptr) { StopEmitting *pkt = check_and_cast(msg); terminated_qnic[pkt->getQnic_address()] = true; } @@ -972,13 +987,16 @@ void RuleEngine::updateResources_EntanglementSwapping(swapping_result swapr) { error("RuleEngine. Entanglement swapping went wrong"); } // FOR DEBUGGING - if (qubit->entangled_partner != nullptr) { - if (qubit->entangled_partner->entangled_partner == nullptr) { - error("1. Entanglement tracking is not doing its job. in update resource E.S."); - } - if (qubit->entangled_partner->entangled_partner != qubit) { - error("2. Entanglement tracking is not doing its job. in update resource E.S."); - } + if (qubit->label == "") { + if (qubit->entangled_partner != nullptr) { + if (qubit->entangled_partner->entangled_partner == nullptr) { + error("1. Entanglement tracking is not doing its job. in update resource E.S."); + } + if (qubit->entangled_partner->entangled_partner != qubit) { + error("2. Entanglement tracking is not doing its job. in update resource E.S."); + } + } + } bool promoted = false; @@ -1009,7 +1027,7 @@ void RuleEngine::updateResources_EntanglementSwapping(swapping_result swapr) { } } else if ((*rule)->rule_index == next_rule_id) { // next rule id is properly updated - (*rule)->addResource(new_partner, qubit); + (*rule)->addResource(new_partner, qubit);its promoted = true; return; } @@ -1037,17 +1055,21 @@ void RuleEngine::updateResources_SimultaneousEntanglementSwapping(swapping_resul if (operation_type == 0) { // nothing - } else if (operation_type == 1) { + } + else if (operation_type == 1) { // do Z qubit->Z_gate(); - } else if (operation_type == 2) { + } + else if (operation_type == 2) { // do X qubit->Z_gate(); - } else if (operation_type == 3) { + } + else if (operation_type == 3) { // do XZ qubit->Z_gate(); qubit->X_gate(); - } else { + } + else { error("something error happened! This operation type doesn't recorded!"); } @@ -1066,18 +1088,65 @@ void RuleEngine::updateResources_SimultaneousEntanglementSwapping(swapping_resul error("qubit is locked"); } bell_pair_store.insertEntangledQubit(new_partner, qubit); - if (qubit->entangled_partner != nullptr) { - if (qubit->entangled_partner->entangled_partner == nullptr) { - error("1. Entanglement tracking is not doing its job. in update resource E.S."); - } - if (qubit->entangled_partner->entangled_partner != qubit) { - error("2. Entanglement tracking is not doing its job. in update resource E.S."); + if (qubit->label == "") { + if (qubit->entangled_partner != nullptr) { + if (qubit->entangled_partner->entangled_partner == nullptr) { + error("1. Entanglement tracking is not doing its job. in update resource E.S."); + } + if (qubit->entangled_partner->entangled_partner != qubit) { + error("2. Entanglement tracking is not doing its job. in update resource E.S."); + } } } + ResourceAllocation(qnic_type, qnic_index); traverseThroughAllProcesses2(); // New resource added to QNIC with qnic_type qnic_index. } +//CM Quick and dirty +void RuleEngine::correction_GeneralizedEntanglementSwapping(GeneralizedSwappingResult *pkt) { + std::string label = pkt->getLabel(); + int correction = pkt->getCorrection_type(); + + EV_INFO << "Received correction with label " << label << " and correction " << correction; + + if (pkt->getIs_for_root()) { + EV_INFO << "Z\n"; + } else { + EV_INFO << "X\n"; + } + + + if (generalized_results.find(label) == generalized_results.end()) { + generalized_results.insert(std::make_pair(label, correction)); + } + else { + generalized_results.at(label) = generalized_results.at(label) ^ correction; + } + received_correction += 1; + if (received_correction == pkt->getNumber_of_corr()) { + EV_INFO << "Received Enough correction lezzugo\n"; + auto info = hardware_monitor->findConnectionInfoByQnicAddr(0); + int qnic_index = info->qnic.index; + QNIC_type qnic_type = info->qnic.type; + + for (int i = 0; i < 10; i++) { + StationaryQubit *qubit = provider.getStationaryQubit(0, i, qnic_type); + if (qubit->label == label && generalized_results.at(label) > 0) { + if (pkt->getIs_for_root()) { + EV_INFO << "ZGATE\n"; + qubit->Z_gate(); + } else { + EV_INFO << "XGATE\n"; + qubit->X_gate(); + } + } + received_correction = 0; + } + } + +} + // Only for MIM and MM void RuleEngine::freeFailedQubits_and_AddAsResource(int destAddr, int internal_qnic_address, int internal_qnic_index, CombinedBSAresults *pk_result) { // get the size of failed bsa @@ -1098,7 +1167,6 @@ void RuleEngine::freeFailedQubits_and_AddAsResource(int destAddr, int internal_q qnic_type = QNIC_R; neighborQNodeAddress = getInterface_toNeighbor_Internal(qnic_address).neighborQNode_address; } - // How many photons are bursted? int num_emitted_in_this_burstTrial = tracker[qnic_address].size(); // start iteration from 0 .. number of failed bsm @@ -1120,23 +1188,27 @@ void RuleEngine::freeFailedQubits_and_AddAsResource(int destAddr, int internal_q StationaryQubit *qubit = provider.getStationaryQubit(qnic_index, it->second.qubit_index, qnic_type); // if the partner is null, not correct - if (qubit->entangled_partner != nullptr) { - if (qubit->entangled_partner->entangled_partner == nullptr) { - // my instance is null (no way) - error("1. Entanglement tracking is not doing its job."); - } - if (qubit->entangled_partner->entangled_partner != qubit) { - // partner's qubit doesn't point this qubit -> wrong - error("2. Entanglement tracking is not doing its job."); + if (qubit->label == "") { + if (qubit->entangled_partner != nullptr) { + if (qubit->entangled_partner->entangled_partner == nullptr) { + // my instance is null (no way) + error("1. Entanglement tracking is not doing its job."); + } + if (qubit->entangled_partner->entangled_partner != qubit) { + // partner's qubit doesn't point this qubit -> wrong + error("2. Entanglement tracking is not doing its job."); + } } } + if (qubit->entangled_partner == nullptr && qubit->Density_Matrix_Collapsed(0, 0).real() == -111 && !qubit->no_density_matrix_nullptr_entangled_partner_ok) { EV << "entangle partner null?" << qubit->entangled_partner << " == nullptr?\n"; EV << "density matrix collapsed?" << qubit->Density_Matrix_Collapsed(0, 0).real() << "==-111?\n"; EV << "here should be true" << qubit->no_density_matrix_nullptr_entangled_partner_ok << "\n"; error("RuleEngine. Ebit succeed. but wrong"); } + EV_INFO << "C'est ajouté avec " << neighborQNodeAddress << "\n"; // Add qubit as available resource between NeighborQNodeAddress. bell_pair_store.insertEntangledQubit(neighborQNodeAddress, qubit); } @@ -1226,7 +1298,6 @@ void RuleEngine::ResourceAllocation(int qnic_type, int qnic_index) { void RuleEngine::traverseThroughAllProcesses2() { int number_of_process = rp.size(); // Number of running processes (in all QNICs). - if (number_of_process == 0) { return; } @@ -1238,12 +1309,10 @@ void RuleEngine::traverseThroughAllProcesses2() { for (auto rule = process->cbegin(), end = process->cend(); rule != end; rule++) { bool process_done = false; bool terminate_this_rule = false; - while (true) { if (!((*rule)->resources.size() > 0)) { break; // No more resource left for now. } - cPacket *pk = (*rule)->checkrun(this); // Do something on qubits entangled with resource_entangled_with_address. if (pk != nullptr) { @@ -1259,35 +1328,40 @@ void RuleEngine::traverseThroughAllProcesses2() { } send(pk, "RouterPort$o"); send(pk_for_self, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { PurificationResult *pkt = check_and_cast(pk); pkt->setSrcAddr(parentAddress); PurificationResult *pk_for_self = pkt->dup(); pk_for_self->setDestAddr(parentAddress); send(pkt, "RouterPort$o"); send(pk_for_self, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { DoublePurificationResult *pkt = check_and_cast(pk); pkt->setSrcAddr(parentAddress); DoublePurificationResult *pk_for_self = pkt->dup(); pk_for_self->setDestAddr(parentAddress); send(pkt, "RouterPort$o"); send(pk_for_self, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { DS_DoublePurificationResult *pkt = check_and_cast(pk); pkt->setSrcAddr(parentAddress); DS_DoublePurificationResult *pk_for_self = pkt->dup(); pk_for_self->setDestAddr(parentAddress); send(pkt, "RouterPort$o"); send(pk_for_self, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { DS_DoublePurificationSecondResult *pkt = check_and_cast(pk); pkt->setSrcAddr(parentAddress); DS_DoublePurificationSecondResult *pk_for_self = pkt->dup(); pk_for_self->setDestAddr(parentAddress); send(pkt, "RouterPort$o"); send(pk_for_self, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { SwappingResult *pkt = check_and_cast(pk); EV << "done swapping at " << parentAddress << " left: " << pkt->getLeft_Dest() << " right: " << pkt->getRight_Dest() << "\n"; // here this packet goes to two destination. @@ -1324,7 +1398,8 @@ void RuleEngine::traverseThroughAllProcesses2() { send(pkt_for_left, "RouterPort$o"); send(pkt_for_right, "RouterPort$o"); - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { SimultaneousSwappingResult *pkt = check_and_cast(pk); EV << "done swapping at " << parentAddress << "\n"; @@ -1355,12 +1430,33 @@ void RuleEngine::traverseThroughAllProcesses2() { send(pkt_for_initiator, "RouterPort$o"); send(pkt_for_responder, "RouterPort$o"); } + else if (dynamic_cast(pk) != nullptr) { + GeneralizedSwappingResult *result_packet = check_and_cast(pk); + + for (int i = 0; i < result_packet->getSize_of_arrays(); i++) { + std::string tmp = std::to_string(result_packet->getResponder_dests(i)); + char const *address = tmp.c_str(); + GeneralizedSwappingResult *packet_to_send = new GeneralizedSwappingResult(address); + packet_to_send->setDestAddr(result_packet->getResponder_dests(i)); + packet_to_send->setSrcAddr(parentAddress); + if (i < result_packet->getSize_of_arrays() - 1) { + packet_to_send->setIs_for_root(false); + }else { + packet_to_send->setIs_for_root(true); + } + packet_to_send->setNumber_of_corr(result_packet->getResponder_number_of_corr(i)); + packet_to_send->setLabel(result_packet->getLabel()); + packet_to_send->setMeasurement_result(result_packet->getMeasurement_results(i)); + send(packet_to_send, "RouterPort$o"); + } + } else if (dynamic_cast(pk) != nullptr) { Error *err = check_and_cast(pk); error(err->getError_text()); delete pk; - } else if (dynamic_cast(pk) != nullptr) { + } + else if (dynamic_cast(pk) != nullptr) { // Condition does not meet. Go to next rule. e.g. Fidelity is good enough by doing purification. Next could be swap. delete pk; break; @@ -1375,6 +1471,7 @@ void RuleEngine::traverseThroughAllProcesses2() { // std::cout<<"Is it done?"; process_done = (*rule)->checkTerminate(); // The entire process is done. e.g. enough measurement for tomography. if (process_done) { // Delete rule set if done + EV_INFO << "FINI !"; // std::cout<<"!!!!!!!!!!!!!!!!!!!!! TERMINATING!!!!!!!!!!!!!!!!!!!!!!!!!"; std::cout << "RuleSet_id=" << process->ruleset_id << "\n"; // todo:Also need to deallocate resources!!!!!!!!!!!!not implemented yet. diff --git a/quisp/modules/QRSA/RuleEngine/RuleEngine.h b/quisp/modules/QRSA/RuleEngine/RuleEngine.h index f53cd4352..62911d1be 100644 --- a/quisp/modules/QRSA/RuleEngine/RuleEngine.h +++ b/quisp/modules/QRSA/RuleEngine/RuleEngine.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "../../PhysicalConnection/BSA/HoMController.h" @@ -69,6 +70,10 @@ class RuleEngine : public IRuleEngine { running_processes rp; // Vector for store package for simultaneous entanglement swapping std::map> simultaneous_es_results; + // Vector to store the resuts of generalized entanglement swapping + std::map generalized_results; + int received_correction = 0; + // tracker accessible table has as many number of boolean value as the number of qnics in the qnode. // when the tracker for the qnic is clered by previous BSM trial it goes true // when the RuleEngine try to start new Photon emittion, it goes false and other BSM trial can't access to it. @@ -118,6 +123,8 @@ class RuleEngine : public IRuleEngine { void clearAppliedRule(IStationaryQubit *qubit); void updateResources_EntanglementSwapping(swapping_result swapr); + //CM + void correction_GeneralizedEntanglementSwapping(GeneralizedSwappingResult *pkt); utils::ComponentProvider provider; virtual void updateResources_SimultaneousEntanglementSwapping(swapping_result swapr); }; diff --git a/quisp/modules/QRSA/RuleEngine/RuleEngine_test.cc b/quisp/modules/QRSA/RuleEngine/RuleEngine_test.cc index 6b8bc5d57..db7cd6607 100644 --- a/quisp/modules/QRSA/RuleEngine/RuleEngine_test.cc +++ b/quisp/modules/QRSA/RuleEngine/RuleEngine_test.cc @@ -151,6 +151,7 @@ TEST(RuleEngineTest, ESResourceUpdate) { rule_engine->rp[0].Rs->getRule(0)->addResource(1, mockQubit1); ASSERT_EQ(rule_engine->rp[0].Rs->getRule(0)->resources.size(), 1); ASSERT_EQ(rule_engine->rp[0].Rs->getRule(1)->resources.size(), 0); + EV_INFO << "On NE DEVRAIT PAS ETRE LA\n"; rule_engine->updateResources_EntanglementSwapping(swapr); // 1. remove from previous rule ASSERT_EQ(rule_engine->rp[0].Rs->getRule(0)->resources.size(), 0); diff --git a/quisp/networks/quisp_tutorial.ini b/quisp/networks/quisp_tutorial.ini index 1fc072695..2b227897c 100644 --- a/quisp/networks/quisp_tutorial.ini +++ b/quisp/networks/quisp_tutorial.ini @@ -23,7 +23,8 @@ network = Linear_One_MIM [Config Three_HoM_star] # from topology_star_network.ned -network = Three_HoM_star +network = BitMoreComplicated + output-vector-file = "./omtest.vec" [Config Realistic_Layer2_Simple_MIM_MM_all_in_one] @@ -35,4 +36,4 @@ network= Realistic_Layer2_Star_Sep [Config Tutorial_Big_Q_Network] #from topology_complex_network.ned -network = ispMap_1239_node_23_48 \ No newline at end of file +network = ispMap_1239_node_23_48 diff --git a/quisp/networks/three_HoM_star.ini b/quisp/networks/three_HoM_star.ini index b1f2b4be5..31326c459 100644 --- a/quisp/networks/three_HoM_star.ini +++ b/quisp/networks/three_HoM_star.ini @@ -1,8 +1,9 @@ [General] # from topology_star_network.ned -network = Three_HoM_star +network = BitMoreComplicated # for testing of MUXing **.EndToEndConnection = true **.link_tomography = false -#**.initial_purification = 1 -#**.Purification_type = 1001 +**.initial_purification = 1 +**.Purification_type = 1001 + diff --git a/quisp/networks/topology_star_network.ned b/quisp/networks/topology_star_network.ned index 4997a5279..11b7b36dc 100644 --- a/quisp/networks/topology_star_network.ned +++ b/quisp/networks/topology_star_network.ned @@ -23,6 +23,7 @@ network Three_HoM_star double cost = default(1); double distance @unit(km) = default(20km); //delay = uniform(0.01ms, 1s); + double Speed_of_light_in_fiber @unit(km) = default(208189.206944km); double distance_of_light_in_fiber_per_sec @unit(km) = default(205336.986301km); delay = this.distance / distance_of_light_in_fiber_per_sec * 1s; datarate = uniform(1kbps, 100kbps); @@ -33,6 +34,7 @@ network Three_HoM_star double cost = default(1); double distance @unit(km) = default(20km); //delay = uniform(0.01ms, 1s); + double Speed_of_light_in_fiber @unit(km) = default(208189.206944km); double distance_of_light_in_fiber_per_sec @unit(km) = default(205336.986301km); delay = this.distance / distance_of_light_in_fiber_per_sec * 1s; datarate = uniform(1kbps, 100kbps); @@ -49,7 +51,7 @@ network Three_HoM_star //} EndNode[3]: QNode { //Initializerでaddress = node idにすればconflict無くなるかも。 - address = index+100000; + address = index+10000; nodeType = "EndNode"; @display("i=device/pc"); } @@ -64,23 +66,133 @@ network Three_HoM_star @display("i=device/server"); } connections: - EndNode[0].port++ <--> C { distance = 5km; } <--> HoM[0].port++; - HoM[0].port++ <--> C <--> Router[0].port++; - EndNode[0].quantum_port++ <--> QuantumChannel { distance = 5km; } <--> HoM[0].quantum_port++; - HoM[0].quantum_port++ <--> QuantumChannel <--> Router[0].quantum_port++; - - EndNode[1].port++ <--> C <--> HoM[1].port++; - HoM[1].port++ <--> C { distance = 100km; } <--> Router[0].port++; - EndNode[1].quantum_port++ <--> QuantumChannel <--> HoM[1].quantum_port++; - HoM[1].quantum_port++ <--> QuantumChannel { distance = 100km; } <--> Router[0].quantum_port++; - - EndNode[2].port++ <--> C <--> HoM[2].port++; - HoM[2].port++ <--> C { distance = 40km; } <--> Router[0].port++; - EndNode[2].quantum_port++ <--> QuantumChannel <--> HoM[2].quantum_port++; - HoM[2].quantum_port++ <--> QuantumChannel { distance = 40km; } <--> Router[0].quantum_port++; + EndNode[0].port++ <--> C { distance = 20km; } <--> HoM[0].port++; + HoM[0].port++ <--> C { distance = 20km; } <--> Router[0].port++; + EndNode[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[0].quantum_port++; + HoM[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[0].quantum_port++; + + EndNode[1].port++ <--> C { distance = 20km; } <--> HoM[1].port++; + HoM[1].port++ <--> C { distance = 20km; } <--> Router[0].port++; + EndNode[1].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[1].quantum_port++; + HoM[1].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[0].quantum_port++; + + EndNode[2].port++ <--> C { distance = 20km; }<--> HoM[2].port++; + HoM[2].port++ <--> C{ distance = 20km; } <--> Router[0].port++; + EndNode[2].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[2].quantum_port++; + HoM[2].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[0].quantum_port++; + +} + +network BitMoreComplicated +{ + parameters: + **.Speed_of_light_in_fiber = 208189.206944 km; + //**.distance_of_light_in_fiber_per_sec = 205336.986301 km; // calculated as 299792/1.46 + int message_id_BSAtimingNoftifier = 4; + int message_id_qubit = 100; + int message_id_PathSelection = 1; + int increment_address = 0; + + @display("bgl=2"); + types: + channel C extends DatarateChannel + { + double cost = default(1); + double distance @unit(km) = default(20km); + //delay = uniform(0.01ms, 1s); + double Speed_of_light_in_fiber @unit(km) = default(208189.206944km); + double distance_of_light_in_fiber_per_sec @unit(km) = default(205336.986301km); + delay = this.distance / distance_of_light_in_fiber_per_sec * 1s; + datarate = uniform(1kbps, 100kbps); + int test = default(0); + } + channel QuantumChannel extends DatarateChannel + { + double cost = default(1); + double distance @unit(km) = default(20km); + //delay = uniform(0.01ms, 1s); + double Speed_of_light_in_fiber @unit(km) = default(208189.206944km); + double distance_of_light_in_fiber_per_sec @unit(km) = default(205336.986301km); + delay = this.distance / distance_of_light_in_fiber_per_sec * 1s; + datarate = uniform(1kbps, 100kbps); + double photon_loss_rate = default(0);//per km + double channel_error_rate = default(0);//per km + double Z_error_ratio = default(1); + double X_error_ratio = default(1); + double Y_error_ratio = default(1); + int test = default(0); + } + submodules: + //configurator: IPv4NetworkConfigurator { + // @display("p=100,100"); + //} + EndNode[5]: QNode { + //Initializerでaddress = node idにすればconflict無くなるかも。 + address = index+10000; + nodeType = "EndNode"; + @display("i=device/pc"); + } + HoM[9]: HoM { + address = index+1000; + //@display("p=326,57"); + @display("i=device/bsm"); + } + Router[5]: QNode { + address = index; + //@display("p=246,56"); + @display("i=device/server"); + } + connections: + EndNode[0].port++ <--> C { distance = 20km; } <--> HoM[0].port++; + HoM[0].port++ <--> C { distance = 20km; } <--> Router[0].port++; + EndNode[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[0].quantum_port++; + HoM[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[0].quantum_port++; + + Router[0].port++ <--> C { distance = 20km; } <--> HoM[1].port++; + HoM[1].port++ <--> C { distance = 20km; } <--> Router[1].port++; + Router[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[1].quantum_port++; + HoM[1].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[1].quantum_port++; + + Router[1].port++ <--> C { distance = 20km; } <--> HoM[2].port++; + HoM[2].port++ <--> C { distance = 20km; } <--> Router[3].port++; + Router[1].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[2].quantum_port++; + HoM[2].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[3].quantum_port++; + + Router[1].port++ <--> C { distance = 20km; } <--> HoM[3].port++; + HoM[3].port++ <--> C { distance = 20km; } <--> Router[2].port++; + Router[1].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[3].quantum_port++; + HoM[3].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[2].quantum_port++; + + Router[2].port++ <--> C { distance = 20km; } <--> HoM[4].port++; + HoM[4].port++ <--> C { distance = 20km; } <--> EndNode[2].port++; + Router[2].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[4].quantum_port++; + HoM[4].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> EndNode[2].quantum_port++; + + Router[2].port++ <--> C { distance = 20km; } <--> HoM[5].port++; + HoM[5].port++ <--> C { distance = 20km; } <--> EndNode[3].port++; + Router[2].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[5].quantum_port++; + HoM[5].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> EndNode[3].quantum_port++; + + Router[3].port++ <--> C { distance = 20km; } <--> HoM[6].port++; + HoM[6].port++ <--> C { distance = 20km; } <--> EndNode[1].port++; + Router[3].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[6].quantum_port++; + HoM[6].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> EndNode[1].quantum_port++; + + EndNode[0].port++ <--> C { distance = 20km; } <--> HoM[7].port++; + HoM[7].port++ <--> C { distance = 20km; } <--> Router[4].port++; + EndNode[0].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[7].quantum_port++; + HoM[7].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> Router[4].quantum_port++; + + Router[4].port++ <--> C { distance = 20km; } <--> HoM[8].port++; + HoM[8].port++ <--> C { distance = 20km; } <--> EndNode[4].port++; + Router[4].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> HoM[8].quantum_port++; + HoM[8].quantum_port++ <--> QuantumChannel { distance = 20km; } <--> EndNode[4].quantum_port++; + } + + network Star_MSM { parameters: diff --git a/quisp/rules/Action.h b/quisp/rules/Action.h index d7acff5c2..ec34ee194 100644 --- a/quisp/rules/Action.h +++ b/quisp/rules/Action.h @@ -9,6 +9,7 @@ #include "actions/RandomMeasureAction.h" #include "actions/SimultaneousSwappingAction.h" #include "actions/SwappingAction.h" +#include "actions/GeneralizedSwappingAction.h" //CM namespace quisp { namespace rules { diff --git a/quisp/rules/Clause.cc.old b/quisp/rules/Clause.cc.old new file mode 100644 index 000000000..aa299bed9 --- /dev/null +++ b/quisp/rules/Clause.cc.old @@ -0,0 +1,181 @@ +/** \file Clause.cc + * + * \authors cldurand,,takaakimatsuo + * \date 2018/07/03 + * + * \brief Clause + */ +#include "Clause.h" +#include "tools.h" + +namespace quisp { +namespace rules { + +/* +bool FidelityClause::check(qnicResources* resources) const { + stationaryQubit* qubit = NULL; + checkQnic();//This is not doing anything... + if(qubit = getQubit(resources, qnic_type, qnic_id, partner, resource)){ + return (qubit->getFidelity() >= threshold); + } + return false; +}*/ + +bool FidelityClause::check(std::multimap resource) const { + StationaryQubit* qubit = nullptr; + /*checkQnic();//This is not doing anything... + if(qubit = getQubit(resources, qnic_type, qnic_id, partner, resource)){ + return (qubit->getFidelity() >= threshold); + } + return false;*/ +} + +bool EnoughResourceClause::check(std::multimap resource) const { + // std::cout<<"!!In enough clause \n"; + bool enough = false; + int num_free = 0; + + for (std::multimap::iterator it = resource.begin(); it != resource.end(); ++it) { + if (it->first == partner) { + if (!it->second->isLocked()) { // here must have loop + num_free++; + } + if (num_free >= num_resource_required) { + enough = true; + } + } + } + // std::cout<<"Enough = "< resource) const { + // std::cout<<"!!In enough clause \n"; + bool enough = false; + int num_free = 0; + + for (std::multimap::iterator it = resource.begin(); it != resource.end(); ++it) { + if (it->first == partner_left) { + if (!it->second->isLocked()) { // here must have loop + num_free++; + } + if (num_free >= num_resource_required_left) { + enough = true; + } + } + } + if (enough) { + EV << "You have enough resource between " << partner_left << "\n"; + } else { + EV << "You don't have enough resource between " << partner_left << "\n"; + } + // std::cout<<"Enough = "< resource) const { + // std::cout<<"!!In enough clause \n"; + bool enough = false; + int num_free = 0; + + for (std::multimap::iterator it = resource.begin(); it != resource.end(); ++it) { + if (it->first == partner_right) { + if (!it->second->isLocked()) { // here must have loop + num_free++; + } + if (num_free >= num_resource_required_right) { + enough = true; + } + } + } + if (enough) { + EV << "You have enough resource between " << partner_right << "\n"; + } else { + EV << "You don't have enough resource between " << partner_right << "\n"; + } + // std::cout<<"Enough = "< resources) const { + // std::cout<<"MeasureCountClause invoked!!!! \n"; + if (current_count < max_count) { + current_count++; // Increment measured counter. + // std::cout<<"Measurement count is now "< resources) const { + EV << "Tomography termination clause invoked.\n"; + bool done = false; + if (current_count >= max_count) { + // EV<<"TRUE: Current count = "<= "<=max_count){ + EV<<"TRUE: Current count = "<= "< resource) const { + StationaryQubit* qubit = nullptr; + // checkQnic();//This is not doing anything... + + /* + qubit = getQubitPurified(resources, qnic_type, qnic_id, partner, num_purify_must); + if(qubit != nullptr){ + return true;//There is a qubit that has been purified "num_purify_must" times. + }else{ + return false; + }*/ +} + +/* +bool PurificationCountClause::checkTerminate(qnicResources* resources) const { + return false; +}*/ + +// Clause *EXAMPLE_CLAUSE = new FidelityClause(0,0,.6); + +} // namespace rules +} // namespace quisp diff --git a/quisp/rules/Condition.cc b/quisp/rules/Condition.cc index df87f43ac..0e3594522 100644 --- a/quisp/rules/Condition.cc +++ b/quisp/rules/Condition.cc @@ -16,6 +16,7 @@ void Condition::addClause(Clause *c) { clauses.push_back(c); } bool Condition::check(std::multimap resources) const { bool satisfying = true; for (auto &clause : clauses) { + if (!clause->check(resources)) { satisfying = false; break; diff --git a/quisp/rules/Condition.h b/quisp/rules/Condition.h index 2634b00af..078cc138a 100644 --- a/quisp/rules/Condition.h +++ b/quisp/rules/Condition.h @@ -13,7 +13,6 @@ namespace quisp { namespace rules { - /** \class Condition Condition.h * * \brief Condition @@ -24,10 +23,12 @@ class Condition { bool check(std::multimap resources) const; bool checkTerminate(std::multimap resources) const; + //CM Would need a type correction + void addCorrection(int measure); + std::vector clauses; }; } // namespace rules } // namespace quisp - #endif // QUISP_RULES_CONDITION_H_ diff --git a/quisp/rules/Rule.cc b/quisp/rules/Rule.cc index fc5426488..1b1af7499 100644 --- a/quisp/rules/Rule.cc +++ b/quisp/rules/Rule.cc @@ -31,6 +31,23 @@ void Rule::setAction(Action *a) { cPacket *Rule::checkrun(cModule *re) { cPacket *pk = nullptr; + /*EV_INFO << "--------------------------- EXAMEN DE RESSOURCES ------------------------------\n"; + //CM Debug + for (auto it = resources.begin(); it != resources.end() ; ++it) { + EV_INFO << " Node address " << it->second->node_address << " QNIC Adress " << it->second->qnic_address << " QNIC index " << it->second->qnic_index << " Qnic Type " + << it->second->qnic_type << "\n"; + EV_INFO << " Is multipartite " << it->second->is_in_multipartite << "\n"; + if (it->second->entangled_partner == nullptr) { + EV_INFO << "No entangled partner\n"; + } else { + EV_INFO << "Entangled partner Node address " << it->second->entangled_partner->node_address + << " QNIC Adress " << it->second->entangled_partner->qnic_address << " QNIC index " << it->second->entangled_partner->qnic_index << " Qnic Type " + << it->second->entangled_partner->qnic_type << "\n"; + EV_INFO << " Is multipartite " << it->second->entangled_partner->is_in_multipartite << "\n"; + } + } + EV_INFO << "--------------------------- FIN ------------------------------\n";*/ + if (condition->check(resources)) { // std::cout<<"Condition met!.\n"; // std::cout<<"before: check num = "<checkNumResource()<<"\n"; diff --git a/quisp/rules/Rule.h b/quisp/rules/Rule.h index 4a7294ce4..66c467e7d 100644 --- a/quisp/rules/Rule.h +++ b/quisp/rules/Rule.h @@ -15,7 +15,6 @@ namespace quisp { namespace rules { - /** \class Rule Rule.h * * \brief Rule @@ -30,6 +29,7 @@ class Rule { std::unique_ptr condition; std::unique_ptr action; std::multimap resources; + std::vector corrections_received; std::vector action_partners; std::vector next_action_partners; // if this rule extends the entanglement int mutable number_of_resources_allocated_in_total = 0; diff --git a/quisp/rules/actions/GeneralizedSwappingAction.cc b/quisp/rules/actions/GeneralizedSwappingAction.cc new file mode 100644 index 000000000..2ef2d97e4 --- /dev/null +++ b/quisp/rules/actions/GeneralizedSwappingAction.cc @@ -0,0 +1,157 @@ +#include +#include +#include "GeneralizedSwappingAction.h" + +using quisp::types::MeasureZResult; + +namespace quisp { +namespace rules { +namespace actions { + +GeneralizedSwappingAction::GeneralizedSwappingAction(unsigned long RuleSet_id, int rule_index, + std::vector partners, + std::vector associated_end_nodes, + std::vector types, + std::vector ids, std::vector addresses, + std::vector resources, std::vector self_ids, + std::vector self_types, std::string label, int size_tree, + std::map correction_number) { + this->ruleset_id = RuleSet_id; + this->rule_id = rule_index; + this->associated_end_nodes = associated_end_nodes; + this->partners = partners; + this->qnic_types = types; + this->qnic_ids = ids; + this->qnic_addresses = addresses; + this->resources = resources; + this->self_qnic_ids = self_ids; + this->self_qnic_types = self_types; + this->label = label; + this->size_tree_leafless = size_tree; + this->correction_number_for_node = correction_number; +} + +// TODO: completely mixed +cPacket *GeneralizedSwappingAction::run(cModule *re) { + float success_probability = 1.0; + std::vector indexes; + std::map qubits_pair; + std::vector qubits; + + + for (int i = 0; i < partners.size(); i++) { + + EV_INFO << "choppons la ressource " << resources.at(i) << " avec le partenaire " << partners.at(i) << "\n"; + + IStationaryQubit *qubit = getResource(resources.at(i), partners.at(i)); + + + if (qubit == nullptr) { + Error *package = new Error; + package->setError_text("Not enough resource found for GeneralizedEntanglementSwapping! This shouldn't happen!"); + return (package); + } + IStationaryQubit *entangled_qubit = qubit->entangled_partner; + //EV_INFO << "Le entangled partner " << entangled_qubit->node_address << "\n"; + qubits_pair.insert(std::make_pair(qubit, entangled_qubit)); + qubits.push_back(qubit); + if (qnic_ids.at(i) < 0) { + Error *package = new Error; + package->setError_text("QNICs are not found!"); + return (package); + } + } + + IStationaryQubit *father_qubit = qubits.back(); + + GeneralizedSwappingResult *packet = new GeneralizedSwappingResult; + + packet->setRuleSet_id(ruleset_id); + packet->setRule_id(rule_id); + packet->setAction_index(action_index); + packet->setSize_of_arrays(partners.size()); + packet->setMeasurement_resultsArraySize(partners.size()); + packet->setResponder_destsArraySize(partners.size()); + packet->setResponder_number_of_corrArraySize(partners.size()); + + for (int i = 0; i < partners.size() - 1; i++) { + qubits[i]->CNOT_gate(father_qubit); + qubits[i]->entangled_partner->label = label; + EV_INFO << "QBIT " << qubits[i]->entangled_partner->stationaryQubit_address << " at adress " << qubits[i]->node_address << "with label " << qubits[i]->entangled_partner->label + << "\n"; + packet->setMeasurement_results(i, (int)qubits[i]->measure_Z()); + EV_INFO << "Correction (Z) " << packet->getMeasurement_results(i) << "\n"; + packet->setResponder_dests(i, associated_end_nodes[i]); + packet->setResponder_number_of_corr(i, correction_number_for_node.at(associated_end_nodes[i])); + } + + qubits[partners.size() - 1]->entangled_partner->label = label; + EV_INFO << "QBIT " << qubits[partners.size() - 1]->entangled_partner->stationaryQubit_address << " at adress " << qubits[partners.size() - 1]->node_address << "with label " + << qubits[partners.size() - 1]->entangled_partner->label << "\n"; + EV_INFO << "Correction (X) " << packet->getMeasurement_results(partners.size() - 1) << "\n"; + packet->setMeasurement_results(partners.size() - 1, (int)father_qubit->measure_X()); + packet->setResponder_dests(partners.size() - 1, associated_end_nodes.back()); + packet->setResponder_number_of_corr(partners.size() - 1, size_tree_leafless); + packet->setLabel(label.c_str()); + + IRuleEngine *rule_engine = check_and_cast(re); + for (auto it = qubits_pair.begin(); it != qubits_pair.end(); ++it) { + //it->second->setEntangledPartnerInfo(father_qubit->entangled_partner); + removeResource_fromRule(it->first); + } + // CM: For now we impose a success + /*if ((std::rand() / RAND_MAX) < success_probability) + { + for (auto it = qubits_pair.begin(); it != qubits_pair.end(); ++it) + { + it->second->setEntangledPartnerInfo(it->first); + removeResource_fromRule(it->first); + } + } + else + { + for (auto it = qubits_pair.begin(); it != qubits_pair.end(); ++it) { + removeResource_fromRule(it->second); + removeResource_fromRule(it->first); + } + }*/ + + for (int i = 0; i < partners.size(); i++) + { + rule_engine->freeConsumedResource(self_qnic_ids.at(i), qubits.at(i), self_qnic_types.at(i)); + indexes.push_back(qubits_pair.at(qubits.at(i))->stationaryQubit_address); + } + + return (packet); + // result packet + // + /*SwappingResult *pk = new SwappingResult; + // no destination here. In RuleEngine, it's set. + // this setKind() doesn't seem to have any effect; set instead in void RuleEngine::traverseThroughAllProcesses2() + pk->setKind(5); + pk->setRuleSet_id(ruleset_id); + pk->setRule_id(rule_id); + pk->setAction_index(action_index); + pk->setOperation_type_left(operation_type_left); // operation type for left node + pk->setOperation_type_right(operation_type_right); // operation type for right node + // These information are cropped in the RuleEngine. + pk->setLeft_Dest(left_partner); // this might not require but just in case + pk->setRight_Dest(right_partner); + + pk->setNew_partner_left(right_partner); + pk->setNew_partner_qnic_index_left(right_qnic_id); + pk->setNew_partner_qnic_type_left(right_qnic_type); + pk->setNew_partner_qnic_address_left(right_qnic_address); + pk->setMeasured_qubit_index_left(lindex); // here is wrong; + + pk->setNew_partner_right(left_partner); + pk->setNew_partner_qnic_index_right(left_qnic_id); + pk->setNew_partner_qnic_type_right(left_qnic_type); + pk->setNew_partner_qnic_address_right(left_qnic_address); + pk->setMeasured_qubit_index_right(rindex);*/ + //return pk; +} + +} // namespace actions +} // namespace rules +} // namespace quisp diff --git a/quisp/rules/actions/GeneralizedSwappingAction.h b/quisp/rules/actions/GeneralizedSwappingAction.h new file mode 100644 index 000000000..6d77a1649 --- /dev/null +++ b/quisp/rules/actions/GeneralizedSwappingAction.h @@ -0,0 +1,40 @@ +#pragma once + +#include "BaseAction.h" +#include + +namespace quisp { +namespace rules { +namespace actions { + +class GeneralizedSwappingAction : public Action { + protected: + // First partner + std::vector partners; + std::vector associated_end_nodes; + std::vector qnic_types; + std::vector qnic_ids; + std::vector qnic_addresses; + std::vector resources; + std::map correction_number_for_node; + std::string label = ""; + int size_tree_leafless; + int action_index = 0; + + std::vector self_qnic_ids; + std::vector self_qnic_types; + + public: + // constructor of entanglement swapping + GeneralizedSwappingAction(unsigned long RuleSet_id, int rule_index, std::vector partners, std::vector associated_end_nodes, + std::vector types, std::vector ids, std::vector addresses, + std::vector resources, std::vector self_ids, std::vector self_types, + std::string label, int size_tree, std::map correction_number); + // cPacket* run(qnicResources *resources) override; + // cPacket* run(cModule *re, qnicResources *resources) override; + cPacket* run(cModule* re) override; +}; + +} // namespace actions +} // namespace rules +} // namespace quisp diff --git a/quisp/rules/actions/SimultaneousSwappingAction.cc b/quisp/rules/actions/SimultaneousSwappingAction.cc index fb1b24034..a9cb30106 100644 --- a/quisp/rules/actions/SimultaneousSwappingAction.cc +++ b/quisp/rules/actions/SimultaneousSwappingAction.cc @@ -76,15 +76,15 @@ cPacket *SimultaneousSwappingAction::run(cModule *re) { int operation_type_left, operation_type_right; - if (left_measure == MeasureZResult::NO_ERROR && right_measure == MeasureZResult::NO_ERROR) { // 0 0 + if (left_measure == MeasureZResult::NO_Z_ERROR && right_measure == MeasureZResult::NO_Z_ERROR) { // 0 0 EV << "operation type 0, operation left I, operation right I\n"; operation_type_left = 0; operation_type_right = 0; - } else if (left_measure == MeasureZResult::NO_ERROR && right_measure == MeasureZResult::HAS_X_ERROR) { // 0 1 + } else if (left_measure == MeasureZResult::NO_Z_ERROR && right_measure == MeasureZResult::HAS_Z_ERROR) { // 0 1 EV << "operation type 1, operation left I, operation right X\n"; operation_type_left = 0; operation_type_right = 1; - } else if (left_measure == MeasureZResult::HAS_X_ERROR && right_measure == MeasureZResult::NO_ERROR) { // 1 0 + } else if (left_measure == MeasureZResult::HAS_Z_ERROR && right_measure == MeasureZResult::NO_Z_ERROR) { // 1 0 EV << "operation type 2, operation left Z, operation right I\n"; operation_type_left = 0; operation_type_right = 2; diff --git a/quisp/rules/actions/SwappingAction.cc b/quisp/rules/actions/SwappingAction.cc index 02411245d..e5ffd15e2 100644 --- a/quisp/rules/actions/SwappingAction.cc +++ b/quisp/rules/actions/SwappingAction.cc @@ -82,15 +82,15 @@ cPacket *SwappingAction::run(cModule *re) { // RuleEngine::updateResources_EntanglementSwapping handles the operation type. int operation_type_left, operation_type_right; // operation_type: 0 = I, 1 = X, 2 = Z - if (left_measure == MeasureZResult::NO_ERROR && right_measure == MeasureZResult::NO_ERROR) { + if (left_measure == MeasureZResult::NO_Z_ERROR && right_measure == MeasureZResult::NO_Z_ERROR) { EV << "operation type 0, operation left I, operation right I\n"; operation_type_left = 0; operation_type_right = 0; - } else if (left_measure == MeasureZResult::NO_ERROR && right_measure == MeasureZResult::HAS_X_ERROR) { + } else if (left_measure == MeasureZResult::NO_Z_ERROR && right_measure == MeasureZResult::HAS_Z_ERROR) { EV << "operation type 1, operation left I, operation right X\n"; operation_type_left = 0; operation_type_right = 1; - } else if (left_measure == MeasureZResult::HAS_X_ERROR && right_measure == MeasureZResult::NO_ERROR) { + } else if (left_measure == MeasureZResult::HAS_Z_ERROR && right_measure == MeasureZResult::NO_Z_ERROR) { EV << "operation type 2, operation left Z, operation right I\n"; operation_type_left = 2; operation_type_right = 0; diff --git a/quisp/rules/actions/SwappingAction_test.cc b/quisp/rules/actions/SwappingAction_test.cc index 6d5e88d8a..9962d8948 100644 --- a/quisp/rules/actions/SwappingAction_test.cc +++ b/quisp/rules/actions/SwappingAction_test.cc @@ -205,7 +205,7 @@ TEST(SwappingActionTest, runWithRightHasError) { right_qubit->entangled_partner = left_qubit; left_qubit->entangled_partner = right_qubit; - EXPECT_CALL(*right_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_X_ERROR)); + EXPECT_CALL(*right_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_Z_ERROR)); EXPECT_CALL(*left_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::NO_ERROR)); EXPECT_CALL(*action, getResource(21, 22)).WillOnce(Return(right_qubit)); @@ -245,7 +245,7 @@ TEST(SwappingActionTest, runWithLeftHasError) { left_qubit->entangled_partner = right_qubit; EXPECT_CALL(*right_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::NO_ERROR)); - EXPECT_CALL(*left_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_X_ERROR)); + EXPECT_CALL(*left_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_Z_ERROR)); EXPECT_CALL(*action, getResource(21, 22)).WillOnce(Return(right_qubit)); EXPECT_CALL(*action, getResource(23, 24)).WillOnce(Return(left_qubit)); @@ -283,8 +283,8 @@ TEST(SwappingActionTest, runWithBothErrors) { right_qubit->entangled_partner = left_qubit; left_qubit->entangled_partner = right_qubit; - EXPECT_CALL(*right_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_X_ERROR)); - EXPECT_CALL(*left_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_X_ERROR)); + EXPECT_CALL(*right_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_Z_ERROR)); + EXPECT_CALL(*left_qubit, measure_Z()).WillOnce(Return(quisp::types::MeasureZResult::HAS_Z_ERROR)); EXPECT_CALL(*action, getResource(21, 22)).WillOnce(Return(right_qubit)); EXPECT_CALL(*action, getResource(23, 24)).WillOnce(Return(left_qubit)); diff --git a/quisp/rules/clauses/EnoughResourceClause.cc b/quisp/rules/clauses/EnoughResourceClause.cc index ea855af47..bffcf532c 100644 --- a/quisp/rules/clauses/EnoughResourceClause.cc +++ b/quisp/rules/clauses/EnoughResourceClause.cc @@ -7,7 +7,6 @@ namespace clauses { bool EnoughResourceClause::check(std::multimap resource) { bool enough = false; int num_free = 0; - for (auto it = resource.begin(); it != resource.end(); ++it) { if (it->first == partner) { if (!it->second->isLocked()) { // here must have loop @@ -20,6 +19,11 @@ bool EnoughResourceClause::check(std::multimap resource) } return enough; } + +//CM: why is there is no checkTerminate for this clause ? +bool EnoughResourceClause::checkTerminate(std::multimap resource) const { + // There is lot of things to change + return (true); } } // namespace clauses } // namespace rules } // namespace quisp diff --git a/quisp/rules/clauses/EnoughResourceClause.h b/quisp/rules/clauses/EnoughResourceClause.h index 7c0ade401..fcc25182d 100644 --- a/quisp/rules/clauses/EnoughResourceClause.h +++ b/quisp/rules/clauses/EnoughResourceClause.h @@ -18,7 +18,7 @@ class EnoughResourceClause : public Clause { partner = partner_addr; }; bool check(std::multimap) override; - bool checkTerminate(std::multimap) const override { return false; }; + bool checkTerminate(std::multimap) const override; }; } // namespace clauses diff --git a/quisp/rules/tools.h b/quisp/rules/tools.h new file mode 100644 index 000000000..14f801b34 --- /dev/null +++ b/quisp/rules/tools.h @@ -0,0 +1,122 @@ +/** \file tools.h + * + * \authors cldurand,takaakimatsuo + * \date 2018/09/04 + * + * \brief tools + */ +#ifndef QUISP_RULES_TOOLS_H_ +#define QUISP_RULES_TOOLS_H_ +//#include + +#include +//#include + +namespace quisp { +namespace rules { + +/*For RuleSets*/ +// typedef std::map resources;//index -> qubit. List of available resource for a particular stage/Rule in this RuleSet. +// typedef std::map AvailableResourceForEachStage;//Rule index -> resources. List of all resources for all stages/Rules in this RuleSet. +// AvailableResourceForEachStage rc; + +/* +static stationaryQubit* getPurifiedQubit_fromTop(qnicResources* resources, QNIC_type qtype, int qid, int partner, int num_purified) { + std::pair ret = resources[qtype][qid].equal_range(partner);//Find all resource in qytpe/qid entangled with partner. + int real_res_id = 0; + for (EntangledPairs::iterator it=ret.first; it!=ret.second; ++it,++real_res_id) { + //std::cout << real_res_id << '\n'; + if (!it->second->isLocked() && it->second->numpurified == num_purified){ + stationaryQubit *pt = it->second; + return pt; + } + } + return NULL; +}*/ + +static StationaryQubit* getUnLockedQubit_fromTop(qnicResources* resources, QNIC_type qtype, int qid, int partner, int res_id) { + std::pair ret = resources[qtype][qid].equal_range(partner); // Find all resource in qytpe/qid entangled with partner. + int real_res_id = 0; + for (EntangledPairs::iterator it = ret.first; it != ret.second; ++it) { + // std::cout << real_res_id << '\n'; + if (!it->second->isLocked()) { + if (real_res_id == res_id) { + StationaryQubit* pt = it->second; + return pt; + } else { + real_res_id++; + } + } + } + return nullptr; +} + +/** \func static stationaryQubit* getQubit(qnicResources* resources, QNIC_type qtype, int qid, int partner, int res_id)*/ + +static StationaryQubit* getQubit(qnicResources* resources, QNIC_type qtype, int qid, int partner, int res_id) { + // assume that qnic type is ok + std::pair ret = resources[qtype][qid].equal_range(partner); // Find all resource in qytpe/qid entangled with partner. + // stationaryQubit *use_this_qubit; + + int real_res_id = 0; + for (EntangledPairs::iterator it = ret.first; it != ret.second; ++it, ++real_res_id) { + // std::cout << real_res_id << '\n'; + if (real_res_id == res_id) { + StationaryQubit* pt = it->second; + // RuleEngine re; + // re.freeResource(qid, it->second->par("stationaryQubit_address"), qtype); + // re.JustATest(); + return pt; + + // use_this_qubit = it->second; + // resources[qtype][qid].erase(it); + // break;//Returns the top qubit in that list, if res_id = 0 + } + } + // resources[qtype][qid].insert(std::make_pair(-1000/*QNode IP address*/,NULL)); + return nullptr; +} + +static StationaryQubit* getQubitPurified(qnicResources* resources, QNIC_type qtype, int qid, int partner, int num_purified_must) { + std::pair ret = resources[qtype][qid].equal_range(partner); // Find all resource in qytpe/qid entangled with partner. + for (EntangledPairs::iterator it = ret.first; it != ret.second; ++it) { + if (it->second->num_purified == num_purified_must && !it->second->isLocked()) { + StationaryQubit* pt = it->second; + return pt; + } + } + return nullptr; +} + +static StationaryQubit* getQubit(cModule* re, qnicResources* resources, QNIC_type qtype, int qid, int partner, int res_id) { + // assume that qnic type is ok + std::pair ret = resources[qtype][qid].equal_range(partner); // Find all resource in qytpe/qid entangled with partner. + // stationaryQubit *use_this_qubit; + + int real_res_id = 0; + for (EntangledPairs::iterator it = ret.first; it != ret.second; ++it, ++real_res_id) { + // std::cout << real_res_id << '\n'; + if (real_res_id == res_id) { + StationaryQubit* pt = it->second; + // rule_engine->JustATest(); + return pt; + + // use_this_qubit = it->second; + // resources[qtype][qid].erase(it); + // break;//Returns the top qubit in that list, if res_id = 0 + } + } + // resources[qtype][qid].insert(std::make_pair(-1000/*QNode IP address*/,NULL)); + + return nullptr; +} + +/* +static void freeConsumedQubit(resources,qnic_type,qnic_id,partner,resource){ + +}*/ + +} // namespace rules +} // namespace quisp + +#endif // QUISP_RULES_TOOLS_H_