-
Notifications
You must be signed in to change notification settings - Fork 58
Germ Selection Gate Penalty #666
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
base: develop
Are you sure you want to change the base?
Conversation
Add a new penalty option for germ selection to penalize the number of times specified gates are used. Currently only implemented for CompactEVD mode for greedy search.
Add a new option for penalizing the number of applications of a specified gate in germ selection.
Finish adding in the plumbing for the gate penalties, and add in new unit tests for the gate penalty and op penalties.
Fix the new unit tests added for testing germ selection penalties.
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.
Left several comments. Happy to iterate on them a bit!
| randomization_strength=1e-2, score_func='all', | ||
| op_penalty=0.0, l1_penalty=0.0, num_nongauge_params=None, | ||
| float_type=_np.cdouble): | ||
| float_type=_np.cdouble, gate_penalty=None): |
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.
Type annotation please :)
| gate_score = 0.0 | ||
| if gate_penalty is not None: | ||
| assert germ_list is not None, 'Must specify `germ_list` when using `gate_penalty`.' | ||
| for gate, penalty_value in gate_penalty.items(): | ||
| #loop through each ckt in the fiducial list. | ||
| for germ in germ_list: | ||
| #alternative approach using the string | ||
| #representation of the ckt. | ||
| num_gate_instances= germ.str.count(gate) | ||
| gate_score += num_gate_instances*penalty_value |
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 text appears three times in this file. Please break it out into a helper function.
| class GermSelectionPenaltyTester(GermSelectionData, BaseCase): | ||
| def setUp(self): | ||
| super(GermSelectionData, self).setUp() | ||
|
|
||
| def test_op_penalty_greedy(self): | ||
|
|
||
| germs_no_penalty_cevd = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='compactEVD', algorithm='greedy') | ||
|
|
||
| germs_penalty_cevd = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='compactEVD', algorithm='greedy', | ||
| algorithm_kwargs={'op_penalty':.1}) | ||
|
|
||
| assert count_ops(germs_no_penalty_cevd) > count_ops(germs_penalty_cevd) | ||
|
|
||
|
|
||
| def test_gate_penalty_greedy(self): | ||
| germs_no_penalty_alljac = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='all-Jac', algorithm='greedy') | ||
| germs_no_penalty_cevd = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='compactEVD', algorithm='greedy') | ||
|
|
||
| germs_penalty_alljac = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='all-Jac', algorithm='greedy', | ||
| algorithm_kwargs={'gate_penalty':{'Gxpi2':.1}}) | ||
| germs_penalty_cevd = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='compactEVD', algorithm='greedy', | ||
| algorithm_kwargs={'gate_penalty':{'Gxpi2':.1}}) | ||
|
|
||
| assert count_gate(germs_no_penalty_alljac, 'Gxpi2') > count_gate(germs_penalty_alljac, 'Gxpi2') | ||
| assert count_gate(germs_no_penalty_cevd, 'Gxpi2') > count_gate(germs_penalty_cevd, 'Gxpi2') | ||
|
|
||
| def test_gate_penalty_grasp(self): | ||
| germs_gate_penalty_grasp = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='all-Jac', algorithm='grasp', | ||
| algorithm_kwargs={'gate_penalty':{'Gxpi2':.2}, 'seed':1234, 'iterations':1}) | ||
|
|
||
| germs_default_grasp = germsel.find_germs(self.target_model, randomize=True, seed=1234, candidate_germ_counts={7:'all upto'}, | ||
| assume_real=True, float_type=np.double, mode='all-Jac', algorithm='grasp', | ||
| algorithm_kwargs={'seed':1234, 'iterations':1}) | ||
|
|
||
| assert count_gate(germs_gate_penalty_grasp, 'Gxpi2') < count_gate(germs_default_grasp, 'Gxpi2') |
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.
The keyword arguments here are hard to read. I suggest something like the following.
class GermSelectionPenaltyTester(GermSelectionData, BaseCase):
common_kwargs : dict[str, Any] = dict(
randomize=True, seed=1234, candidate_germ_counts={7:'all upto'},
assume_real=True, float_type=np.double, mode='compactEVD', algorithm='greedy'
)
def setUp(self):
super(GermSelectionData, self).setUp()
def test_op_penalty_greedy(self):
germs_no_penalty_cevd = germsel.find_germs(self.target_model, **self.common_kwargs)
germs_penalty_cevd = germsel.find_germs(self.target_model, **self.common_kwargs, algorithm_kwargs={'op_penalty':.1})
assert count_ops(germs_no_penalty_cevd) > count_ops(germs_penalty_cevd)
def test_gate_penalty_greedy(self):
kwargs = self.common_kwargs.copy()
kwargs.pop('mode')
germs_no_penalty_alljac = germsel.find_germs(self.target_model, **kwargs, mode='all-Jac')
germs_no_penalty_cevd = germsel.find_germs(self.target_model, **kwargs, mode='compactEVD')
germs_penalty_alljac = germsel.find_germs(
self.target_model, **kwargs, mode='all-Jac', algorithm_kwargs={'gate_penalty':{'Gxpi2':.1}}
)
germs_penalty_cevd = germsel.find_germs(
self.target_model, **kwargs, mode='compactEVD', algorithm_kwargs={'gate_penalty':{'Gxpi2':.1}}
)
assert count_gate(germs_no_penalty_alljac, 'Gxpi2') > count_gate(germs_penalty_alljac, 'Gxpi2')
assert count_gate(germs_no_penalty_cevd, 'Gxpi2') > count_gate(germs_penalty_cevd, 'Gxpi2')
def test_gate_penalty_grasp(self):
kwargs = self.common_kwargs.copy()
kwargs['mode'] = 'all-Jac'
kwargs['algorithm'] = 'grasp'
germs_gate_penalty_grasp = germsel.find_germs(
self.target_model, **kwargs, algorithm_kwargs={'seed':1234, 'iterations':1, 'gate_penalty':{'Gxpi2':.2}}
)
germs_default_grasp = germsel.find_germs(
self.target_model, **kwargs, algorithm_kwargs={'seed':1234, 'iterations':1}
)
assert count_gate(germs_gate_penalty_grasp, 'Gxpi2') < count_gate(germs_default_grasp, 'Gxpi2')| num_ops = 0 | ||
| for circuit in circuits: | ||
| num_ops+= circuit.num_gates | ||
| return num_ops |
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.
Missing blank line at EOF
|
@coreyostrove, is this is an appropriate PR to look into the complex-dtype issues with compactEVD germ selection #659? It's fine with me if you'd like to handle that separately, but I figured I'd point out the chance. |
We recently ran into a scenario where it was desirable to perform germ selection in a manner which minimized the number of applications of a particularly expensive gate operation. To support that sort of use case this PR adds a new
algorithm_kwargoption calledgate_penaltyforfind_germswhich is compatible with the 'greedy' and 'grasp' search algorithms which allows a user to specify and additional penalty factors for the number of instances of particular gates in a candidate germ set. Also included are some additional unit tests for both this new gate penalty as well as tests for the existingop_penaltyoption (which penalized the total number of gate operations overall).