Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion crates/qpy/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use qiskit_circuit::operations::Param;
use qiskit_circuit::parameter::parameter_expression::{
OPReplay, OpCode, ParameterExpression, ParameterValueType, PyParameter,
};
use qiskit_circuit::parameter::symbol_expr::Symbol;
use qiskit_circuit::parameter::symbol_expr::{Symbol, SymbolExpr, Value};
use std::sync::Arc;
use uuid::Uuid;

Expand Down Expand Up @@ -343,6 +343,18 @@ pub(crate) fn unpack_parameter_expression(
let parameter_expression_data = deserialize_vec::<formats::ParameterExpressionElementPack>(
&parameter_expression_pack.expression_data,
)?;
if parameter_expression_data.is_empty() {
// special case: we can't reconstruct the expression from replay, we'll instantiate it directly
// empty expressions are basically Value(0), but we also need to preserve the symbol table
let expr = SymbolExpr::Value(Value::Int(0));
let mut name_map = HashMap::new();
for value in param_uuid_map.values() {
if let GenericValue::ParameterExpressionSymbol(symbol) = &value {
name_map.insert(symbol.repr(false), symbol.clone());
}
}
return Ok(ParameterExpression::new(expr, name_map));
}

// we now convert the parameter_expression_data into Vec<OPReplay> that can be used via ParameterExpression::from_qpy
let mut replay: Vec<OPReplay> = Vec::new();
Expand Down
16 changes: 16 additions & 0 deletions test/python/circuit/test_circuit_load_from_qpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,22 @@ def test_parameter_expression(self):
self.assertEqual(qc, new_circuit)
self.assertDeprecatedBitProperties(qc, new_circuit)

def test_degenerate_parameter_expression(self):
"""Test a circuit with a parameter expression that simplifies to 0."""
x = Parameter("x")
y_vec = ParameterVector("y", 2)
cases = [0 * x, x - x, 0 * y_vec[0], 0 * (x + y_vec[1])]
for case in cases:
qc = QuantumCircuit(1)
qc.rz(case, 0)
qpy_file = io.BytesIO()
dump(qc, qpy_file)
qpy_file.seek(0)
new_circuit = load(qpy_file)[0]
self.assertEqual(qc, new_circuit)
# should still have the same parameters even if they are not used
self.assertEqual(qc.parameters, new_circuit.parameters)

def test_string_parameter(self):
"""Test a PauliGate instruction that has string parameters."""

Expand Down