This PR is a large-scale refactoring, moving all parameters from CircuitSeq to Context. It will reduce the memory usage of ECC sets.
Please review this PR if you are developing on Quartz.
Benchmark for generator on Nam gate set:
Before:
(3,3)-complete:
Before ECC simplification: num_total_dags = 4496, num_equivalence_classes = 4179, #transformations Nam_3_3 = 634
Nam_3_3 generated. Running Time (s): 9.253
Pruning Time (s): 0.029
Verification Time (s): 8.898
Num_total_dags = 82, num_equivalence_classes = 31
*** Number of transformations of Nam_3_3 = 102
(4,3)-complete (87.1KiB):
Before ECC simplification: num_total_dags = 38357, num_equivalence_classes = 36177, #transformations Nam_4_3 = 4360
Nam_4_3 generated. Running Time (s): 65.136
Pruning Time (s): 0.224
Verification Time (s): 61.132
Num_total_dags = 426, num_equivalence_classes = 193
*** Number of transformations of Nam_4_3 = 466
After (slightly worse, will be fixed in the next PR):
(3,3)-complete:
Before ECC simplification: num_total_dags = 4496, num_equivalence_classes = 4179, #transformations Nam_3_3 = 634
Nam_3_3 generated. Running Time (s): 3.943
Pruning Time (s): 0.009
Verification Time (s): 3.848
Num_total_dags = 94, num_equivalence_classes = 37
*** Number of transformations of Nam_3_3 = 114
(4,3)-complete (70.1KiB):
Before ECC simplification: num_total_dags = 38357, num_equivalence_classes = 36177, #transformations Nam_4_3 = 4360
Nam_4_3 generated. Running Time (s): 29.053
Pruning Time (s): 0.143
Verification Time (s): 27.874
Num_total_dags = 542, num_equivalence_classes = 250
*** Number of transformations of Nam_4_3 = 584
Change list:
CircuitSeq
The object no longer stores any parameters.
The constructor no longer takes the number of input parameters.
add_gate() and insert_gate() no longer allow creating parameters, and add_input_parameter() is removed.
get_num_input_parameters(), get_num_total_parameters(), get_num_internal_parameters(), input_param_used() are removed. Instead, functions get_input_param_indices(), get_directly_used_param_indices(), get_param_expr_ops() are added for convenience.
Parameter-related optimizations like remove_unused_input_params() are removed.
Functions add_gate(), insert_gate(), canonical_representation(), to_canonical_representation(), get_gate_permutation(), get_permuted_seq(), clone_from() now take a context object.
Minor changes:
evaluate() does not compute parameters now.
The return type of remove_gate() changes from int to bool because it can only remove at most one gate now.
get_input_param_mask() is renamed to get_input_param_usage_mask() and part of its function is moved to Context.
PhaseShiftIdType now uses ctx->get_num_parameters() instead of get_num_total_parameters() to distinguish different cases.
Added documentation.
Json
CircuitSeq::to_json() now adds a flag to keep the hash values in the metadata or not. It no longer contains parameter expressions.
The metadata of a CircuitSeq in Json files no longer contains num_input_parameters and num_total_parameters.
Context is now in charge of dumping parameter information to Json by the newly added functions param_info_to_json() and load_param_info_from_json().
The Json file format of Dataset and EquivalenceSet are updated correspondingly.
Adds functions CircuitGate::to_json(), read_json() for convenience.
Generator
generate() no longer takes num_input_parameters and max_num_param_gates. These should be specified in Context.
The function generate_parameter_gates() is moved from CircuitSeq to Context and renamed to generate_parameter_expressions().
Minor changes:
As a private member, context is renamed to ctx_.
Generator now stores a private member input_param_masks_ from Context for convenience.
decltype(std::chrono::steady_clock::now() - std::chrono::steady_clock::now()) is updated to std::chrono::steady_clock::duration. This is what it evaluates to.
Similar to generate(), bfs() no longer takes max_num_param_gates.
Updated documentation.
Verifier
evaluate() no longer computes the parameters -- the logic is moved to find_equivalences().
As a result, we need to copy the equations for the parameters to each call of equivalent().
Phase shift ID (despite unused) is adjusted according to the change to CircuitSeq.
Optimizer
Updates many places involving the construction of Graph and GraphXfer.
Updates Graph::to_circuit_sequence().
Instead of recording constant_param_values in Graph, we now record param_idx and store the concrete parameter values in Context. This keeps the Graphs convertible to CircuitSeqs.
Adds functions get_param_value() and param_has_value() which should be easier to update if the API is going to change again in the future.
Context
get_and_gen_parameters() and get_generated_parameters() are removed. The random values for symbolic parameters for random testing are generated in the constructor of the Context object now.
get_and_gen_input_dis() and get_and_gen_hashing_dis() are merged and renamed to gen_input_and_hashing_dis() because they are always generated together. This also makes the result more deterministic (unrelated to the order of calling get_and_gen_input_dis() and get_and_gen_hashing_dis()).
get_all_param_values() is renamed to get_all_input_param_values().
Functions to create parameters now: get_new_param_id() for plain (input) symbolic and concrete ones, get_new_param_expression_id() for symbolic expressions.
Helper functions get_num_parameters(), get_num_input_symbolic_parameters(), param_is_symbolic(), param_has_value(), param_is_expression(), get_param_wire(). The wire is used in CircuitSeq.
get_param_masks() for input parameter usage masks of each parameter expression.
Cython
The constructor of CircuitSeq now takes only one parameter (the number of qubits).
Member functions of CircuitSeqget_num_input_parameters(), get_num_total_parameters(), get_num_internal_parameters() are removed.
The same changes also apply to the Python class PyDAG.
EquivalenceSet::load_json now takes an extra parameter specifying if it is from the Python verifier.
QASMParser
Renames the private member context to ctx_.
Simulator
Some functions need a Context for parameters now.
When verifying a schedule, we only compute the parameters through Context once now (previously twice).
Utils
read_json_style_vector() now also supports std::istream (previously only std::stringstream).
Moves to_string_with_precision() from utils.h to string_utils.h and adds to_json_style_string_with_precision().
Close #17
This PR is a large-scale refactoring, moving all parameters from
CircuitSeq
toContext
. It will reduce the memory usage of ECC sets.Please review this PR if you are developing on Quartz.
Benchmark for generator on Nam gate set: Before: (3,3)-complete:
(4,3)-complete (87.1KiB):
After (slightly worse, will be fixed in the next PR): (3,3)-complete:
(4,3)-complete (70.1KiB):
Change list:
CircuitSeq
add_gate()
andinsert_gate()
no longer allow creating parameters, andadd_input_parameter()
is removed.get_num_input_parameters(), get_num_total_parameters(), get_num_internal_parameters(), input_param_used()
are removed. Instead, functionsget_input_param_indices(), get_directly_used_param_indices(), get_param_expr_ops()
are added for convenience.remove_unused_input_params()
are removed.add_gate(), insert_gate(), canonical_representation(), to_canonical_representation(), get_gate_permutation(), get_permuted_seq(), clone_from()
now take a context object.evaluate()
does not compute parameters now.remove_gate()
changes fromint
tobool
because it can only remove at most one gate now.get_input_param_mask()
is renamed toget_input_param_usage_mask()
and part of its function is moved toContext
.PhaseShiftIdType
now usesctx->get_num_parameters()
instead ofget_num_total_parameters()
to distinguish different cases.Json
CircuitSeq::to_json()
now adds a flag to keep the hash values in the metadata or not. It no longer contains parameter expressions.CircuitSeq
in Json files no longer containsnum_input_parameters
andnum_total_parameters
.Context
is now in charge of dumping parameter information to Json by the newly added functionsparam_info_to_json()
andload_param_info_from_json()
.Dataset
andEquivalenceSet
are updated correspondingly.CircuitGate::to_json(), read_json()
for convenience.Generator
generate()
no longer takesnum_input_parameters
andmax_num_param_gates
. These should be specified inContext
.generate_parameter_gates()
is moved fromCircuitSeq
toContext
and renamed togenerate_parameter_expressions()
.context
is renamed toctx_
.Generator
now stores a private memberinput_param_masks_
fromContext
for convenience.decltype(std::chrono::steady_clock::now() - std::chrono::steady_clock::now())
is updated tostd::chrono::steady_clock::duration
. This is what it evaluates to.generate()
,bfs()
no longer takesmax_num_param_gates
.Verifier
evaluate()
no longer computes the parameters -- the logic is moved tofind_equivalences()
.equivalent()
.CircuitSeq
.Optimizer
Graph
andGraphXfer
.Graph::to_circuit_sequence()
.constant_param_values
inGraph
, we now recordparam_idx
and store the concrete parameter values inContext
. This keeps theGraph
s convertible toCircuitSeq
s.get_param_value()
andparam_has_value()
which should be easier to update if the API is going to change again in the future.Context
get_and_gen_parameters()
andget_generated_parameters()
are removed. The random values for symbolic parameters for random testing are generated in the constructor of theContext
object now.get_and_gen_input_dis()
andget_and_gen_hashing_dis()
are merged and renamed togen_input_and_hashing_dis()
because they are always generated together. This also makes the result more deterministic (unrelated to the order of callingget_and_gen_input_dis()
andget_and_gen_hashing_dis()
).get_all_param_values()
is renamed toget_all_input_param_values()
.get_new_param_id()
for plain (input) symbolic and concrete ones,get_new_param_expression_id()
for symbolic expressions.get_num_parameters(), get_num_input_symbolic_parameters(), param_is_symbolic(), param_has_value(), param_is_expression(), get_param_wire()
. The wire is used inCircuitSeq
.get_param_masks()
for input parameter usage masks of each parameter expression.Cython
CircuitSeq
now takes only one parameter (the number of qubits).CircuitSeq
get_num_input_parameters(), get_num_total_parameters(), get_num_internal_parameters()
are removed.PyDAG
.EquivalenceSet::load_json
now takes an extra parameter specifying if it is from the Python verifier.QASMParser
context
toctx_
.Simulator
Context
for parameters now.Context
once now (previously twice).Utils
read_json_style_vector()
now also supportsstd::istream
(previously onlystd::stringstream
).to_string_with_precision()
fromutils.h
tostring_utils.h
and addsto_json_style_string_with_precision()
.