-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Rename ActOnArgs to SimulationState #5293
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
95-martin-orion
left a comment
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 will be a big help in parsing these types! How are we doing in terms of remaining "act_on_arg" / "actonarg" appearances in Cirq after this PR?
Thanks also for keeping this nice for review. For the follow-up PRs, I think the appropriate way to handle them is to point them at this branch - that way I can approve those and get the whole sequence merged into master without a big breaking change.
| return self.mapped_circuit(deep=False).all_operations() | ||
|
|
||
| def _act_on_(self, args: 'cirq.OperationTarget') -> bool: | ||
| def _act_on_(self, args: 'cirq.SimulationStateBase') -> bool: |
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.
A minor nit: renaming args to state (or similar) throughout this PR would be nice.
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 did for local variables. For function arguments I expect there'll need to be a deprecation cycle. Though I guess for private / protocol methods that doesn't apply.
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 went ahead and updated it for the protocol handlers. I think I'm going to have to take a rain check on the rest as there's just too much to fit in one PR, and args is way too common to find and replace. The main one is _create_partial_act_on_args, which is a bit complicated and will require a deprecation cycle and probably some dynamic hasattr or inspect stuff to be backwards compatible. Beyond that, misc stuff here and there, mostly in sim.. Was there anything else in particular you wanted me to deal with in this PR?
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.
Good call on the deprecation cycle. We should keep an eye on it even for the protocol methods, since they have a bad habit of being called from outside of Cirq.
I don't see anything else urgent to deal with in this PR - moving to #5296 for further review.
|
Ready to go once #5296 is merged into this. |
Add old ActOnArgs, deprecated
|
@95-martin-orion looks like that approach still caused git to change from recognizing renamed files to big unrelated deletes and adds. But I guess that's fine since we're done reviewing. |
For posterity, the renaming view of this PR can be seen by only looking at commits up to 7486e3b (link). |
|
Automerge cancelled: A required status check is not present. Missing statuses: ['Build docs', 'Build protos', 'Changed files test', 'Coverage check', 'Doc test', 'Format check', 'Lint check', 'Misc check', 'Notebook formatting', 'Pytest MacOS (3.7)', 'Pytest MacOS (3.8)', 'Pytest MacOS (3.9)', 'Pytest Ubuntu (3.7)', 'Pytest Ubuntu (3.8)', 'Pytest Ubuntu (3.9)', 'Pytest Windows (3.7)', 'Pytest Windows (3.8)', 'Pytest Windows (3.9)', 'Type check', 'Typescript lint check', 'Typescript tests', 'Typescript tests coverage'] |
|
@95-martin-orion kick me |
| TSimulationState = TypeVar('TSimulationState', bound='cirq.SimulationState') | ||
|
|
||
|
|
||
| class SimulationStateBase(Generic[TSimulationState], metaclass=abc.ABCMeta): |
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.
@daxfohl Can you please explain what's going on with the generics here? For example:
-
SimulationStateBase(Generic[TSimulationState], metaclass=abc.ABCMeta)is a generic of typeTSimulationState= TypeVar('TSimulationState', bound='cirq.SimulationState')` and -
SimulationState(SimulationStateBase, Generic[TState], metaclass=abc.ABCMeta)derives fromSimulationStateBaseand is also a generic of typeTypeVar('TState', bound='cirq.QuantumStateRepresentation')
Why is TSimulationState used in SimulatorStateBase bound to SimulatorState and not SimulatorStateBase ? Why can we not use TSelfTarget in place of TSimulationState in the SimulationStateBase class? Is it because we want to allow __getitem__ and create_merged_state to potentially return a different type compared to TSelfTarget ?
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.
Thanks for asking. It's pretty challenging and I remember some idiosyncrasies of mypy getting in the way for a while.
So hierarchy: SimStateBase has two subclasses {SimState, SimProductState}.
SimState is abstract and has multiple subclasses: StateVectorSimState, DensityMatrixSimState, etc. Those are "dense" as in they have a single big state vector, density matrix, tableau, or whatever for all qubits in the simulation. TSimState is the generic constrained to a single SimState.
SimProductState is concrete and generic: SimProductState[TSimState]. It contains a qubit->TSimState mapping. It's a product state representation for whichever TSimState it contains, so it's smaller and faster when there's not full entanglement. I consider this a "final" class. (You can control whether a simulator uses a SimProductState or a single SimState, by the split_untangled_states flag in simulator constructors that support it).
SimStateBase is the superclass of them all. It is generic on TSimState, because there's an abstract function create_merged_state() -> TSimState that's there to give you the "dense" version of whatever your TSimState is. So in SimState, the implementation of that just returns self; in SimProductState it krons up all the values in its mapping and returns that. This is why SimStateBase is generic on TSimState, and why TSimState is bound to SimState: SimState is the "dense" representation. __getitem__ works similarly; the docstring should probably read "Gets the dense substate associated with the qubit" or something like that.
Then TSelfTarget is different because the copy of a SimProductState should return a SimProductState.
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.
And TState is separate. It is purely the quantum component. SimState contains not only the quantum component (density matrix, tableau, etc), but also the qubit->axis mapping, a prng, measurement records, etc. So that's why you see DensityMatrixSimState inherits SimState[DensityMatrixQuantumRepresentation].
In an ideal world we shouldn't even need DensityMatrixSimState etc as their own classes, and instead just have SimState be a generic final class that we use directly. However there are a lot of backwards compatibility issues and useful convenience methods preventing that. (Otherwise you'd end up needing to write code like result.get_merged_state().state.state.state_vector or something).
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.
Thanks, this is extremely helpful!
I think the fact that we are supporting SimulationProductState for any arbitrary TSimulationState is adding a lot of complexity to the type hierarchy. An alternative could have been to have
- A type Hierarchy for specifying simulation states as
Generic[TState]; i.e. what theSimulationStateclass is doing right now.SimulationStateBasewouldn't exist and the abstract base class for simulation states would beSimulationState. - Have a separate container type for dense vs sparse representation of states -- This container could maintain the
Dict[cirq.Qid, TSimulationState]. Based on the configurable parameter, a simulator would construct either a dense container or a sparse container for the specified simulation state type.
The fact that a container of simulation states (SimulationProductState) is also a simulation state is I think making the type hierarchy super complex. But given the Cirq 1.0 backwards compatibility constraints, I'm not sure if we can do anything about the situation at this point except improving documentation.
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.
Yes, that was our initial approach but that caused some backwards incompatibility at the time IIRC, so we went with subclassing. Probably could have revisited this before 1.0 but didn't think about it.
|
Note the other option is to push the "product state" functionality down to the quantum-state level rather than the simulation-state level. I actually think that would be the best approach (it maps better to what's physically happening). I investigated this approach before 1.0 in #5389, but my conclusion was that it would be a major project. |
* Rename ActOnArgs * Rename act_on_args locals and tests * Rename modules * coverage * coverage * TActOnArgs * change args to sim_state in _act_on_ impls * Add old ActOnArgs, deprecated Co-authored-by: Cirq Bot <craiggidney+github+cirqbot@google.com>
* Rename ActOnArgs * Rename act_on_args locals and tests * Rename modules * coverage * coverage * TActOnArgs * change args to sim_state in _act_on_ impls * Add old ActOnArgs, deprecated Co-authored-by: Cirq Bot <craiggidney+github+cirqbot@google.com>
Most of #5244. Will backfill the existing ActOnArgs classes in subsequent PR, as it will merge cleaner (here git detects the renamed file; if we do backfill here then git will see all new files). Will also need to rename a few methods like
_create_partial_act_on_argsin a future PR.