/// # Summary
        /// Uses a quantum function to get a solution string from the QAOA that relies on the current values of beta and gamma vectors.
        ///To get a reasonable estimate for the expectation value of a Hamiltonian that encodes the problem, we run the QAOA many times and calculate the expectation based on solutions obtained.
        ///If the expectation of the Hamiltonian is smaller than our current best, we update our best solution to the current solution. The solution vector for the current best solution is the mode of boolean strings that we obtained from the QAOA.
        ///
        /// # Input
        /// ## bigfreeParamsVector
        /// Beta and gamma vectors concatenated.
        ///
        /// # Output
        /// The expected value of a Hamiltonian that we calculated in this run.
        public Double CalculateObjectiveFunction(double[] bigfreeParamsVector)
        {
            Utils.FreeParamsVector freeParamsVector   = Utils.ConvertVectorIntoHalves(bigfreeParamsVector);
            double        hamiltonianExpectationValue = 0;
            List <bool[]> allSolutionVectors          = new List <bool[]>();

            var beta  = new QArray <Double>(freeParamsVector.beta);
            var gamma = new QArray <Double>(freeParamsVector.gamma);

            Utils.PrintCurrentBetaGamma(beta, gamma);

            var oneLocalHamiltonianCoefficients = new QArray <Double>(problemInstance.oneLocalHamiltonianCoefficients);
            var twoLocalHamiltonianCoefficients = new QArray <Double>(problemInstance.twoLocalHamiltonianCoefficients);

            using (var qsim = new QuantumSimulator())
            {
                for (int i = 0; i < numberOfIterations; i++)
                {
                    IQArray <bool> result = RunQaoa.Run(qsim, problemInstance.problemSizeInBits, beta, gamma, oneLocalHamiltonianCoefficients, twoLocalHamiltonianCoefficients, p).Result;
                    allSolutionVectors.Add(result.ToArray());
                    string solutionVector   = Utils.GetBoolStringFromBoolArray(result.ToArray());
                    double hamiltonianValue = EvaluateHamiltonian(solutionVector);
                    hamiltonianExpectationValue += (hamiltonianValue / numberOfIterations);
                }
            }

            UpdateBestSolution(hamiltonianExpectationValue, allSolutionVectors, freeParamsVector);
            Utils.PrintCurrentBestSolution(this.bestHamiltonianValue, this.bestVector);

            return(hamiltonianExpectationValue);
        }
 /// # Summary
 /// Updates the currently best solution if a new solution is better.
 ///
 /// # Input
 /// ## hamiltonianExpectationValue
 /// Expectation value of a Hamiltonian.
 /// ## allSolutionVectors
 /// A vector of all binary solutions that were found by a QAOA.
 /// ## freeParamsVector
 /// A vector of beta and gamma coefficients.
 private void UpdateBestSolution(double hamiltonianExpectationValue, List <bool[]> allSolutionVectors, Utils.FreeParamsVector freeParamsVector)
 {
     if (hamiltonianExpectationValue < this.bestHamiltonianValue)
     {
         String mostProbableSolutionVectorTemp = Utils.GetModeFromBoolList(allSolutionVectors);
         bestHamiltonianValue = hamiltonianExpectationValue;
         bestVector           = mostProbableSolutionVectorTemp;
         bestBeta             = freeParamsVector.beta;
         bestGamma            = freeParamsVector.gamma;
     }
 }