• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Qiskit / qiskit / 15919177642

27 Jun 2025 05:49AM UTC coverage: 87.647% (-0.3%) from 87.988%
15919177642

push

github

web-flow
fixing MCXSynthesis1DirtyKG24 and MCXSynthesis2DirtyKG24 plugins (#14670) (#14671)

(cherry picked from commit 835325167)

Co-authored-by: Alexander Ivrii <alexi@il.ibm.com>

2 of 2 new or added lines in 1 file covered. (100.0%)

251 existing lines in 70 files now uncovered.

80014 of 91291 relevant lines covered (87.65%)

511543.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.0
/crates/circuit/src/classical/expr/expr.rs
1
// This code is part of Qiskit.
2
//
3
// (C) Copyright IBM 2025
4
//
5
// This code is licensed under the Apache License, Version 2.0. You may
6
// obtain a copy of this license in the LICENSE.txt file in the root directory
7
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
//
9
// Any modifications or derivative works of this code must retain this
10
// copyright notice, and modified files need to carry a notice indicating
11
// that they have been altered from the originals.
12

13
use crate::classical::expr::{Binary, Cast, Index, Stretch, Unary, Value, Var};
14
use crate::classical::types::Type;
15
use pyo3::prelude::*;
16
use pyo3::{intern, IntoPyObjectExt};
17

18
/// A classical expression.
19
///
20
/// Variants that themselves contain [Expr]s are boxed. This is done instead
21
/// of boxing the contained [Expr]s within the specific type to reduce the
22
/// number of boxes we need (e.g. Binary would otherwise contain two boxed
23
/// expressions).
24
#[derive(Clone, Debug, PartialEq)]
25
pub enum Expr {
26
    Unary(Box<Unary>),
27
    Binary(Box<Binary>),
28
    Cast(Box<Cast>),
29
    Value(Value),
30
    Var(Var),
31
    Stretch(Stretch),
32
    Index(Box<Index>),
33
}
34

35
impl Expr {
36
    /// The const-ness of the expression.
37
    pub fn is_const(&self) -> bool {
3,718✔
38
        match self {
3,718✔
39
            Expr::Unary(u) => u.constant,
38✔
40
            Expr::Binary(b) => b.constant,
378✔
41
            Expr::Cast(c) => c.constant,
106✔
42
            Expr::Value(_) => true,
1,412✔
43
            Expr::Var(_) => false,
1,700✔
44
            Expr::Stretch(_) => true,
78✔
45
            Expr::Index(i) => i.constant,
6✔
46
        }
47
    }
3,718✔
48

49
    /// The expression's [Type].
50
    pub fn ty(&self) -> Type {
×
51
        match self {
×
52
            Expr::Unary(u) => u.ty,
×
53
            Expr::Binary(b) => b.ty,
×
54
            Expr::Cast(c) => c.ty,
×
55
            Expr::Value(v) => match v {
×
56
                Value::Duration(_) => Type::Duration,
×
57
                Value::Float { ty, .. } => *ty,
×
58
                Value::Uint { ty, .. } => *ty,
×
59
            },
60
            Expr::Var(v) => match v {
×
61
                Var::Standalone { ty, .. } => *ty,
×
62
                Var::Bit { .. } => Type::Bool,
×
63
                Var::Register { ty, .. } => *ty,
×
64
            },
65
            Expr::Stretch(_) => Type::Duration,
×
66
            Expr::Index(i) => i.ty,
×
67
        }
68
    }
×
69

70
    /// Returns an iterator over the [Var] nodes in this expression in some
71
    /// deterministic order.
72
    pub fn vars(&self) -> impl Iterator<Item = &Var> {
6,664✔
73
        VarIterator(ExprIterator { stack: vec![self] })
6,664✔
74
    }
6,664✔
75
}
76

77
/// A private iterator over the [Expr] nodes of an expression
78
/// by reference.
79
///
80
/// The first node reference returned is the [Expr] itself.
81
struct ExprIterator<'a> {
82
    stack: Vec<&'a Expr>,
83
}
84

85
impl<'a> Iterator for ExprIterator<'a> {
86
    type Item = &'a Expr;
87

88
    fn next(&mut self) -> Option<Self::Item> {
16,378✔
89
        let expr = self.stack.pop()?;
16,378✔
90
        match expr {
9,714✔
91
            Expr::Unary(u) => {
176✔
92
                self.stack.push(&u.operand);
176✔
93
            }
176✔
94
            Expr::Binary(b) => {
1,380✔
95
                self.stack.push(&b.left);
1,380✔
96
                self.stack.push(&b.right);
1,380✔
97
            }
1,380✔
98
            Expr::Cast(c) => self.stack.push(&c.operand),
82✔
99
            Expr::Value(_) => {}
2,690✔
100
            Expr::Var(_) => {}
5,370✔
101
            Expr::Stretch(_) => {}
×
102
            Expr::Index(i) => {
16✔
103
                self.stack.push(&i.index);
16✔
104
                self.stack.push(&i.target);
16✔
105
            }
16✔
106
        }
107
        Some(expr)
9,714✔
108
    }
16,378✔
109
}
110

111
/// A private iterator over the [Var] nodes contained within an [Expr].
112
struct VarIterator<'a>(ExprIterator<'a>);
113

114
impl<'a> Iterator for VarIterator<'a> {
115
    type Item = &'a Var;
116

117
    fn next(&mut self) -> Option<Self::Item> {
12,034✔
118
        for expr in self.0.by_ref() {
12,034✔
119
            if let Expr::Var(v) = expr {
9,714✔
120
                return Some(v);
5,370✔
121
            }
4,344✔
122
        }
123
        None
6,664✔
124
    }
12,034✔
125
}
126

127
impl From<Unary> for Expr {
128
    fn from(value: Unary) -> Self {
×
129
        Expr::Unary(Box::new(value))
×
130
    }
×
131
}
132

133
impl From<Box<Unary>> for Expr {
134
    fn from(value: Box<Unary>) -> Self {
×
135
        Expr::Unary(value)
×
136
    }
×
137
}
138

139
impl From<Binary> for Expr {
140
    fn from(value: Binary) -> Self {
×
141
        Expr::Binary(Box::new(value))
×
142
    }
×
143
}
144

145
impl From<Box<Binary>> for Expr {
146
    fn from(value: Box<Binary>) -> Self {
×
147
        Expr::Binary(value)
×
148
    }
×
149
}
150

151
impl From<Cast> for Expr {
152
    fn from(value: Cast) -> Self {
×
153
        Expr::Cast(Box::new(value))
×
154
    }
×
155
}
156

157
impl From<Box<Cast>> for Expr {
158
    fn from(value: Box<Cast>) -> Self {
×
159
        Expr::Cast(value)
×
160
    }
×
161
}
162

163
impl From<Value> for Expr {
164
    fn from(value: Value) -> Self {
×
165
        Expr::Value(value)
×
166
    }
×
167
}
168

169
impl From<Var> for Expr {
170
    fn from(value: Var) -> Self {
×
171
        Expr::Var(value)
×
172
    }
×
173
}
174

175
impl From<Stretch> for Expr {
176
    fn from(value: Stretch) -> Self {
×
177
        Expr::Stretch(value)
×
178
    }
×
179
}
180

181
impl From<Index> for Expr {
182
    fn from(value: Index) -> Self {
×
183
        Expr::Index(Box::new(value))
×
184
    }
×
185
}
186

187
impl From<Box<Index>> for Expr {
188
    fn from(value: Box<Index>) -> Self {
×
189
        Expr::Index(value)
×
190
    }
×
191
}
192

