34 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
46 std::vector<Eigen::Index> keys;
47 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
53 while (tensors.size() > 1)
56 auto it = tensors.begin();
57 Eigen::Index tensor1Id = it->first;
59 Eigen::Index tensor2Id = it->first;
63 Eigen::Index maxCost = std::numeric_limits<Eigen::Index>::max();
64 size_t bestDepth = numberOfLevels;
65 Lookahead(qubit, tensor1Id, tensor2Id, bestDepth, 0, 0, dummyTensors, 1, maxCost, 0);
67 const auto &tensor = tensors[tensor1Id];
68 const auto resultRank =
GetResultRank(tensor, tensors[tensor2Id]);
71 ContractNodes(qubit, dummyTensors, tensor1Id, tensor2Id, resultRank);
75 ContractNodes(qubit, tensors, tensor1Id, tensor2Id, resultRank);
79 if (tensors.size() == 1 || tensor->contractsTheNeededQubit)
80 return std::real(tensor->tensor->atOffset(0));
84 tensors.erase(tensor1Id);
85 dummyTensors.erase(tensor1Id);
89 return std::real(tensors.begin()->second->tensor->atOffset(0));
94 return numberOfLevels;
99 numberOfLevels = levels;
104 return useMaxRankCost;
109 useMaxRankCost = val;
117 std::shared_ptr<ITensorContractor>
Clone()
const override
119 auto cloned = std::make_shared<LookaheadContractor>();
123 cloned->numberOfLevels = numberOfLevels;
124 cloned->useMaxRankCost = useMaxRankCost;
130 void Lookahead(
Types::qubit_t qubit, Eigen::Index &tensor1Id, Eigen::Index &tensor2Id,
size_t &bestDepth, Eigen::Index curt1, Eigen::Index curt2,
131 DummyTensorsMap &dummyTensors,
size_t curLevel, Eigen::Index &maxCost, Eigen::Index CostOnPath)
133 if (dummyTensors.size() > 1 && curLevel < numberOfLevels)
135 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
137 for (
auto tensorIt = dummyTensors.begin(); tensorIt != dummyTensors.end(); ++tensorIt)
139 auto tensor = tensorIt->second;
140 const auto curTensorId = tensor->GetId();
142 assert(tensor->tensor->IsDummy());
145 for (Eigen::Index ti = 0; ti < static_cast<Eigen::Index>(tensor->connections.size()); ++ti)
147 const auto nextTensorId = tensor->connections[ti];
151 auto t1 = curTensorId;
152 auto t2 = nextTensorId;
155 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end())
158 visitedPairs.insert(std::make_pair(t1, t2));
160 const Eigen::Index newRank =
GetResultRank(tensor, dummyTensors[nextTensorId]);
164 const Eigen::Index newCostOnPath = useMaxRankCost ? std::max(newRank, CostOnPath) : CostOnPath + newRank;
165 if (newCostOnPath < maxCost)
177 auto saveTensor2 = dummyTensors[nextTensorId];
179 ContractNodes(qubit, dummyTensors, curTensorId, nextTensorId, newRank);
181 Lookahead(qubit, tensor1Id, tensor2Id, bestDepth, curLevel == 1 ? curTensorId : curt1, curLevel == 1 ? nextTensorId : curt2,
182 dummyTensors, curLevel + 1, maxCost, newCostOnPath);
186 dummyTensors[curTensorId] = tensor;
187 dummyTensors[nextTensorId] = saveTensor2;
192 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(tensor->connections.size()); ++i)
196 const auto connectedTensorId = tensor->connections[i];
197 const auto otherTensorIndex = tensor->connectionsIndices[i];
200 dummyTensors[connectedTensorId]->connectionsIndices[otherTensorIndex] = i;
204 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(saveTensor2->connections.size()); ++i)
208 const auto connectedTensorId = saveTensor2->connections[i];
209 const auto otherTensorIndex = saveTensor2->connectionsIndices[i];
210 dummyTensors[connectedTensorId]->connections[otherTensorIndex] = nextTensorId;
211 dummyTensors[connectedTensorId]->connectionsIndices[otherTensorIndex] = i;
218 tensorIt = dummyTensors.find(curTensorId);
225 if ((curLevel == numberOfLevels && CostOnPath < maxCost) ||
226 (dummyTensors.size() <= 1 && (CostOnPath < maxCost || (maxCost == CostOnPath && curLevel < bestDepth))))
228 maxCost = CostOnPath;
229 bestDepth = curLevel;
239 for (
const auto &[tensorId, tensor] : tensors)
240 clonedTensors[tensorId] = tensor->CloneWithADummyTensor();
242 return clonedTensors;
245 size_t numberOfLevels = 3;
246 bool useMaxRankCost =
true;