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];
82 if (t1 > t2) std::swap(t1, t2);
83 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end()) {
92 visitedPairs.insert(std::make_pair(t1, t2));
94 const auto tensor2 = tensors[tensor2Id];
96 const auto keysKeysIt = keysKeys.find(tensor2Id);
97 if (keysKeysIt != keysKeys.end()) pos2 = keysKeysIt->second;
99 const Eigen::Index resultRank =
GetResultRank(tensor1, tensor2);
102 const Eigen::Index Cost =
103 resultRank - (tensor1->GetRank() + tensor2->GetRank()) / 2;
104 if (Cost <= CostThreshold) {
108 ContractNodes(qubit, tensors, tensor1Id, tensor2Id, resultRank);
110 visitedPairs.clear();
115 if (pos1 ==
static_cast<Eigen::Index
>(keys.size()) - 1) pos1 = pos2;
117 keys[pos2] = keys.back();
118 keysKeys[keys[pos2]] = pos2;
119 keysKeys.erase(tensor2Id);
120 keys.resize(keys.size() - 1);
122 if (resultRank == 0) {
123 if (tensors.size() == 1 ||
124 tensors[tensor1Id]->contractsTheNeededQubit)
125 return std::real(tensors[tensor1Id]->tensor->atOffset(0));
130 keys[pos1] = keys.back();
131 keysKeys[keys[pos1]] = pos1;
132 keysKeys.erase(tensor1Id);
133 keys.resize(keys.size() - 1);
135 tensors.erase(tensor1Id);
142 visitedPairs.clear();
147 return std::real(tensors.begin()->second->tensor->atOffset(0));