Maestro 0.3.11
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{
27
34{
35 public:
42 double Contract(const TensorNetwork &network, Types::qubit_t qubit) override
43 {
44 std::vector<Eigen::Index> keys;
45 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
46
47 TensorsMap tensors = InitializeTensors(network, qubit, keys, keysKeys, false);
48
49 const auto &qubitGroup = network.GetQubitGroup(qubit);
50 const std::set<Types::qubit_t> qubitGroupSet(qubitGroup.begin(), qubitGroup.end());
51
52 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
53 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
54
55 auto qit = qubitGroupSet.begin();
56
57 // while there is more than one tensor...
58 while (tensors.size() > 1)
59 {
60 if (qit == qubitGroupSet.end())
61 throw std::out_of_range("The contraction qubit is out of range.");
62
63 const auto q = *qit;
64
65 bool found = false;
66
67 Eigen::Index tensor1IdBest;
68 Eigen::Index tensor2IdBest;
69 Eigen::Index resultRankBest;
70 Eigen::Index bestCost;
71
72 for (auto tensorIt = tensors.begin(); tensorIt != tensors.end(); ++tensorIt)
73 {
74 const auto &tensor = tensorIt->second;
75 Eigen::Index tensor1Id = tensor->GetId();
76
77 for (Eigen::Index qi = 0; qi < static_cast<Eigen::Index>(tensor->qubits.size()); ++qi)
78 {
79 if (tensor->qubits[qi] == q)
80 {
81 const Eigen::Index tensor2Id = tensor->connections[qi];
82
83 if (tensor2Id != TensorNode::NotConnected)
84 {
85 auto t1 = tensor1Id;
86 auto t2 = tensor2Id;
87 if (t1 > t2)
88 std::swap(t1, t2);
89 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end())
90 continue;
91 else
92 visitedPairs.insert(std::make_pair(t1, t2));
93
94 const Eigen::Index resultRank = GetResultRank(tensors[tensor1Id], tensors[tensor2Id]);
95
96 // const Eigen::Index Cost = resultRank -
97 // std::max(tensor->GetRank(), tensors[tensor2Id]->GetRank());
98 const Eigen::Index Cost = resultRank - (tensor->GetRank() + tensors[tensor2Id]->GetRank()) / 2;
99
100 if (!found || resultRank < resultRankBest || (resultRank == resultRankBest && Cost < bestCost))
101 {
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 {
117 ++qit;
118 continue;
119 }
120
121 ContractNodes(qubit, tensors, tensor1IdBest, tensor2IdBest, resultRankBest);
122
123 if (resultRankBest == 0)
124 {
125 if (tensors.size() == 1 || 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 {
144 auto cloned = std::make_shared<VerticalContractor>();
145 cloned->maxTensorRank = maxTensorRank;
146 cloned->enableMultithreading = enableMultithreading;
147 return cloned;
148 }
149};
150
151} // namespace TensorNetworks
152
153#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:173
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:23