-
Notifications
You must be signed in to change notification settings - Fork 2.6k
[Alternative] Move Parameter to Rust #14757
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
Conversation
-- 606 failing tests
- name conflicts - hash(2.3) == hash(ParamExpr(2.3)) - some error messages
This allows keeping track of which parameters are still in the expression, even though the expression is optimized. E.g. x*0 = 0, but x is still valid to bind.
- don't use UUID in to_string, only in string_id (using strings for comparisons should probably be avoided in future) - clippy - relax Python is-checks to eq-checks
this is rather a temporary solution, maybe we ought to disable string parsing in favor or a proper SymPy->parameter expression conversion
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 16633739615Details
💛 - Coveralls |
mainly removing some unnecessary clones, and fixing Hash for ParameterExpression
--- and just reconstruct the Py symbols from ParameterExpression.name_map
I ran some preliminary benchmarks comparing Qiskit v2.1.1 vs this and it seems this PR speeds things up a bit:
Note that the first benchmarks measures time to construct the circuit too, so the binding speedup is hidden a bit. |
Co-authored-by: "U-AzureAD\JUNDOI" doichan@jp.ibm.com
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This completes my first pass of review. Thanks to both you and @doichanj for all of this work.
Overall, this looks good to me. The one high-level question I've got concerns the split between PyParameterExpression
, ParameterExpression
, and SymbolExpr
. Am I correct in my understanding that the only reason to have a ParameterExpression
is so we have some place to maintain a name_map
? If not for this, I would think we could get away with just having PyParameterExpression
for Python and SymbolExpr
for Rust.
Yeah I also thought about this (in fact it's what I had initially). There's 2 reasons I added the
That being said -- the An advantage of not having |
mainly rm unused code and dangling comments
- dangling commented code - error for derivative
d2a233d
to
2a23689
Compare
Co-authored-by: Jun Doi <doichan@jp.ibm.com>
2a23689
to
5d336aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me now. I have one minor comment, but I don't think we need to hold this up.
For posterity, we talked offline about the idea of eliminating ParameterExpression
(and just keeping SymbolExpr
) and our conclusion was that SymbolExpr
is more of a Qiskit-independent symbol layer, and ParameterExpression
is the piece that wraps it with our extra domain-specific logic. I suggested that we might want to move SymbolExpr
to its own crate to avoid future coupling, but we've decided to defer that for a potential follow-up.
@@ -905,7 +900,7 @@ impl SymbolExpr { | |||
} | |||
|
|||
pub fn string_id(&self) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not a fan of calling this an "id" since it sounds like what gets returned is a simple ID of a constant length.
In the recently merged Qiskit#14757 a few docs lines were overindented. Newer versions of clippy detect this and raise a warning but the version we run in CI doesn't have this rule so this went uncaught. This commit fixes this small oversight so clippy is happy and the docs are properly formatted.
In the recently merged #14757 a few docs lines were overindented. Newer versions of clippy detect this and raise a warning but the version we run in CI doesn't have this rule so this went uncaught. This commit fixes this small oversight so clippy is happy and the docs are properly formatted.
* Split py and py-free methods * playing with Symbol as Parameter -- 606 failing tests * fix errors * about to start the mess * suite passing * PVE in Rust * start assign * add assign * dealing with unknown params and conflicts * an attempt at vector fixing * fix more tests - name conflicts - hash(2.3) == hash(ParamExpr(2.3)) - some error messages * implement name_map as track record This allows keeping track of which parameters are still in the expression, even though the expression is optimized. E.g. x*0 = 0, but x is still valid to bind. * The string debacle - don't use UUID in to_string, only in string_id (using strings for comparisons should probably be avoided in future) - clippy - relax Python is-checks to eq-checks * some housekeeping * implement _qpy_replay * implement sympify * fix copy/deepcopy * Implement pickle via QPY and Parameter.assign to return Parameter * fix template matching this is rather a temporary solution, maybe we ought to disable string parsing in favor or a proper SymPy->parameter expression conversion * fix rhs - lhs mixup * fix more tests on binding {x: 0*y} * fix last failing tests (see numeric(strict=False)) * clippy * a lot of docs * rename PyParameterExpression to ParameterExpression * Thou shan't fake hyperrefs * proper split: (Py)ParameterExpression * rm pyclass from Symbol * TODO's and no more RwLock - rm Arc<RwLock<..>> for inner, since expressions are immutable and not shared, this is not needed - address a bunch of todos, that include - rm rsub/rdiv/rpow - introduce try_to_value and _to_symbol - make internal data private * First round of review comments mainly removing some unnecessary clones, and fixing Hash for ParameterExpression * rm `name_map` from PyParameterExpression --- and just reconstruct the Py symbols from ParameterExpression.name_map * Fix vector element parsing Co-authored-by: "U-AzureAD\JUNDOI" doichan@jp.ibm.com * finish 1st review round mainly rm unused code and dangling comments * left over review comments - dangling commented code - error for derivative * rename SymbolExpr::display --> repr Co-authored-by: Jun Doi <doichan@jp.ibm.com> --------- Co-authored-by: Jun Doi <doichan@jp.ibm.com>
* Split py and py-free methods * playing with Symbol as Parameter -- 606 failing tests * fix errors * about to start the mess * suite passing * PVE in Rust * start assign * add assign * dealing with unknown params and conflicts * an attempt at vector fixing * fix more tests - name conflicts - hash(2.3) == hash(ParamExpr(2.3)) - some error messages * implement name_map as track record This allows keeping track of which parameters are still in the expression, even though the expression is optimized. E.g. x*0 = 0, but x is still valid to bind. * The string debacle - don't use UUID in to_string, only in string_id (using strings for comparisons should probably be avoided in future) - clippy - relax Python is-checks to eq-checks * some housekeeping * implement _qpy_replay * implement sympify * fix copy/deepcopy * Implement pickle via QPY and Parameter.assign to return Parameter * fix template matching this is rather a temporary solution, maybe we ought to disable string parsing in favor or a proper SymPy->parameter expression conversion * fix rhs - lhs mixup * fix more tests on binding {x: 0*y} * fix last failing tests (see numeric(strict=False)) * clippy * a lot of docs * rename PyParameterExpression to ParameterExpression * Thou shan't fake hyperrefs * proper split: (Py)ParameterExpression * rm pyclass from Symbol * TODO's and no more RwLock - rm Arc<RwLock<..>> for inner, since expressions are immutable and not shared, this is not needed - address a bunch of todos, that include - rm rsub/rdiv/rpow - introduce try_to_value and _to_symbol - make internal data private * First round of review comments mainly removing some unnecessary clones, and fixing Hash for ParameterExpression * rm `name_map` from PyParameterExpression --- and just reconstruct the Py symbols from ParameterExpression.name_map * Fix vector element parsing Co-authored-by: "U-AzureAD\JUNDOI" doichan@jp.ibm.com * finish 1st review round mainly rm unused code and dangling comments * left over review comments - dangling commented code - error for derivative * rename SymbolExpr::display --> repr Co-authored-by: Jun Doi <doichan@jp.ibm.com> --------- Co-authored-by: Jun Doi <doichan@jp.ibm.com>
* Split py and py-free methods * playing with Symbol as Parameter -- 606 failing tests * fix errors * about to start the mess * suite passing * PVE in Rust * start assign * add assign * dealing with unknown params and conflicts * an attempt at vector fixing * fix more tests - name conflicts - hash(2.3) == hash(ParamExpr(2.3)) - some error messages * implement name_map as track record This allows keeping track of which parameters are still in the expression, even though the expression is optimized. E.g. x*0 = 0, but x is still valid to bind. * The string debacle - don't use UUID in to_string, only in string_id (using strings for comparisons should probably be avoided in future) - clippy - relax Python is-checks to eq-checks * some housekeeping * implement _qpy_replay * implement sympify * fix copy/deepcopy * Implement pickle via QPY and Parameter.assign to return Parameter * fix template matching this is rather a temporary solution, maybe we ought to disable string parsing in favor or a proper SymPy->parameter expression conversion * fix rhs - lhs mixup * fix more tests on binding {x: 0*y} * fix last failing tests (see numeric(strict=False)) * clippy * a lot of docs * rename PyParameterExpression to ParameterExpression * Thou shan't fake hyperrefs * proper split: (Py)ParameterExpression * rm pyclass from Symbol * TODO's and no more RwLock - rm Arc<RwLock<..>> for inner, since expressions are immutable and not shared, this is not needed - address a bunch of todos, that include - rm rsub/rdiv/rpow - introduce try_to_value and _to_symbol - make internal data private * First round of review comments mainly removing some unnecessary clones, and fixing Hash for ParameterExpression * rm `name_map` from PyParameterExpression --- and just reconstruct the Py symbols from ParameterExpression.name_map * Fix vector element parsing Co-authored-by: "U-AzureAD\JUNDOI" doichan@jp.ibm.com * finish 1st review round mainly rm unused code and dangling comments * left over review comments - dangling commented code - error for derivative * rename SymbolExpr::display --> repr Co-authored-by: Jun Doi <doichan@jp.ibm.com> --------- Co-authored-by: Jun Doi <doichan@jp.ibm.com>
In the recently merged Qiskit#14757 a few docs lines were overindented. Newer versions of clippy detect this and raise a warning but the version we run in CI doesn't have this rule so this went uncaught. This commit fixes this small oversight so clippy is happy and the docs are properly formatted.
Summary
Based on the excellent work in #14207, this is PR implements a slightly alternative approach to porting the
ParameterExpression
to Rust, based on discussions with @doichanj, @kevinhartman and @mtreinish. The main differences are outlined below. We should compare both approaches and check which one is closer to what we'd like. Of course the efforts could also be merged.Details and comments
This PR does not supersede #14207, it is merely a slightly different approach and it's majority is based on #14207. The main differences are:
ParameterExpression
,Parameter
andParameterVectorElement
fully in Rust, without a Python-side class. This is done to reduce the code base and maintainer effort. This could also improve performance as we need less back and forth between the Rust and Python boundaries.Symbol
in the symbolic expression engine itself, rather than keep a separate map of symbols to their UUID. This is done to couple the UUID and symbol closer instead of relying on a third object to make this connection.Things that could make this PR better (maybe in this PR or a follow up)
ParameterExpression
andPyParameterExpression
for clearer Python split. Doing this would allow us to make the expression'sname_map
useSymbol
s directly. Let's think about how we want to use this from C!Symbol
not apyclass
(probably easy to do, just didn't get to it yet)Symbol
and have anIndexedSymbol
, like in Move Parameter classes from Python to Rust #14207? Answer: no, it won't reduce memory footprint, so we don't bother now.try to remove string parsingthis will be a follow upsome other bits I surely did forget and am unaware ofCo-authored-by: "U-AzureAD\JUNDOI" doichan@jp.ibm.com