Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add ParameterExpression in Rust #13278

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

doichanj
Copy link
Contributor

@doichanj doichanj commented Oct 4, 2024

Summary

This is draft of ParameterExpression in Rust for #13267

Details and comments

I made symbolic algebra engine instead of using symengine to remove dependencies of conan.
The functionalities are limited compared to symengine but I'm implementing enough functions for ParameterExpression

[TO DOs]

  • Add python interface maybe in other structure like ParameterPy to keep Parameter structure independent from Python
  • Add complex number support (is it necessary ?) - Done
  • Add missing functions
  • Add more heuristics to simplify equation - Done
  • Add simplification of equation
  • Add test cases and documentation

@doichanj doichanj requested a review from a team as a code owner October 4, 2024 10:07
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Nov 8, 2024

Pull Request Test Coverage Report for Build 12024667837

Details

  • 0 of 1282 (0.0%) changed or added relevant lines in 3 files are covered.
  • 26 unchanged lines in 3 files lost coverage.
  • Overall coverage decreased (-1.3%) to 87.669%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/circuit/src/symbol_parser.rs 0 187 0.0%
crates/circuit/src/parameter.rs 0 195 0.0%
crates/circuit/src/symbol_expr.rs 0 900 0.0%
Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 92.2%
crates/qasm2/src/lex.rs 7 92.23%
crates/qasm2/src/parse.rs 18 96.69%
Totals Coverage Status
Change from base Build 12015226815: -1.3%
Covered Lines: 79397
Relevant Lines: 90564

💛 - Coveralls

@mtreinish
Copy link
Member

Add complex number support (is it necessary ?)

@Cryoris can confirm, but I think on main we don't have to worry about this for 2.0 since we're dropping pulse support. AFAIK the complex parameter binding and handling was only necessary for pulse expressions. But maybe there is a use case I'm overlooking.

@Cryoris
Copy link
Contributor

Cryoris commented Nov 12, 2024

For circuits, real is enough. But we currently also allow parameter expressions in the SparsePauliOp, where there's no restriction to real values. Beyond being more difficult to implement, complex number support doesn't come with a performance hit, does it?

@ShellyGarion ShellyGarion linked an issue Nov 27, 2024 that may be closed by this pull request
@1ucian0 1ucian0 added the Rust This PR or issue is related to Rust code in the repository label Dec 11, 2024
rhs : SymbolExpr,
}

impl Clone for SymbolExpr {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this separate Clone implementation? It looks like it would be the same as the standard Clone, but maybe I'm missing something. Or is this doing something specific to the Arc in Unary and Binary?

Value::Real(r) => r,
Value::Complex(c) => c.re,
}
None => 0.0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might not understand this fully, but if self is a plain Symbol then self.eval returns None and this the functions real/complex will return 0, right? But if I just have a plain Symbol with no value associated yet, then I would expect that I cannot query the real or complex parts, because they are not defined, no? (In which case I thought this might need to raise an error 🙂)

}
}

pub fn has_symbol(&self, param: String) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use &String or even &str here since we're only reading the value?

_ => false,
},
SymbolExpr::Unary(e) => e.expr.is_complex(),
SymbolExpr::Binary(e) => e.lhs.is_complex() || e.rhs.is_complex(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this get us into trouble in expressions like 1j * 1j, i.e. where LHS and RHS are complex but the expression is not? (Same question for is_real)

Comment on lines +1203 to +1210
match self.lhs.eval(recurse) {
Some(v) => lval = v,
None => return None,
}
match self.rhs.eval(recurse) {
Some(v) => rval = v,
None => return None,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make this a bit less typing by matching the tuple if you would like (no guarantees on the formatting 🙂)

Suggested change
match self.lhs.eval(recurse) {
Some(v) => lval = v,
None => return None,
}
match self.rhs.eval(recurse) {
Some(v) => rval = v,
None => return None,
}
match (self.lhs.eval(true), self.rhs.eval(true)) {
(Some(left), Some(right)) => {
lval = left;
rval = right;
}
_ => return None,
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Rust This PR or issue is related to Rust code in the repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Oxidize ParameterExpression
6 participants