44 std::vector<Eigen::Index> keys;
45 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
50 const std::set<Types::qubit_t> qubitGroupSet(qubitGroup.begin(), qubitGroup.end());
52 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
53 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
55 auto qit = qubitGroupSet.begin();
58 while (tensors.size() > 1)
60 if (qit == qubitGroupSet.end())
61 throw std::out_of_range(
"The contraction qubit is out of range.");
67 Eigen::Index tensor1IdBest;
68 Eigen::Index tensor2IdBest;
69 Eigen::Index resultRankBest;
70 Eigen::Index bestCost;
72 for (
auto tensorIt = tensors.begin(); tensorIt != tensors.end(); ++tensorIt)
74 const auto &tensor = tensorIt->second;
75 Eigen::Index tensor1Id = tensor->GetId();
77 for (Eigen::Index qi = 0; qi < static_cast<Eigen::Index>(tensor->qubits.size()); ++qi)
79 if (tensor->qubits[qi] == q)
81 const Eigen::Index tensor2Id = tensor->connections[qi];
89 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end())
92 visitedPairs.insert(std::make_pair(t1, t2));
94 const Eigen::Index resultRank =
GetResultRank(tensors[tensor1Id], tensors[tensor2Id]);
98 const Eigen::Index Cost = resultRank - (tensor->GetRank() + tensors[tensor2Id]->GetRank()) / 2;
100 if (!found || resultRank < resultRankBest || (resultRank == resultRankBest && Cost < bestCost))
102 resultRankBest = resultRank;
104 tensor1IdBest = tensor1Id;
105 tensor2IdBest = tensor2Id;
113 visitedPairs.clear();
121 ContractNodes(qubit, tensors, tensor1IdBest, tensor2IdBest, resultRankBest);
123 if (resultRankBest == 0)
125 if (tensors.size() == 1 || tensors[tensor1IdBest]->contractsTheNeededQubit)
126 return std::real(tensors[tensor1IdBest]->tensor->atOffset(0));
130 tensors.erase(tensor1IdBest);
134 return std::real(tensors.begin()->second->tensor->atOffset(0));