41 std::vector<Eigen::Index> keys;
42 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
48 const std::set<Types::qubit_t> qubitGroupSet(qubitGroup.begin(),
51 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
52 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
54 auto qit = qubitGroupSet.begin();
57 while (tensors.size() > 1) {
58 if (qit == qubitGroupSet.end())
59 throw std::out_of_range(
"The contraction qubit is out of range.");
65 Eigen::Index tensor1IdBest;
66 Eigen::Index tensor2IdBest;
67 Eigen::Index resultRankBest;
68 Eigen::Index bestCost;
70 for (
auto tensorIt = tensors.begin(); tensorIt != tensors.end();
72 const auto &tensor = tensorIt->second;
73 Eigen::Index tensor1Id = tensor->GetId();
75 for (Eigen::Index qi = 0;
76 qi < static_cast<Eigen::Index>(tensor->qubits.size()); ++qi) {
77 if (tensor->qubits[qi] == q) {
78 const Eigen::Index tensor2Id = tensor->connections[qi];
83 if (t1 > t2) std::swap(t1, t2);
84 if (visitedPairs.find(std::make_pair(t1, t2)) !=
88 visitedPairs.insert(std::make_pair(t1, t2));
90 const Eigen::Index resultRank =
95 const Eigen::Index Cost =
97 (tensor->GetRank() + tensors[tensor2Id]->GetRank()) / 2;
99 if (!found || resultRank < resultRankBest ||
100 (resultRank == resultRankBest && Cost < bestCost)) {
101 resultRankBest = resultRank;
103 tensor1IdBest = tensor1Id;
104 tensor2IdBest = tensor2Id;
112 visitedPairs.clear();
122 if (resultRankBest == 0) {
123 if (tensors.size() == 1 ||
124 tensors[tensor1IdBest]->contractsTheNeededQubit)
125 return std::real(tensors[tensor1IdBest]->tensor->atOffset(0));
129 tensors.erase(tensor1IdBest);
133 return std::real(tensors.begin()->second->tensor->atOffset(0));