32 using TensorPair = std::pair<Eigen::Index, Eigen::Index>;
34 std::unordered_set<TensorPair, boost::hash<TensorPair>>;
44 std::vector<Eigen::Index> keys;
45 std::unordered_map<Eigen::Index, Eigen::Index> keysKeys;
52 while (tensors.size() > 1) {
54 auto it = tensors.begin();
55 Eigen::Index tensor1Id = it->first;
57 Eigen::Index tensor2Id = it->first;
61 Eigen::Index maxCost = std::numeric_limits<Eigen::Index>::max();
62 size_t bestDepth = numberOfLevels;
63 Lookahead(qubit, tensor1Id, tensor2Id, bestDepth, 0, 0, dummyTensors, 1,
66 const auto &tensor = tensors[tensor1Id];
67 const auto resultRank =
GetResultRank(tensor, tensors[tensor2Id]);
70 ContractNodes(qubit, dummyTensors, tensor1Id, tensor2Id, resultRank);
74 ContractNodes(qubit, tensors, tensor1Id, tensor2Id, resultRank);
76 if (resultRank == 0) {
77 if (tensors.size() == 1 || tensor->contractsTheNeededQubit)
78 return std::real(tensor->tensor->atOffset(0));
82 tensors.erase(tensor1Id);
83 dummyTensors.erase(tensor1Id);
87 return std::real(tensors.begin()->second->tensor->atOffset(0));
103 std::shared_ptr<ITensorContractor>
Clone()
const override {
104 auto cloned = std::make_shared<LookaheadContractor>();
108 cloned->numberOfLevels = numberOfLevels;
109 cloned->useMaxRankCost = useMaxRankCost;
116 Eigen::Index &tensor2Id,
size_t &bestDepth, Eigen::Index curt1,
118 size_t curLevel, Eigen::Index &maxCost,
119 Eigen::Index CostOnPath) {
120 if (dummyTensors.size() > 1 && curLevel < numberOfLevels) {
121 std::unordered_set<TensorPair, boost::hash<TensorPair>> visitedPairs;
123 for (
auto tensorIt = dummyTensors.begin(); tensorIt != dummyTensors.end();
125 auto tensor = tensorIt->second;
126 const auto curTensorId = tensor->GetId();
128 assert(tensor->tensor->IsDummy());
131 for (Eigen::Index ti = 0;
132 ti < static_cast<Eigen::Index>(tensor->connections.size()); ++ti) {
133 const auto nextTensorId = tensor->connections[ti];
136 auto t1 = curTensorId;
137 auto t2 = nextTensorId;
140 if (visitedPairs.find(std::make_pair(t1, t2)) != visitedPairs.end())
143 visitedPairs.insert(std::make_pair(t1, t2));
145 const Eigen::Index newRank =
150 const Eigen::Index newCostOnPath =
151 useMaxRankCost ? std::max(newRank, CostOnPath)
152 : CostOnPath + newRank;
153 if (newCostOnPath < maxCost) {
164 auto saveTensor2 = dummyTensors[nextTensorId];
166 ContractNodes(qubit, dummyTensors, curTensorId, nextTensorId,
169 Lookahead(qubit, tensor1Id, tensor2Id, bestDepth,
170 curLevel == 1 ? curTensorId : curt1,
171 curLevel == 1 ? nextTensorId : curt2, dummyTensors,
172 curLevel + 1, maxCost, newCostOnPath);
176 dummyTensors[curTensorId] = tensor;
177 dummyTensors[nextTensorId] = saveTensor2;
182 for (Eigen::Index i = 0;
183 i < static_cast<Eigen::Index>(tensor->connections.size());
186 tensor->connections[i] != nextTensorId) {
187 const auto connectedTensorId = tensor->connections[i];
188 const auto otherTensorIndex = tensor->connectionsIndices[i];
191 dummyTensors[connectedTensorId]
192 ->connectionsIndices[otherTensorIndex] = i;
196 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(
197 saveTensor2->connections.size());
200 saveTensor2->connections[i] != curTensorId) {
201 const auto connectedTensorId = saveTensor2->connections[i];
202 const auto otherTensorIndex =
203 saveTensor2->connectionsIndices[i];
204 dummyTensors[connectedTensorId]
205 ->connections[otherTensorIndex] = nextTensorId;
206 dummyTensors[connectedTensorId]
207 ->connectionsIndices[otherTensorIndex] = i;
214 tensorIt = dummyTensors.find(curTensorId);
221 if ((curLevel == numberOfLevels && CostOnPath < maxCost) ||
222 (dummyTensors.size() <= 1 &&
223 (CostOnPath < maxCost ||
224 (maxCost == CostOnPath && curLevel < bestDepth)))) {
225 maxCost = CostOnPath;
226 bestDepth = curLevel;
235 for (
const auto &[tensorId, tensor] : tensors)
236 clonedTensors[tensorId] = tensor->CloneWithADummyTensor();
238 return clonedTensors;
241 size_t numberOfLevels = 3;
242 bool useMaxRankCost =
true;