code: def expectation_from_sampling(pyquil_program: Program,
                                marked_qubits: List[int],
                                qc: QuantumComputer,
                                samples: int) -> float:
      
      program = Program()
      ro = program.declare('ro', 'BIT', max(marked_qubits) + 1)
      program += pyquil_program
      program += [MEASURE(qubit, r) for qubit, r in zip(list(range(max(marked_qubits) + 1)), ro)]
      program.wrap_in_numshots_loop(samples)
      executable = qc.compile(program)
      bitstring_samples = qc.run(executable)
      bitstring_tuples = list(map(tuple, bitstring_samples))
  
      freq = Counter(bitstring_tuples)
  
      # perform weighted average
      expectation = 0
      for bitstring, count in freq.items():
          bitstring_int = int("".join([str(x) for x in bitstring[::-1]]), 2)
          if parity_even_p(bitstring_int, marked_qubits):
              expectation += float(count) / samples
          else:
              expectation -= float(count) / samples
      return expectation
docs: Calculation of Z_{i} at marked_qubits
  
      Given a wavefunctions, this calculates the expectation value of the Zi
      operator where i ranges over all the qubits given in marked_qubits.
  
      :param pyquil_program: pyQuil program generating some state
      :param marked_qubits: The qubits within the support of the Z pauli
                            operator whose expectation value is being calculated
      :param qc: A QuantumComputer object.
      :param samples: Number of bitstrings collected to calculate expectation
                      from sampling.
      :returns: The expectation value as a float.