193
/// Root base class of all nodes in the expression tree.  The base case should never be
194
/// instantiated directly.
195
///
196
/// This must not be subclassed by users; subclasses form the internal data of the representation of
197
/// expressions, and it does not make sense to add more outside of Qiskit library code.
198
///
199
/// All subclasses are responsible for setting their ``type`` attribute in their ``__init__``, and
200
/// should not call the parent initializer."""
UNCOV
201
#[pyclass(
×
UNCOV
202
    eq,
×
UNCOV
203
    hash,
×
204
    subclass,
205
    frozen,
206
    name = "Expr",
207
    module = "qiskit._accelerate.circuit.classical.expr"
UNCOV
208
)]
×
209
#[derive(PartialEq, Clone, Copy, Debug, Hash)]
210
pub struct PyExpr(pub ExprKind); // ExprKind is used for fast extraction from Python
211

212
#[pymethods]
213
impl PyExpr {
214
    /// Call the relevant ``visit_*`` method on the given :class:`ExprVisitor`.  The usual entry
215
    /// point for a simple visitor is to construct it, and then call :meth:`accept` on the root
216
    /// object to be visited.  For example::
217
    ///
218
    ///     expr = ...
219
    ///     visitor = MyVisitor()
220
    ///     visitor.accept(expr)
221
    ///
222
    /// Subclasses of :class:`Expr` should override this to call the correct virtual method on the
223
    /// visitor.  This implements double dispatch with the visitor."""
224
    /// return visitor.visit_generic(self)
225
    fn accept<'py>(
×
226
        slf: PyRef<'py, Self>,
×
227
        visitor: &Bound<'py, PyAny>,
×
228
    ) -> PyResult<Bound<'py, PyAny>> {
×
229
        visitor.call_method1(intern!(visitor.py(), "visit_generic"), (slf,))
×
230
    }
×
231
}
232

233
/// The expression's kind, used internally during Python instance extraction to avoid
234
/// `isinstance` checks.
235
#[repr(u8)]
236
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
237
pub enum ExprKind {
238
    Unary,
239
    Binary,
240
    Value,
241
    Var,
242
    Cast,
243
    Stretch,
244
    Index,
245
}
246

247
impl<'py> IntoPyObject<'py> for Expr {
248
    type Target = PyAny;
249
    type Output = Bound<'py, PyAny>;
250
    type Error = PyErr;
251

252
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
5,082✔
253
        match self {
5,082✔
254
            Expr::Unary(u) => u.into_bound_py_any(py),
142✔
255
            Expr::Binary(b) => b.into_bound_py_any(py),
1,046✔
256
            Expr::Cast(c) => c.into_bound_py_any(py),
48✔
257
            Expr::Value(v) => v.into_bound_py_any(py),
1,462✔
258
            Expr::Var(v) => v.into_bound_py_any(py),
2,254✔
259
            Expr::Stretch(s) => s.into_bound_py_any(py),
110✔
260
            Expr::Index(i) => i.into_bound_py_any(py),
20✔
261
        }
262
    }
5,082✔
263
}
264

265
impl<'py> FromPyObject<'py> for Expr {
266
    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
29,206✔
267
        let expr: PyRef<'_, PyExpr> = ob.downcast()?.borrow();
29,206✔
268
        match expr.0 {
11,798✔
269
            ExprKind::Unary => Ok(Expr::Unary(Box::new(ob.extract()?))),
198✔
270
            ExprKind::Binary => Ok(Expr::Binary(Box::new(ob.extract()?))),
1,664✔
271
            ExprKind::Value => Ok(Expr::Value(ob.extract()?)),
3,960✔
272
            ExprKind::Var => Ok(Expr::Var(ob.extract()?)),
5,724✔
273
            ExprKind::Cast => Ok(Expr::Cast(Box::new(ob.extract()?))),
154✔
274
            ExprKind::Stretch => Ok(Expr::Stretch(ob.extract()?)),
78✔
275
            ExprKind::Index => Ok(Expr::Index(Box::new(ob.extract()?))),
20✔
276
        }
277
    }
29,206✔
278
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc