44 std::vector<Eigen::Index> keys;
45 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
49 std::map<Eigen::Index, std::shared_ptr<TensorNode>> tensorsMap(
50 tensors.begin(), tensors.end());
52 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
53 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
55 Eigen::Index maxRank = 4;
56 Eigen::Index nextRank = 4;
59 Eigen::Index tensor1Id = 0;
60 Eigen::Index tensor2Id = 1;
61 Eigen::Index resultRank = 4;
62 Eigen::Index bestCost = 4;
65 while (tensors.size() > 1) {
71 bool nextRankSet =
false;
73 for (
auto tensorIt = tensorsMap.rbegin(); tensorIt != tensorsMap.rend();
75 const auto &tensor = tensorIt->second;
76 const auto curTensorId = tensor->GetId();
82 for (Eigen::Index ti = 0;
83 ti < static_cast<Eigen::Index>(tensor->connections.size()); ++ti) {
84 const auto nextTensorId = tensor->connections[ti];
87 auto t1 = curTensorId;
88 auto t2 = nextTensorId;
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));