45 std::vector<Eigen::Index> keys;
46 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
50 std::map<Eigen::Index, std::shared_ptr<TensorNode>> tensorsMap(
51 tensors.begin(), tensors.end());
53 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
54 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
56 Eigen::Index maxRank = 4;
57 Eigen::Index nextRank = 4;
60 Eigen::Index tensor1Id = 0;
61 Eigen::Index tensor2Id = 1;
62 Eigen::Index resultRank = 4;
63 Eigen::Index bestCost = 4;
66 while (tensors.size() > 1) {
72 bool nextRankSet =
false;
74 for (
auto tensorIt = tensorsMap.rbegin(); tensorIt != tensorsMap.rend();
76 const auto &tensor = tensorIt->second;
77 const auto curTensorId = tensor->GetId();
83 for (Eigen::Index ti = 0;
84 ti < static_cast<Eigen::Index>(tensor->connections.size()); ++ti) {
85 const auto nextTensorId = tensor->connections[ti];
88 auto t1 = curTensorId;
89 auto t2 = nextTensorId;
90 if (t1 > t2) std::swap(t1, t2);
92 const auto p = std::make_pair(t1, t2);
93 if (visitedPairs.find(p) != visitedPairs.end())
96 visitedPairs.insert(p);
98 const Eigen::Index newRank =
101 if (newRank <= maxRank) {
102 const Eigen::Index Cost =
104 (tensor->GetRank() + tensors[nextTensorId]->GetRank()) / 2;
106 if (!found || newRank < resultRank ||
107 (newRank == resultRank && Cost < bestCost)) {
108 tensor1Id = curTensorId;
109 tensor2Id = nextTensorId;
110 resultRank = newRank;
121 nextRank = std::min(nextRank, newRank);
127 visitedPairs.clear();
134 ContractNodes(qubit, tensors, tensor1Id, tensor2Id, resultRank);
135 tensorsMap[tensor1Id] = tensors[tensor1Id];
136 tensorsMap.erase(tensor2Id);
138 if (resultRank == 0) {
139 if (tensors.size() == 1 || tensors[tensor1Id]->contractsTheNeededQubit)
140 return std::real(tensors[tensor1Id]->tensor->atOffset(0));
146 tensors.erase(tensor1Id);
147 tensorsMap.erase(tensor1Id);
151 return std::real(tensors.begin()->second->tensor->atOffset(0));