Repository: Qiskit/qiskit

Issue:
Documentation for inputs to an Estimator instance disagree with implementation
### Environment

- **Qiskit Terra version**:  0.37.1
 


### What is happening?

The documentation in [BaseEstimator](https://github.com/Qiskit/qiskit-terra/blob/c318725d679b0eb3aa8874fb9755fa0567c5e94b/qiskit/primitives/base_estimator.py#L114) says that when calling an instance four arguments are supplied. The third and fourth are parameters and parameter values.

But the implementation and the example are different. They take only three arguments. Parameter values are passed, but not parameters. Instead, in the call method, the parameters are retrieved from the circuit.

The above is in the file for `BaseEstimator`, but the doc string and example contained therein refer to `Estimator`. It appears online in the API reference section.
 

### How can we reproduce the issue?

Read the source

### What should happen?

Documented interface should agree with implementation.


### Any suggestions?

_No response_


Discussion:

Resolving patch:
diff --git a/qiskit/primitives/base_estimator.py b/qiskit/primitives/base_estimator.py
--- a/qiskit/primitives/base_estimator.py
+++ b/qiskit/primitives/base_estimator.py
@@ -19,44 +19,35 @@
 
 Estimator class estimates expectation values of quantum circuits and observables.
 
-An estimator object is initialized with multiple quantum circuits and observables
-and users can specify pairs of quantum circuits and observables
-to estimate the expectation values.
-
-An estimator is initialized with the following elements.
+An estimator is initialized with an empty parameter set. The estimator is used to
+create a :class:`~qiskit.providers.JobV1`, via the
+:meth:`qiskit.primitives.Estimator.run()` method. This method is called
+with the following parameters
 
 * quantum circuits (:math:`\psi_i(\theta)`): list of (parameterized) quantum circuits
-  (a list of :class:`~qiskit.circuit.QuantumCircuit`))
-
-* observables (:math:`H_j`): a list of :class:`~qiskit.quantum_info.SparsePauliOp`.
-
-The estimator is called with the following inputs.
-
-* circuits: a list of the quantum circuits.
+  (a list of :class:`~qiskit.circuit.QuantumCircuit` objects).
 
-* observables: a list of the observables.
+* observables (:math:`H_j`): a list of :class:`~qiskit.quantum_info.SparsePauliOp`
+  objects.
 
 * parameter values (:math:`\theta_k`): list of sets of values
-  to be bound to the parameters of the quantum circuits.
-  (list of list of float)
+  to be bound to the parameters of the quantum circuits
+  (list of list of float).
 
-The output is an :class:`~qiskit.primitives.EstimatorResult` which contains a list of
-expectation values plus optional metadata like confidence intervals for the estimation.
+The method returns a :class:`~qiskit.providers.JobV1` object, calling
+:meth:`qiskit.providers.JobV1.result()` yields the
+a list of expectation values plus optional metadata like confidence intervals for
+the estimation.
 
 .. math::
 
     \langle\psi_i(\theta_k)|H_j|\psi_i(\theta_k)\rangle
 
-
-The estimator object is expected to be ``close()`` d after use or
-accessed inside "with" context
-and the objects are called with parameter values and run options
-(e.g., ``shots`` or number of shots).
-
-Here is an example of how estimator is used.
+Here is an example of how the estimator is used.
 
 .. code-block:: python
 
+    from qiskit.primitives import Estimator
     from qiskit.circuit.library import RealAmplitudes
     from qiskit.quantum_info import SparsePauliOp
 
@@ -74,22 +65,16 @@
     estimator = Estimator()
 
     # calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
-    result = estimator.run([psi1], [H1], [theta1]).result()
-    print(result)
-
-    # calculate [ <psi2(theta2)|H2|psi2(theta2)> ]
-    result2 = estimator.run([psi2], [H1], [theta2]).result()
-    print(result2)
-
-    # calculate [ <psi1(theta1)|H2|psi1(theta1)>, <psi1(theta1)|H3|psi1(theta1)> ]
-    result3 = estimator.run([psi1, psi1], [H2, H3], [theta1]*2).result()
-    print(result3)
+    job = estimator.run([psi1], [H1], [theta1])
+    job_result = job.result() # It will block until the job finishes.
+    print(f"The primitive-job finished with result {job_result}"))
 
     # calculate [ <psi1(theta1)|H1|psi1(theta1)>,
     #             <psi2(theta2)|H2|psi2(theta2)>,
     #             <psi1(theta3)|H3|psi1(theta3)> ]
