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];
85 if (visitedPairs.find(std::make_pair(t1, t2)) !=
89 visitedPairs.insert(std::make_pair(t1, t2));
91 const Eigen::Index resultRank =
96 const Eigen::Index Cost =
98 (tensor->GetRank() + tensors[tensor2Id]->GetRank()) / 2;
100 if (!found || resultRank < resultRankBest ||
101 (resultRank == resultRankBest && Cost < bestCost)) {
102 resultRankBest = resultRank;
104 tensor1IdBest = tensor1Id;
105 tensor2IdBest = tensor2Id;
113 visitedPairs.clear();
123 if (resultRankBest == 0) {
124 if (tensors.size() == 1 ||
125 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));