Skip to content

Conversation

@chriseclectic
Copy link
Collaborator

Summary

  • This PR updates the initialization of composite experiments ExperimentData to be handled entirely by the CompositeAnalysis class, this is intended to make it more robust when re-running on loaded data.
  • Adds an analysis kwarg to CompositeExperiment, BatchExperiment and ParallelExperiment to allow a user to supply a custom CompositeAnalysis instance. This may be used by subclass experiments.

Details and comments

When initializing the child experiment data during analysis specific properties of the parent data will be copied to the child data including tags, share level, and auto save, so that to an end user the behavior of setting this attributes is unchanged by this PR.

Copy link
Collaborator

@nkanazawa1989 nkanazawa1989 left a comment

Choose a reason for hiding this comment

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

I almost copied my comments from #721 but did more careful review. Overall instantiating the child experiment data at the beginning of analysis routine looks nice. Seems like this makes the analysis more robust to the complicated situation, such as nested composite experiment.

# Store the indices of the added child data in metadata
experiment_data.metadata["component_child_index"] = component_index

def _initialize_component_data(self, experiment_data: ExperimentData) -> List[ExperimentData]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Having initialize_component_data and initialize_child_data are really confusing for developers. As far as I can understand, there is no physical component_data member in this class (indeed this is deprecated attribute), and what this method is doing looks like initializing the data container for the experiment data of child experiment. What about renaming this to _create_empty_containers? Probably removing this method and just merging the logic here to _initialize_child_data is also fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

_initialize_component_data creates the empty component ExperimentData objects for analysis, but it doesn't save them as child data. This needs to be separate to _initialize_child_data for the follow up PR for combining results where you want to generate these, analyse them, but not necessarily save them as child experiments.

# and auto save from the parent experiment data
component_expdata = []
for i, _ in enumerate(self._analyses):
subdata = ExperimentData(backend=experiment_data.backend)
Copy link
Collaborator

Choose a reason for hiding this comment

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

How does this work if composite analysis is nested? Probably we need instance check of analysis and do recursive call of initialize method when composite analysis subclass is found.

Copy link
Collaborator Author

@chriseclectic chriseclectic Mar 23, 2022

Choose a reason for hiding this comment

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

Arbitrary nesting is fine. The point of doing it this way is that the analysis of each component is independent, so when the component analysis is run on the sub-experiment, if it is itself a composite experiment it will then go through this same initialization and for that component and its children.

self._experiments = experiments
self._num_experiments = len(experiments)
analysis = CompositeAnalysis([exp.analysis for exp in self._experiments])
if analysis is None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need instance check. If user provides custom analysis that directly inherits from the base analysis, the mechanism to instantiate child container is missing there.

# added to the component experiment data containers
metadata = experiment_data.metadata
num_components = len(self._analyses)
experiment_types = metadata.get("component_types", [None] * num_components)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we retrieve old composite analysis class from the experiment db?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Old data can still be loaded and analyzed, since old data will have the child_data already initialized (and have hence have "component_child_index" metadata field) this bit will be skipped.

# Return list of experiment data containers for each component experiment
# containing the marginalied data from the composite experiment
component_exp_data = self._component_experiment_data(experiment_data)
component_expdata = self._component_experiment_data(experiment_data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should _component_experiment_data be renamed now because component_experiment_data attribute has been already renamed in the ExperimentData?

# Return list of experiment data containers for each component experiment
# containing the marginalied data from the composite experiment
component_exp_data = self._component_experiment_data(experiment_data)
component_expdata = self._component_experiment_data(experiment_data)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should _component_experiment_data be renamed now because component_experiment_data attribute has been already renamed in the ExperimentData?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This really is the component experiments experiment data though, so i think it's the appropriate name in this class

Also add to Batch and Parallel Experiment. This is intended to make it easier to attach a custom analysis class to subclasses of these experiments.
Copy link
Collaborator

@nkanazawa1989 nkanazawa1989 left a comment

Choose a reason for hiding this comment

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

LGTM

start_index = len(experiment_data.child_data())
for i, subdata in enumerate(child_components):
experiment_data.add_child_data(subdata)
component_index.append(start_index + i)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is because we can add new child data on top of previous data?

@chriseclectic chriseclectic merged commit 3b16c3d into qiskit-community:main Mar 23, 2022
nkanazawa1989 pushed a commit to nkanazawa1989/qiskit-experiments that referenced this pull request Mar 28, 2022
…nity#720)

* Update initialization of CompositeAnalysis

* Add analysis kwarg to CompositeExpereiments

Also add to Batch and Parallel Experiment. This is intended to make it easier to attach a custom analysis class to subclasses of these experiments.
@chriseclectic chriseclectic added Changelog: New Feature Include in the "Added" section of the changelog Changelog: API Change Include in the "Changed" section of the changelog labels Apr 25, 2022
paco-ri pushed a commit to paco-ri/qiskit-experiments that referenced this pull request Jul 11, 2022
…nity#720)

* Update initialization of CompositeAnalysis

* Add analysis kwarg to CompositeExpereiments

Also add to Batch and Parallel Experiment. This is intended to make it easier to attach a custom analysis class to subclasses of these experiments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changelog: API Change Include in the "Changed" section of the changelog Changelog: New Feature Include in the "Added" section of the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants