def test_nested_assignment_partial_bind(self): """Test nested schedule with call instruction. Inline the schedule and partially bind parameters.""" context = AlignEquispaced(duration=self.context_dur) subroutine = pulse.ScheduleBlock(alignment_context=context) subroutine += pulse.Play(self.parametric_waveform1, self.d1) nested_block = pulse.ScheduleBlock() nested_block += pulse.Call(subroutine=subroutine) test_obj = pulse.ScheduleBlock() test_obj += nested_block test_obj = inline_subroutines(test_obj) value_dict = {self.context_dur: 1000, self.dur1: 200, self.ch1: 1} visitor = ParameterSetter(param_map=value_dict) assigned = visitor.visit(test_obj) ref_context = AlignEquispaced(duration=1000) ref_subroutine = pulse.ScheduleBlock(alignment_context=ref_context) ref_subroutine += pulse.Play( pulse.Gaussian(200, self.amp1_1 + self.amp1_2, 50), pulse.DriveChannel(1)) ref_nested_block = pulse.ScheduleBlock() ref_nested_block += ref_subroutine ref_obj = pulse.ScheduleBlock() ref_obj += ref_nested_block self.assertEqual(assigned, ref_obj)
def test_append_an_instruction_to_empty_block_inplace(self): """Test append instructions to an empty block with inplace.""" block = pulse.ScheduleBlock() block.append(pulse.Play(self.test_waveform0, self.d0), inplace=True) self.assertEqual(block.blocks[0], pulse.Play(self.test_waveform0, self.d0))
def test_overlapping_on_expression_assigment_to_zero(self): """Test constant*zero expression conflict.""" schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(self.qubit)) schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(2*self.qubit)) with self.assertRaises(PulseError): schedule.assign_parameters({self.qubit: 0})
def test_append_an_instruction_to_empty_block_sugar(self): """Test append instructions to an empty block with syntax sugar.""" block = pulse.ScheduleBlock() block += pulse.Play(self.test_waveform0, self.d0) self.assertEqual(block.blocks[0], pulse.Play(self.test_waveform0, self.d0))
def test_overlapping_on_assignment(self): """Test that assignment will catch against existing instructions.""" schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(1)) schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(self.qubit)) with self.assertRaises(PulseError): schedule.assign_parameters({self.qubit: 1})
def test_overlapping_pulses(self): """Test that an error is still raised when overlapping instructions are assigned.""" schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(self.qubit)) with self.assertRaises(PulseError): schedule |= pulse.Play(pulse.Waveform([0.5, 0.5, 0.5, 0.5]), DriveChannel(self.qubit))
def test_append_an_instruction_to_empty_block(self): """Test append instructions to an empty block.""" block = pulse.ScheduleBlock() block = block.append(pulse.Play(self.test_waveform0, self.d0)) self.assertEqual(block.instructions[0], pulse.Play(self.test_waveform0, self.d0))
def test_assemble_sample_pulse(self): """Test that the pulse lib and qobj instruction can be paired up.""" schedule = pulse.Schedule() schedule += pulse.Play(pulse.SamplePulse([0.1] * 16, name='test0'), pulse.DriveChannel(0), name='test1') schedule += pulse.Play(pulse.SamplePulse([0.1] * 16, name='test1'), pulse.DriveChannel(0), name='test2') schedule += pulse.Play(pulse.SamplePulse([0.5] * 16, name='test0'), pulse.DriveChannel(0), name='test1') qobj = assemble(schedule, qobj_header=self.header, qubit_lo_freq=self.default_qubit_lo_freq, meas_lo_freq=self.default_meas_lo_freq, schedule_los=[], **self.config) validate_qobj_against_schema(qobj) test_dict = qobj.to_dict() experiment = test_dict['experiments'][0] inst0_name = experiment['instructions'][0]['name'] inst1_name = experiment['instructions'][1]['name'] inst2_name = experiment['instructions'][2]['name'] pulses = {} for item in test_dict['config']['pulse_library']: pulses[item['name']] = item['samples'] self.assertTrue( all(name in pulses for name in [inst0_name, inst1_name, inst2_name])) # Their pulses are the same self.assertEqual(inst0_name, inst1_name) self.assertTrue(np.allclose(pulses[inst0_name], [0.1] * 16)) self.assertTrue(np.allclose(pulses[inst2_name], [0.5] * 16))
def test_assign_parameter_to_subroutine_parameter(self): """Test that assign parameter objects to parameter of subroutine.""" param1 = Parameter("amp") waveform = pulse.library.Constant(duration=100, amp=param1) param_sub1 = Parameter("amp") param_sub2 = Parameter("phase") subroutine = pulse.Schedule() subroutine += pulse.Play(waveform, DriveChannel(0)) reference = deepcopy(subroutine).assign_parameters({param1: 0.1 * np.exp(0.5j)}) main_prog = pulse.Schedule() pdict = {param1: param_sub1 * np.exp(1j * param_sub2)} main_prog += pulse.instructions.Call(subroutine, value_dict=pdict) # parameter is overwritten by parameters self.assertEqual(len(main_prog.parameters), 2) target = deepcopy(main_prog).assign_parameters({param_sub1: 0.1, param_sub2: 0.5}) result = inline_subroutines(target) if not HAS_SYMENGINE: self.assertEqual(result, reference) else: # Because of simplification differences between sympy and symengine when # symengine is used we get 0.1*exp(0.5*I) instead of the evaluated # 0.0877582562 + 0.0479425539*I resulting in a failure. When # symengine is installed manually build the amplitude as a complex to # avoid this. reference = pulse.Schedule() waveform = pulse.library.Constant(duration=100, amp=0.1 * cmath.exp(0.5j)) reference += pulse.Play(waveform, DriveChannel(0)) self.assertEqual(result, reference)
def setUp(self): super().setUp() self.test_blocks = [ pulse.Play(self.test_waveform0, self.d0), pulse.Play(self.test_waveform1, self.d1), pulse.Delay(50, self.d0), pulse.Play(self.test_waveform1, self.d0), ]
def test_overlapping_on_multiple_assignment(self): """Test that assigning one qubit then another raises error when overlapping.""" qubit2 = Parameter('q2') schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(self.qubit)) schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(qubit2)) schedule.assign_parameters({qubit2: 2}) with self.assertRaises(PulseError): schedule.assign_parameters({self.qubit: 2})
def test_merging_upon_assignment(self): """Test that schedule can match instructions on a channel.""" schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(1)) schedule = schedule.insert(4, pulse.Play(pulse.Waveform([1, 1, 1, 1]), DriveChannel(self.qubit))) schedule.assign_parameters({self.qubit: 1}) self.assertEqual(schedule.ch_duration(DriveChannel(1)), 8) self.assertEqual(schedule.channels, (DriveChannel(1),))
def test_get_assigend_duration(self): """Test duration is correctly evaluated.""" block = pulse.ScheduleBlock() block += pulse.Play(self.test_par_waveform0, self.d0) block += pulse.Play(self.test_waveform0, self.d0) block = block.assign_parameters({self.dur0: 300}) self.assertEqual(block.duration, 400)
def test_instruction_out_of_order_equispaced(self): """Test equality is False if two blocks have instructions in different order.""" block1 = pulse.ScheduleBlock(alignment_context=self.equispaced_context) block1 += pulse.Play(self.test_waveform0, self.d0) block1 += pulse.Play(self.test_waveform0, self.d1) block2 = pulse.ScheduleBlock(alignment_context=self.equispaced_context) block2 += pulse.Play(self.test_waveform0, self.d1) block2 += pulse.Play(self.test_waveform0, self.d0) self.assertNotEqual(block1, block2)
def test_parameter_attribute_play(self): """Test the ``parameter`` attributes.""" inst = pulse.Play( pulse.Gaussian(self.dur, self.amp, self.sigma), pulse.DriveChannel(self.qubit) ) self.assertTrue(inst.is_parameterized()) self.assertSetEqual(inst.parameters, {self.dur, self.amp, self.sigma, self.qubit}) inst = pulse.Play(pulse.Gaussian(self.dur, 0.1, self.sigma), pulse.DriveChannel(self.qubit)) self.assertTrue(inst.is_parameterized()) self.assertSetEqual(inst.parameters, {self.dur, self.sigma, self.qubit})
def test_instrution_in_oder_but_different_node(self): """Test equality is False if two blocks have different instructions.""" block1 = pulse.ScheduleBlock(alignment_context=self.left_context) block1 += pulse.Play(self.test_waveform0, self.d0) block1 += pulse.Play(self.test_waveform1, self.d1) block2 = pulse.ScheduleBlock(alignment_context=self.left_context) block2 += pulse.Play(self.test_waveform0, self.d0) block2 += pulse.Play(self.test_waveform0, self.d1) self.assertNotEqual(block1, block2)
def test_instruction_in_order_func(self): """Test equality is True if two blocks have instructions in same order.""" block1 = pulse.ScheduleBlock(alignment_context=self.func_context) block1 += pulse.Play(self.test_waveform0, self.d0) block1 += pulse.Play(self.test_waveform0, self.d1) block2 = pulse.ScheduleBlock(alignment_context=self.func_context) block2 += pulse.Play(self.test_waveform0, self.d0) block2 += pulse.Play(self.test_waveform0, self.d1) self.assertEqual(block1, block2)
def test_get_parameter(self): """Test that get parameter by name.""" param1 = Parameter('amp') param2 = Parameter('amp') schedule = pulse.Schedule() waveform1 = pulse.library.Constant(duration=1280, amp=param1) waveform2 = pulse.library.Constant(duration=1280, amp=param2) schedule += pulse.Play(waveform1, DriveChannel(0)) schedule += pulse.Play(waveform2, DriveChannel(1)) self.assertEqual(len(schedule.get_parameters('amp')), 2)
def stretch_sub_sched(sim_pulse_array, factor): ''' Input: A set of pulses happening at the same time (sim = simultaneous) and factor to be stretched by Output: A schedule consisting of the stretched pulses ''' sub_sched = qiskit.pulse.Schedule() for instruc in sim_pulse_array: #anything except shift phase if (isinstance(instruc, Play)): if (isinstance(instruc.pulse, Drag)): drag = instruc.pulse ## param = {"duration": self.duration, "amp": self.amp, "sigma": self.sigma, "width": self.width} param = drag.parameters duration = int(factor * param['duration']) sigma = (factor * param['sigma']) #stretching the drag pulse s_pulse = Drag(duration, param['amp'] / factor, sigma, param['beta']) channel = instruc.channels[0] sub_sched = sub_sched.append(pulse.Play(s_pulse, channel)) elif (isinstance(instruc.pulse, GaussianSquare)): gauss = instruc.pulse ## param = {"duration": self.duration, "amp": self.amp, "sigma": self.sigma, "width": self.width} param = gauss.parameters #print('------Old Param') #print(param) #stretching the drag pulse duration = get_closest_multiple_of_16(factor * param['duration']) sigma = (factor * param['sigma']) width = get_closest_multiple_of_16(factor * param['width']) s_pulse = GaussianSquare(duration, param['amp'] / factor, sigma, width) #print('------new Param') #print('Duration') #print(str(duration) + ' '+ str(param['amp']/factor) + ' '+ str(sigma) + ' '+ str(width)) #print(param) channel = instruc.channels[0] sub_sched = sub_sched.append(pulse.Play(s_pulse, channel)) #if not acquire elif (not isinstance(instruc, Acquire)): sub_sched += instruc else: sub_sched += instruc return sub_sched
def test_sequential_alignment(self): """Test sequential alignment context.""" block = pulse.ScheduleBlock(alignment_context=self.sequential_context) block = block.append(pulse.Play(self.test_waveform0, self.d0)) block = block.append(pulse.Play(self.test_waveform1, self.d1)) ref_sched = pulse.Schedule() ref_sched = ref_sched.insert(0, pulse.Play(self.test_waveform0, self.d0)) ref_sched = ref_sched.insert(100, pulse.Play(self.test_waveform1, self.d1)) self.assertScheduleEqual(block, ref_sched)
def test_set_parameter_to_complex_schedule(self): """Test get parameters from complicated schedule.""" test_block = deepcopy(self.test_sched) value_dict = { self.amp1_1: 0.1, self.amp1_2: 0.2, self.amp2: 0.3, self.amp3: 0.4, self.dur1: 100, self.dur2: 125, self.dur3: 150, self.ch1: 0, self.ch2: 2, self.ch3: 4, self.phi1: 1.0, self.phi2: 2.0, self.phi3: 3.0, self.meas_dur: 300, self.mem1: 3, self.reg1: 0, self.context_dur: 1000, } visitor = ParameterSetter(param_map=value_dict) assigned = visitor.visit(test_block) # create ref schedule subroutine = pulse.ScheduleBlock(alignment_context=AlignLeft()) subroutine += pulse.ShiftPhase(1.0, pulse.DriveChannel(0)) subroutine += pulse.Play(pulse.Gaussian(100, 0.3, 25), pulse.DriveChannel(0)) sched = pulse.Schedule() sched += pulse.ShiftPhase(3.0, pulse.DriveChannel(4)) ref_obj = pulse.ScheduleBlock(alignment_context=AlignEquispaced(1000), name="long_schedule") ref_obj += subroutine ref_obj += pulse.ShiftPhase(2.0, pulse.DriveChannel(2)) ref_obj += pulse.Play(pulse.Gaussian(125, 0.3, 25), pulse.DriveChannel(2)) ref_obj += pulse.Call(sched) ref_obj += pulse.Play(pulse.Gaussian(150, 0.4, 25), pulse.DriveChannel(4)) ref_obj += pulse.Acquire(300, pulse.AcquireChannel(0), pulse.MemorySlot(3), pulse.RegisterSlot(0)) self.assertEqual(assigned, ref_obj)
def test_overlapping_on_multiple_assignment(self): """Test that assigning one qubit then another raises error when overlapping.""" param_idx1 = Parameter("q1") param_idx2 = Parameter("q2") schedule = pulse.Schedule() schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), pulse.DriveChannel(param_idx1)) schedule |= pulse.Play(pulse.Waveform([1, 1, 1, 1]), pulse.DriveChannel(param_idx2)) schedule.assign_parameters({param_idx1: 2}) with self.assertRaises(PulseError): schedule.assign_parameters({param_idx2: 2})
def _waveform_loader(self, program: Union[pulse.Waveform, pulse.ParametricPulse]): """Load Waveform instance. This function is sub-routine of py:method:`load_program`. Args: program: `Waveform` to draw. """ chart = Chart(parent=self) # add waveform data fake_inst = pulse.Play(program, types.WaveformChannel()) inst_data = types.PulseInstruction( t0=0, dt=self.device.dt, frame=types.PhaseFreqTuple(phase=0, freq=0), inst=fake_inst, is_opaque=program.is_parameterized()) for gen in self.generator['waveform']: obj_generator = partial(gen, formatter=self.formatter, device=self.device) for data in obj_generator(inst_data): chart.add_data(data) self.charts.append(chart)
def test_parametrized_frame_change(self): """Test generating waveforms that are parameterized. Parametrized phase should be ignored when calculating waveform frame. This is due to phase modulated representation of waveforms, i.e. we cannot calculate the phase factor of waveform if the phase is unbound. """ param = circuit.Parameter('phase') test_fc1 = pulse.ShiftPhase(param, pulse.DriveChannel(0)) test_fc2 = pulse.ShiftPhase(1.57, pulse.DriveChannel(0)) test_waveform = pulse.Play(pulse.Constant(10, 0.1), pulse.DriveChannel(0)) ch_events = events.ChannelEvents(waveforms={0: test_waveform}, frames={0: [test_fc1, test_fc2]}, channel=pulse.DriveChannel(0)) # waveform frame pulse_inst = list(ch_events.get_waveforms())[0] self.assertFalse(pulse_inst.is_opaque) self.assertEqual(pulse_inst.frame.phase, 1.57) # framechange pulse_inst = list(ch_events.get_frame_changes())[0] self.assertTrue(pulse_inst.is_opaque) self.assertEqual(pulse_inst.frame.phase, param + 1.57)
def amp_sweep(self, drive_durations, amp_times, sched_cx, init_state): duration_schedules = [] for cr_duration in drive_durations: sched = pulse.Schedule() sched_cx_copy = copy.deepcopy(sched_cx) if (init_state == 1) or (init_state == 2): sched += self.sched_x if init_state == 2: sched += pulse.Play(self.pi_pulse_12, DriveChannel(self.ctr_q2)) new_cx = pulse.Schedule() for index, instruction in enumerate(sched_cx_copy.instructions): child = instruction[1] if type(child.pulse) != pulse_lib.GaussianSquare: new_cx += child else: mini_pulse = child.pulse mini_pulse._width = mini_pulse.width * cr_duration / mini_pulse.duration mini_pulse.duration = cr_duration mini_pulse._amp = amp_times * mini_pulse._amp new_cx = new_cx.insert(new_cx.duration, child) sched |= new_cx << sched.duration sched |= self.sched_meas_tar_q << sched.duration # 駆動パルスの後に測定をシフト duration_schedules.append(sched) return duration_schedules
def test_gen_iqx_latex_waveform_name_x90(self): """Test gen_iqx_latex_waveform_name with x90 waveform.""" iqx_pulse = pulse.Waveform(samples=[0, 0, 0, 0], name="X90p_d0_1234567") play = pulse.Play(iqx_pulse, pulse.DriveChannel(0)) inst_data = create_instruction(play, 0, 0, 0, 0.1) obj = waveform.gen_ibmq_latex_waveform_name(inst_data, formatter=self.formatter, device=self.device)[0] # type check self.assertEqual(type(obj), drawings.TextData) # data check self.assertListEqual(obj.channels, [pulse.DriveChannel(0)]) self.assertEqual(obj.text, "X90p_d0_1234567") self.assertEqual(obj.latex, r"{\rm X}(\pi/2)") # style check ref_style = { "zorder": self.formatter["layer.annotate"], "color": self.formatter["color.annotate"], "size": self.formatter["text_size.annotate"], "va": "center", "ha": "center", } self.assertDictEqual(obj.styles, ref_style)
def test_gen_iqx_latex_waveform_name_x90(self): """Test gen_iqx_latex_waveform_name with x90 waveform.""" iqx_pulse = pulse.Waveform(samples=[0, 0, 0, 0], name='X90p_d0_1234567') play = pulse.Play(iqx_pulse, pulse.DriveChannel(0)) inst_data = self.create_instruction(play, 0, 0, 0, 0.1) obj = generators.gen_iqx_latex_waveform_name(inst_data)[0] # type check self.assertEqual(type(obj), drawing_objects.TextData) # data check self.assertEqual(obj.channel, pulse.DriveChannel(0)) self.assertEqual(obj.text, 'X90p_d0_1234567') self.assertEqual(obj.latex, r'{\rm X}(\frac{\pi}{2})') # style check ref_style = { 'zorder': self.style['formatter.layer.annotate'], 'color': self.style['formatter.color.annotate'], 'size': self.style['formatter.text_size.annotate'], 'va': 'center', 'ha': 'center' } self.assertDictEqual(obj.styles, ref_style)
def test_gen_iqx_latex_waveform_name_x90(self): """Test gen_iqx_latex_waveform_name with x90 waveform.""" iqx_pulse = pulse.Waveform(samples=[0, 0, 0, 0], name='X90p_d0_1234567') play = pulse.Play(iqx_pulse, pulse.DriveChannel(0)) inst_data = create_instruction(play, 0, 0, 0, 0.1) obj = waveform.gen_ibmq_latex_waveform_name(inst_data, formatter=self.formatter, device=self.device)[0] # type check self.assertEqual(type(obj), drawings.TextData) # data check self.assertListEqual(obj.channels, [pulse.DriveChannel(0)]) self.assertEqual(obj.text, 'X90p_d0_1234567') self.assertEqual(obj.latex, r'{\rm X}(\pi/2)') # style check ref_style = { 'zorder': self.formatter['layer.annotate'], 'color': self.formatter['color.annotate'], 'size': self.formatter['text_size.annotate'], 'va': 'center', 'ha': 'center' } self.assertDictEqual(obj.styles, ref_style)
def test_invalid_parametric_pulses(self): """Test that invalid parameters are still checked upon assignment.""" schedule = pulse.Schedule() waveform = pulse.library.Constant(duration=1280, amp=2 * self.amp) schedule += pulse.Play(waveform, DriveChannel(0)) with self.assertRaises(PulseError): waveform.assign_parameters({self.amp: 0.6})
def test_assign_parameter_to_subroutine_parameter(self): """Test that assign parameter objects to parameter of subroutine.""" param1 = Parameter('amp') waveform = pulse.library.Constant(duration=100, amp=param1) param_sub1 = Parameter('amp') param_sub2 = Parameter('phase') subroutine = pulse.Schedule() subroutine += pulse.Play(waveform, DriveChannel(0)) reference = deepcopy(subroutine).assign_parameters( {param1: 0.1 * np.exp(1j * 0.5)}) main_prog = pulse.Schedule() pdict = {param1: param_sub1 * np.exp(1j * param_sub2)} main_prog += pulse.instructions.Call(subroutine, value_dict=pdict) # parameter is overwritten by parameters self.assertEqual(len(main_prog.parameters), 2) target = deepcopy(main_prog).assign_parameters({ param_sub1: 0.1, param_sub2: 0.5 }) self.assertEqual(inline_subroutines(target), reference)