-    result4 = estimator.run([psi1, psi2, psi1], [H1, H2, H3], [theta1, theta2, theta3]).result()
-    print(result4)
+    job2 = estimator.run([psi1, psi2, psi1], [H1, H2, H3], [theta1, theta2, theta3])
+    job_result = job2.result()
+    print(f"The primitive-job finished with result {job_result}")
 """
 from __future__ import annotations
 
diff --git a/qiskit/primitives/base_sampler.py b/qiskit/primitives/base_sampler.py
--- a/qiskit/primitives/base_sampler.py
+++ b/qiskit/primitives/base_sampler.py
@@ -16,71 +16,60 @@
 
 Sampler class calculates probabilities or quasi-probabilities of bitstrings from quantum circuits.
 
-A sampler is initialized with the following elements.
+A sampler is initialized with an empty parameter set. The sampler is used to
+create a :class:`~qiskit.providers.JobV1`, via the :meth:`qiskit.primitives.Sampler.run()`
+method. This method is called with the following parameters
 
 * quantum circuits (:math:`\psi_i(\theta)`): list of (parameterized) quantum circuits.
-  (a list of :class:`~qiskit.circuit.QuantumCircuit`))
-
-The sampler is run with the following inputs.
-
-* circuits: a list of QuantumCircuit objects to evaluate.
+  (a list of :class:`~qiskit.circuit.QuantumCircuit` objects)
 
 * parameter values (:math:`\theta_k`): list of sets of parameter values
   to be bound to the parameters of the quantum circuits.
   (list of list of float)
 
-The output is a :class:`~qiskit.primitives.SamplerResult` which contains probabilities
-or quasi-probabilities of bitstrings,
+The method returns a :class:`~qiskit.providers.JobV1` object, calling
+:meth:`qiskit.providers.JobV1.result()` yields a :class:`~qiskit.primitives.SamplerResult`
+object, which contains probabilities or quasi-probabilities of bitstrings,
 plus optional metadata like error bars in the samples.
 
-The sampler object is expected to be closed after use or
-accessed within "with" context
-and the objects are called with parameter values and run options
-(e.g., ``shots`` or number of shots).
-
 Here is an example of how sampler is used.
 
 .. code-block:: python
 
+    from qiskit.primitives import Sampler
     from qiskit import QuantumCircuit
     from qiskit.circuit.library import RealAmplitudes
 
+    # a Bell circuit
     bell = QuantumCircuit(2)
     bell.h(0)
     bell.cx(0, 1)
     bell.measure_all()
 
-    # executes a Bell circuit
-    sampler = Sampler()
-    result = sampler.run(circuits=[bell]).result()
-    print([q.binary_probabilities() for q in result.quasi_dists])
-
-    # executes three Bell circuits
-    sampler = Sampler()
-    result = sampler.run([bell, bell, bell]).result()
-    print([q.binary_probabilities() for q in result.quasi_dists])
-
-    # parameterized circuit
+    # two parameterized circuits
     pqc = RealAmplitudes(num_qubits=2, reps=2)
     pqc.measure_all()
     pqc2 = RealAmplitudes(num_qubits=2, reps=3)
     pqc2.measure_all()
 
     theta1 = [0, 1, 1, 2, 3, 5]
-    theta2 = [1, 2, 3, 4, 5, 6]
-    theta3 = [0, 1, 2, 3, 4, 5, 6, 7]
+    theta2 = [0, 1, 2, 3, 4, 5, 6, 7]
 
+    # initialization of the sampler
     sampler = Sampler()
-    result = sampler.run([pqc, pqc, pqc2], [theta1, theta2, theta3]).result()
-
-    # result of pqc(theta1)
-    print(result.quasi_dists[0].binary_probabilities())
-
-    # result of pqc(theta2)
-    print(result.quasi_dists[1].binary_probabilities())
 
-    # result of pqc2(theta3)
-    print(result.quasi_dists[2].binary_probabilities())
+    # Sampler runs a job on the Bell circuit
+    job = sampler.run(circuits=[bell], parameter_values=[[]], parameters=[[]])
+    job_result = job.result()
+    print([q.binary_probabilities() for q in job_result.quasi_dists])
+
+    # Sampler runs a job on the parameterized circuits
+    job2 = sampler.run(
+        circuits=[pqc, pqc2],
+        parameter_values=[theta1, theta2],
+        parameters=[pqc.parameters, pqc2.parameters])
+    job_result = job2.result()
+    print([q.binary_probabilities() for q in job_result.quasi_dists])
 """
 from __future__ import annotations
 


Test patch: