docs: def rabi_oscillations(sampler: sim.Sampler,
                        qubit: devices.GridQubit,
                        max_angle: float = 2 * np.pi,
                        *,
                        repetitions: int = 1000,
                        num_points: int = 200) -> RabiResult:
      """Runs a Rabi oscillation experiment.
  
      Rotates a qubit around the x-axis of the Bloch sphere by a sequence of Rabi
      angles evenly spaced between 0 and max_angle. For each rotation, repeat
      the circuit a number of times and measure the average probability of the
      qubit being in the |1> state.
  
      Args:
          sampler: The quantum engine or simulator to run the circuits.
          qubit: The qubit under test.
          max_angle: The final Rabi angle in radians.
          repetitions: The number of repetitions of the circuit for each Rabi
              angle.
          num_points: The number of Rabi angles.
  
      Returns:
          A RabiResult object that stores and plots the result.
      """
      theta = sympy.Symbol('theta')
      circuit = circuits.Circuit.from_ops(ops.X(qubit) ** theta)
      circuit.append(ops.measure(qubit, key='z'))
      sweep = study.Linspace(key='theta', start=0.0, stop=max_angle / np.pi,
                             length=num_points)
      results = sampler.run_sweep(circuit, params=sweep, repetitions=repetitions)
      angles = np.linspace(0.0, max_angle, num_points)
      excited_state_probs = np.zeros(num_points)
      for i in range(num_points):
          excited_state_probs[i] = np.mean(results[i].measurements['z'])
  
      return RabiResult(angles, excited_state_probs)