52 long long int CostThreshold = -1;
53 size_t rejections = 0;
55 std::vector<Eigen::Index> keys;
56 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
60 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
61 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
64 while (tensors.size() > 1) {
66 std::uniform_int_distribution<Eigen::Index> tensor1Dist(
67 0LL,
static_cast<Eigen::Index
>(keys.size()) - 1);
68 auto pos1 = tensor1Dist(
gen);
69 Eigen::Index tensor1Id = keys[pos1];
70 const auto tensor1 = tensors[tensor1Id];
75 std::uniform_int_distribution<Eigen::Index> tensor2Dist(
76 0LL,
static_cast<Eigen::Index
>(tensor1->connections.size()) - 1);
77 auto pos2 = tensor2Dist(
gen);
78 Eigen::Index tensor2Id = tensor1->connections[pos2];
84 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end()) {
93 visitedPairs.insert(std::make_pair(t1, t2));
95 const auto tensor2 = tensors[tensor2Id];
97 const auto keysKeysIt = keysKeys.find(tensor2Id);
98 if (keysKeysIt != keysKeys.end())
99 pos2 = keysKeysIt->second;
101 const Eigen::Index resultRank =
GetResultRank(tensor1, tensor2);
104 const Eigen::Index Cost =
105 resultRank - (tensor1->GetRank() + tensor2->GetRank()) / 2;
106 if (Cost <= CostThreshold) {
110 ContractNodes(qubit, tensors, tensor1Id, tensor2Id, resultRank);
112 visitedPairs.clear();
117 if (pos1 ==
static_cast<Eigen::Index
>(keys.size()) - 1)
120 keys[pos2] = keys.back();
121 keysKeys[keys[pos2]] = pos2;
122 keysKeys.erase(tensor2Id);
123 keys.resize(keys.size() - 1);
125 if (resultRank == 0) {
126 if (tensors.size() == 1 ||
127 tensors[tensor1Id]->contractsTheNeededQubit)
128 return std::real(tensors[tensor1Id]->tensor->atOffset(0));
133 keys[pos1] = keys.back();
134 keysKeys[keys[pos1]] = pos1;
135 keysKeys.erase(tensor1Id);
136 keys.resize(keys.size() - 1);
138 tensors.erase(tensor1Id);
145 visitedPairs.clear();
150 return std::real(tensors.begin()->second->tensor->atOffset(0));