-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
stim::ReferenceSampleTree
to support loop folded reference samp…
…ling Part of #768
- Loading branch information
Showing
12 changed files
with
605 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#include "stim/util_top/reference_sample_tree.h" | ||
|
||
using namespace stim; | ||
|
||
bool ReferenceSampleTree::empty() const { | ||
if (repetitions == 0) { | ||
return true; | ||
} | ||
if (!prefix_bits.empty()) { | ||
return false; | ||
} | ||
for (const auto &child: suffix_children) { | ||
if (!child.empty()) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
void ReferenceSampleTree::flatten_and_simplify_into(std::vector<ReferenceSampleTree> &out) const { | ||
if (repetitions == 0) { | ||
return; | ||
} | ||
|
||
std::vector<ReferenceSampleTree> flattened; | ||
if (!prefix_bits.empty()) { | ||
flattened.push_back(ReferenceSampleTree{ | ||
.prefix_bits = prefix_bits, | ||
.suffix_children = {}, | ||
.repetitions = 1, | ||
}); | ||
} | ||
for (const auto &child : suffix_children) { | ||
child.flatten_and_simplify_into(flattened); | ||
} | ||
|
||
// Fuse children. | ||
auto &f = flattened; | ||
for (size_t k = 0; k < f.size(); k++) { | ||
while (k + 1 < f.size() && f[k].repetitions == 1 && f[k].suffix_children.empty() && f[k + 1].repetitions == 1) { | ||
f[k].suffix_children = std::move(f[k + 1].suffix_children); | ||
f[k].prefix_bits.insert(f[k].prefix_bits.end(), f[k + 1].prefix_bits.begin(), f[k + 1].prefix_bits.end()); | ||
f.erase(f.begin() + k + 1); | ||
} | ||
} | ||
|
||
if (repetitions == 1) { | ||
// Un-nest all the children. | ||
for (auto &e : flattened) { | ||
out.push_back(e); | ||
} | ||
} else if (flattened.size() == 1) { | ||
// Merge with single child. | ||
flattened[0].repetitions *= repetitions; | ||
out.push_back(std::move(flattened[0])); | ||
} else if (flattened.empty()) { | ||
// Nothing to report. | ||
} else if (flattened[0].suffix_children.empty() && flattened[0].repetitions == 1) { | ||
// Take payload from first child. | ||
auto result = std::move(flattened[0]); | ||
flattened.erase(flattened.begin()); | ||
result.repetitions = repetitions; | ||
result.suffix_children = std::move(flattened); | ||
out.push_back(std::move(result)); | ||
} else { | ||
out.push_back(ReferenceSampleTree{ | ||
.prefix_bits={}, | ||
.suffix_children=std::move(flattened), | ||
.repetitions=repetitions, | ||
}); | ||
} | ||
} | ||
|
||
ReferenceSampleTree ReferenceSampleTree::simplified() const { | ||
std::vector<ReferenceSampleTree> flat; | ||
flatten_and_simplify_into(flat); | ||
if (flat.empty()) { | ||
return ReferenceSampleTree(); | ||
} else if (flat.size() == 1) { | ||
return flat[0]; | ||
} | ||
|
||
ReferenceSampleTree result; | ||
result.repetitions = 1; | ||
if (flat[0].repetitions == 1 && flat[0].suffix_children.empty()) { | ||
// Take payload from first child. | ||
result = std::move(flat[0]); | ||
flat.erase(flat.begin()); | ||
} | ||
result.suffix_children = std::move(flat); | ||
return result; | ||
} | ||
|
||
size_t ReferenceSampleTree::size() const { | ||
size_t result = prefix_bits.size(); | ||
for (const auto &child: suffix_children) { | ||
result += child.size(); | ||
} | ||
return result * repetitions; | ||
} | ||
|
||
void ReferenceSampleTree::decompress_into(std::vector<bool> &output) const { | ||
for (uint64_t k = 0; k < repetitions; k++) { | ||
output.insert(output.end(), prefix_bits.begin(), prefix_bits.end()); | ||
for (const auto &child: suffix_children) { | ||
child.decompress_into(output); | ||
} | ||
} | ||
} | ||
|
||
ReferenceSampleTree ReferenceSampleTree::from_circuit_reference_sample(const Circuit &circuit) { | ||
auto stats = circuit.compute_stats(); | ||
std::mt19937_64 irrelevant_rng{0}; | ||
CompressedReferenceSampleHelper<MAX_BITWORD_WIDTH> helper( | ||
TableauSimulator<MAX_BITWORD_WIDTH>( | ||
std::move(irrelevant_rng), | ||
stats.num_qubits, | ||
+1, | ||
MeasureRecord(stats.max_lookback))); | ||
return helper.do_loop_with_tortoise_hare_folding(circuit, 1).simplified(); | ||
} | ||
|
||
std::string ReferenceSampleTree::str() const { | ||
std::stringstream ss; | ||
ss << *this; | ||
return ss.str(); | ||
} | ||
|
||
bool ReferenceSampleTree::operator==(const ReferenceSampleTree &other) const { | ||
return repetitions == other.repetitions && | ||
prefix_bits == other.prefix_bits && | ||
suffix_children == other.suffix_children; | ||
} | ||
bool ReferenceSampleTree::operator!=(const ReferenceSampleTree &other) const { | ||
return !(*this == other); | ||
} | ||
|
||
std::ostream &stim::operator<<(std::ostream &out, const ReferenceSampleTree &v) { | ||
out << v.repetitions << "*"; | ||
out << "("; | ||
out << "'"; | ||
for (auto b : v.prefix_bits) { | ||
out << "01"[b]; | ||
} | ||
out << "'"; | ||
for (const auto &child : v.suffix_children) { | ||
out << "+"; | ||
out << child; | ||
} | ||
out << ")"; | ||
return out; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#ifndef _STIM_UTIL_TOP_REFERENCE_SAMPLE_TREE_H | ||
#define _STIM_UTIL_TOP_REFERENCE_SAMPLE_TREE_H | ||
|
||
#include "stim/simulators/tableau_simulator.h" | ||
|
||
namespace stim { | ||
|
||
/// A compressed tree representation of a reference sample. | ||
struct ReferenceSampleTree { | ||
/// Bits to repeatedly output before outputting bits for the children. | ||
std::vector<bool> prefix_bits; | ||
/// Compressed representations of additional bits to output after the prefix. | ||
std::vector<ReferenceSampleTree> suffix_children; | ||
/// The number of times to repeatedly output the prefix and suffix bits. | ||
size_t repetitions = 0; | ||
|
||
/// Initializes a reference sample tree containing a reference sample for the given circuit. | ||
static ReferenceSampleTree from_circuit_reference_sample(const Circuit &circuit); | ||
|
||
/// Returns a tree with the same compressed contents, but a simpler tree structure. | ||
ReferenceSampleTree simplified() const; | ||
|
||
/// Determines whether the tree contains any bits at all. | ||
bool empty() const; | ||
|
||
bool operator==(const ReferenceSampleTree &other) const; | ||
bool operator!=(const ReferenceSampleTree &other) const; | ||
std::string str() const; | ||
|
||
/// Computes the total size of the uncompressed bits represented by the tree. | ||
size_t size() const; | ||
|
||
/// Writes the contents of the tree into the given output vector. | ||
void decompress_into(std::vector<bool> &output) const; | ||
|
||
private: | ||
void flatten_and_simplify_into(std::vector<ReferenceSampleTree> &out) const; | ||
}; | ||
std::ostream &operator<<(std::ostream &out, const ReferenceSampleTree &v); | ||
|
||
/// Helper class for computing compressed reference samples. | ||
template <size_t W> | ||
struct CompressedReferenceSampleHelper { | ||
TableauSimulator<W> sim; | ||
|
||
CompressedReferenceSampleHelper(TableauSimulator<MAX_BITWORD_WIDTH> sim) : sim(sim) { | ||
} | ||
|
||
/// Processes a loop with no top-level folding. | ||
/// | ||
/// Loops containing within the body of this loop (or circuit body) may | ||
/// still be compressed. Only the top-level loop is not folded. | ||
ReferenceSampleTree do_loop_with_no_folding( | ||
const Circuit &loop, | ||
uint64_t reps); | ||
|
||
/// Runs tortoise-and-hare analysis of the loop while simulating its | ||
/// reference sample, in order to attempt to return a compressed | ||
/// representation. | ||
ReferenceSampleTree do_loop_with_tortoise_hare_folding( | ||
const Circuit &loop, | ||
uint64_t reps); | ||
}; | ||
|
||
} // namespace stim | ||
|
||
#include "stim/util_top/reference_sample_tree.inl" | ||
|
||
#endif |
Oops, something went wrong.