Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
VerticalContractor.h
Go to the documentation of this file.
1
15
16#pragma once
17
18#ifndef __VERTICAL_CONTRACTOR_H_
19#define __VERTICAL_CONTRACTOR_H_ 1
20
21#include "BaseContractor.h"
22
23#include <boost/container_hash/hash.hpp>
24
25namespace TensorNetworks {
26
33public:
40 double Contract(const TensorNetwork &network, Types::qubit_t qubit) override {
41 std::vector<Eigen::Index> keys;
42 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
43
44 TensorsMap tensors =
45 InitializeTensors(network, qubit, keys, keysKeys, false);
46
47 const auto &qubitGroup = network.GetQubitGroup(qubit);
48 const std::set<Types::qubit_t> qubitGroupSet(qubitGroup.begin(),
49 qubitGroup.end());
50
51 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
52 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
53
54 auto qit = qubitGroupSet.begin();
55
56 // while there is more than one tensor...
57 while (tensors.size() > 1) {
58 if (qit == qubitGroupSet.end())
59 throw std::out_of_range("The contraction qubit is out of range.");
60
61 const auto q = *qit;
62
63 bool found = false;
64
65 Eigen::Index tensor1IdBest;
66 Eigen::Index tensor2IdBest;
67 Eigen::Index resultRankBest;
68 Eigen::Index bestCost;
69
70 for (auto tensorIt = tensors.begin(); tensorIt != tensors.end();
71 ++tensorIt) {
72 const auto &tensor = tensorIt->second;
73 Eigen::Index tensor1Id = tensor->GetId();
74
75 for (Eigen::Index qi = 0;
76 qi < static_cast<Eigen::Index>(tensor->qubits.size()); ++qi) {
77 if (tensor->qubits[qi] == q) {
78 const Eigen::Index tensor2Id = tensor->connections[qi];
79
80 if (tensor2Id != TensorNode::NotConnected) {
81 auto t1 = tensor1Id;
82 auto t2 = tensor2Id;
83 if (t1 > t2)
84 std::swap(t1, t2);
85 if (visitedPairs.find(std::make_pair(t1, t2)) !=
86 visitedPairs.end())
87 continue;
88 else
89 visitedPairs.insert(std::make_pair(t1, t2));
90
91 const Eigen::Index resultRank =
92 GetResultRank(tensors[tensor1Id], tensors[tensor2Id]);
93
94 // const Eigen::Index Cost = resultRank -
95 // std::max(tensor->GetRank(), tensors[tensor2Id]->GetRank());
96 const Eigen::Index Cost =
97 resultRank -
98 (tensor->GetRank() + tensors[tensor2Id]->GetRank()) / 2;
99
100 if (!found || resultRank < resultRankBest ||
101 (resultRank == resultRankBest && Cost < bestCost)) {
102 resultRankBest = resultRank;
103 bestCost = Cost;
104 tensor1IdBest = tensor1Id;
105 tensor2IdBest = tensor2Id;
106 found = true;
107 }
108 }
109 }
110 }
111 }
112
113 visitedPairs.clear();
114
115 if (!found) {
116 ++qit;
117 continue;
118 }
119
120 ContractNodes(qubit, tensors, tensor1IdBest, tensor2IdBest,
121 resultRankBest);
122
123 if (resultRankBest == 0) {
124 if (tensors.size() == 1 ||
125 tensors[tensor1IdBest]->contractsTheNeededQubit)
126 return std::real(tensors[tensor1IdBest]->tensor->atOffset(0));
127 // erasing this tensor happens because (not the case anymore, it's
128 // avoided) the tensor network might be a disjoint one and a subnetwork
129 // is contracted that does not contain the needed qubit
130 tensors.erase(tensor1IdBest);
131 }
132 }
133
134 return std::real(tensors.begin()->second->tensor->atOffset(0));
135 }
136
142 std::shared_ptr<ITensorContractor> Clone() const override {
143 auto cloned = std::make_shared<VerticalContractor>();
144 cloned->maxTensorRank = maxTensorRank;
145 cloned->enableMultithreading = enableMultithreading;
146 return cloned;
147 }
148};
149
150} // namespace TensorNetworks
151
152#endif // __VERTICAL_CONTRACTOR_H_
The Base Class Tensor Contractor.
bool enableMultithreading
A flag to indicate if multithreading should be enabled.
ITensorContractor::TensorsMap TensorsMap
TensorsMap InitializeTensors(const TensorNetwork &network, Types::qubit_t qubit, std::vector< Eigen::Index > &keys, std::unordered_map< Eigen::Index, Eigen::Index > &keysKeys, bool fillKeys=true, bool contract=true) override
Eigen::Index ContractNodes(Types::qubit_t qubit, PassedTensorsMap &tensors, Eigen::Index tensor1Id, Eigen::Index tensor2Id, Eigen::Index resultRank)
size_t maxTensorRank
The maximum rank of the tensors in the network.
static size_t GetResultRank(const std::shared_ptr< TensorNode > &tensor1, const std::shared_ptr< TensorNode > &tensor2)
const std::unordered_set< Types::qubit_t > & GetQubitGroup(Types::qubit_t q) const
static constexpr Index NotConnected
Definition TensorNode.h:155
The Vertical Variable Elimination Tensor Contractor.
double Contract(const TensorNetwork &network, Types::qubit_t qubit) override
Contract the tensor network.
std::shared_ptr< ITensorContractor > Clone() const override
Clone the tensor contractor.
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:20