{"action":"created","comment":{"url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/comments/227179167","pull_request_review_id":167153225,"id":227179167,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyNzE3OTE2Nw==","diff_hunk":"@@ -0,0 +1,805 @@\n+#   Licensed under the Apache License, Version 2.0 (the \"License\");\n+#   you may not use this file except in compliance with the License.\n+#   You may obtain a copy of the License at\n+#\n+#       http://www.apache.org/licenses/LICENSE-2.0\n+#\n+#   Unless required by applicable law or agreed to in writing, software\n+#   distributed under the License is distributed on an \"AS IS\" BASIS,\n+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+#   See the License for the specific language governing permissions and\n+#   limitations under the License.\n+\n+\"\"\"\n+Classes for Bayesian estimators for quantum phase estimation.\n+Estimators described in arXiv:1809.09697 (in particular in App.C and App.C.1)\n+\"\"\"\n+import warnings\n+import numpy\n+from numpy import cos, sin, pi\n+from scipy import sparse, optimize\n+from openfermion.config import EQ_TOLERANCE\n+\n+\n+class FourierProbabilityDist(object):\n+    \"\"\"\n+    Stores a estimate of multiple phases in the form arXiv:1809.09697 App.C.\n+    In particular, stores the Fourier representation as a sum of sine and\n+    cosine waves (Eq. (C1)), and provides methods for manipulation of these.\n+    \"\"\"\n+\n+    def __init__(self,\n+                 amplitude_guess=None,\n+                 amplitude_vars=None,\n+                 num_vectors=1,\n+                 num_freqs=1000,\n+                 max_n=1,\n+                 vector_guess=None):\n+        \"\"\"\n+        Args:\n+            amplitude_guess (numpy array or list):\n+                estimates for amplitudes of different\n+                eigenstates in the initial state.\n+            amplitude_vars (numpy array or list): variance on the amplitude estimates\n+            num_vectors (int): number of phases to estimate\n+            num_freqs (int): number of frequencies in Fourier representation.\n+            max_n (int): maximum number of unitary evolutions before measurement.\n+                dictates how many matrices for updates are made and stored.\n+            vector_guess (numpy array): a prior estimate of the phases. If none,\n+                assumes flat.\n+\n+        Raises:\n+            ValueError: if prior distribution does not have required shape.\n+            ValueError: if insufficient amplitude guesses are given.\n+            ValueError: if starting amplitudes do not break symmetry.\n+        \"\"\"\n+\n+        # Store size data\n+        self._num_vectors = num_vectors\n+        self._num_freqs = num_freqs\n+\n+        if amplitude_guess is None:\n+            amplitude_guess = [1]\n+        if amplitude_vars is None:\n+            amplitude_vars = [[1]]\n+\n+        # Store prior information\n+        if vector_guess is not None and (\n+                num_vectors != vector_guess.shape[1]\n+                or 2*num_freqs+1 != vector_guess.shape[0]):\n+            raise ValueError('''Prior distribution of phases has shape {},\n+                required shape is {}'''.format(\n+                    vector_guess.shape, (2*num_freqs+1, num_vectors)))\n+\n+        self._vector_guess = vector_guess\n+\n+        if num_vectors != len(amplitude_guess):\n+            raise ValueError('''I need {} amplitudes, but you have\n+                given me {}.'''.format(num_vectors, len(amplitude_guess)))\n+\n+        self._amplitude_guess = amplitude_guess\n+        self._amplitude_vars = amplitude_vars\n+\n+        if any([numpy.isclose(self._amplitude_guess[j],\n+                              self._amplitude_guess[j+1])\n+                for j in range(num_vectors - 1)]):\n+            raise ValueError('''Starting amplitudes must be different.''')\n+\n+        # Store max_n\n+        self._max_n = max_n\n+\n+        # Set un-created variables to be made elsewhere in the class to None\n+        self._jacobian = None\n+        self._amplitude_estimates = None\n+        self._fourier_vectors = None\n+\n+        # Create matrices for multiplication\n+        self._make_matrices()\n+        self._make_projector()\n+        self.reset()\n+\n+    def reset(self):\n+        \"\"\"\n+        Resets the distribution.\n+        \"\"\"\n+        if self._vector_guess is not None:\n+            self._fourier_vectors = numpy.array(self._vector_guess)\n+        else:\n+            # Initialize probability distributions\n+            self._fourier_vectors = numpy.zeros((self._num_freqs*2+1,\n+                                                 self._num_vectors))\n+            for j in range(self._num_vectors):\n+                self._fourier_vectors[0, j] = 1\n+\n+        # Initialize p_vec with some information to break the symmetry\n+        self._p_vecs = [numpy.array(self._amplitude_guess)]\n+        self._amplitude_estimates = numpy.array(self._amplitude_guess)\n+        self._inv_covar_mat = numpy.linalg.inv(\n+            numpy.array(self._amplitude_vars))\n+\n+    def get_real_dist(self, x_vec=numpy.linspace(-pi, pi, 101)):\n+        \"\"\"\n+        Generates the real distribution over a sequence of points\n+\n+        Args:\n+            x_vec (numpy array or list): the points at which the distribution is generated\n+        Returns:\n+            y_vecs (list): the value of the distributions at the given x points.\n+        \"\"\"\n+\n+        # Init storage to return\n+        y_vecs = []\n+\n+        for j in range(self._num_vectors):\n+\n+            # Get vector and evaluate corresponding function\n+            # at the chosen set of points\n+            vector = self._fourier_vectors[:, j]\n+            y_vec = [self._make_dist(vector, theta) for theta in x_vec]\n+\n+            # Store and plot data\n+            y_vecs.append(y_vec)\n+\n+        return y_vecs\n+\n+    def _holevo_centers(self, vectors=None):\n+        \"\"\"\n+        Gets the Holevo average phase from a distribution.\n+        Args:\n+            vectors (numpy array): vectors to calculate the average of. If None,\n+                defaults to the vectors stored in the class.\n+        Returns:\n+            centers (numpy array): the corresponding average angle of the\n+                distribution.\n+        \"\"\"\n+        if vectors is None:\n+            vectors = self._fourier_vectors\n+\n+        centers = numpy.angle(vectors[2, :] + 1j*vectors[1, :])\n+        return centers\n+\n+    def _holevo_variances(self, vectors=None, maxvar=4*numpy.pi**2/12):\n+        \"\"\"\n+        Gets the Holevo variance from a distribution\n+\n+        Args:\n+            vectors (numpy array): Fourier vectors to calculate the variance of.\n+                If none, defaults to the vectors stored in the class.\n+            maxvar (float): The maximum allowed variance. Defaults to the\n+                maximum of a uniform distribution on [-pi,pi].\n+        Returns:\n+            variances (list): The Holevo variances of each vector.\n+        \"\"\"\n+        variances = []\n+\n+        if vectors is None:\n+            vectors = self._fourier_vectors\n+\n+        for j in range(self._num_vectors):\n+            if (vectors[2, j]**2 + vectors[1, j]**2) == 0:\n+\n+                variances.append(maxvar)\n+\n+            else:\n+                variances.append(min(\n+                    maxvar,\n+                    4 / (vectors[2, j]**2+vectors[1, j]**2) - 1))\n+        return variances\n+\n+    def _make_matrices(self):\n+        \"\"\"\n+        Function to make the matrices that define multiplication\n+        by sin(theta) and cos(theta). We store these as sparse matrices\n+        in CSR format, and initialize them in (row,col,data) format.\n+        We assume here that self.max_n is less than self.num_freqs.\n+        \"\"\"\n+\n+        # self._matrices[n][a] contains matrix M^a(n+1)\n+        # following our paper\n+        self._matrices = []\n+\n+        for index in range(1, self._max_n+1):\n+\n+            # We generate the matrices ourselves in\n+            # COO format, and then create a\n+            # CSR matrix directly\n+\n+            cos_matrix, sin_matrix = self._make_matrix(index)\n+\n+            # Append to list\n+            self._matrices.append([cos_matrix, sin_matrix])\n+\n+    def _make_matrix(self, nrot):\n+        \"\"\"\n+        Makes matrices that sends a Fourier representation of p(phi)\n+        to the Fourier representation of cos^2(n*phi/2+beta/2)*p(phi).\n+\n+        See App. C in arXiv:1809.09697\n+\n+        Args:\n+            nrot (n): the number of rotations n in the above formula.\n+        Returns:\n+            cos_matrix (scipy.sparse.csr_matrix) matrix for multiplication\n+                by cos(phi)\n+            sin_matrix (scipy.sparse.csr_matrix) matrix for multiplication\n+                by sin(phi)\n+        \"\"\"\n+\n+        # Initialize with terms for when j = 0\n+        data_cos = [2]\n+        row_ind_cos = [2*nrot]\n+        col_ind_cos = [0]\n+\n+        data_sin = [-2]\n+        row_ind_sin = [2*nrot-1]\n+        col_ind_sin = [0]\n+\n+        # First do terms when j < n\n+        for j in range(1, nrot):\n+\n+            data_cos += [1, 1, -1, 1]\n+            row_ind_cos += [2*j+2*nrot-1, 2*j+2*nrot, 2*nrot-2*j-1, 2*nrot-2*j]\n+            col_ind_cos += [2*j-1, 2*j, 2*j-1, 2*j]\n+\n+            data_sin += [1, -1, -1, -1]\n+            row_ind_sin += [2*j+2*nrot, 2*j+2*nrot-1, 2*nrot-2*j, 2*nrot-2*j-1]\n+            col_ind_sin += [2*j-1, 2*j, 2*j-1, 2*j]\n+\n+        # Next do terms when j = n\n+        data_cos += [1, 1, 1]\n+        row_ind_cos += [4*nrot-1, 0, 4*nrot]\n+        col_ind_cos += [2*nrot-1, 2*nrot, 2*nrot]\n+\n+        data_sin += [-1, 1, -1]\n+        row_ind_sin += [0, 4*nrot, 4*nrot-1]\n+        col_ind_sin += [2*nrot-1, 2*nrot-1, 2*nrot]\n+\n+        # Finish with terms when j > n\n+        for j in range(nrot+1, self._num_freqs+1):\n+\n+            data_cos += [1, 1]\n+            row_ind_cos += [2*j-2*nrot-1, 2*j-2*nrot]\n+            col_ind_cos += [2*j-1, 2*j]\n+\n+            data_sin += [-1, 1]\n+            row_ind_sin += [2*j-2*nrot, 2*j-2*nrot-1]\n+            col_ind_sin += [2*j-1, 2*j]\n+\n+            if j + nrot <= self._num_freqs:\n+\n+                data_cos += [1, 1]\n+                row_ind_cos += [2*j+2*nrot-1, 2*j+2*nrot]\n+                col_ind_cos += [2*j-1, 2*j]\n+\n+                data_sin += [1, -1]\n+                row_ind_sin += [2*j+2*nrot, 2*j+2*nrot-1]\n+                col_ind_sin += [2*j-1, 2*j]\n+\n+        # Make sparse matrices\n+        cos_matrix = sparse.csr_matrix(\n+            (data_cos, (row_ind_cos, col_ind_cos)))\n+        sin_matrix = sparse.csr_matrix(\n+            (data_sin, (row_ind_sin, col_ind_sin)))\n+\n+        return cos_matrix, sin_matrix\n+\n+    def _vector_product(self, vectors, round_data):\n+        \"\"\"\n+        Calculates cos^2(n*phi/2+beta/2)P(phi) for an input\n+        n, beta and P(phi).\n+\n+        Args:\n+            vectors (numpy array): the input vectors to be multiplied\n+\n+            round_data (dict): data about this round in the experiment.\n+                in particular, round data needs 'num_rotations',\n+                'final_rotation', and 'measurement'.\n+\n+        Returns:\n+            updated vectors: the vector representation\n+                of P_{k,beta}(m|phi_j)P_{prior}(phi_j) for each\n+                input vector P_{prior}(phi_j)\n+        \"\"\"\n+\n+        # Extract the pieces we want from the round_data\n+        beta = round_data.final_rotation\n+        meas = round_data.measurement\n+        nrot = round_data.num_rotations\n+\n+        # Get the matrices for multiplication\n+        if nrot <= self._max_n:\n+            cos_matrix = self._matrices[nrot-1][0]\n+            sin_matrix = self._matrices[nrot-1][1]\n+        else:\n+            cos_matrix, sin_matrix = self._make_matrix(nrot)\n+\n+        return 0.5 * vectors +\\\n+            0.25 * cos(beta - meas * pi) * cos_matrix.dot(vectors) +\\\n+            0.25 * sin(beta - meas * pi) * sin_matrix.dot(vectors)\n+\n+    def _mlikelihood(self, a_vec):\n+        # Calculates the negative likelihood of a set of amplitudes\n+        # generating the observed measurements\n+        return -sum([numpy.log(p_vec.dot(a_vec[:len(p_vec)]))\n+                     for p_vec in self._p_vecs]) +\\\n+            self._init_mlikelihood(a_vec)\n+\n+    def _diff_mlikelihood(self, a_vec):\n+        # The derivative of the above function\n+        return -sum([p_vec/(p_vec.dot(a_vec[:len(p_vec)]))\n+                     for p_vec in self._p_vecs]) +\\\n+            self._dinit_mlikelihood(a_vec)\n+\n+    def _single_diff(self, p_vec, a_vec):\n+        # The first derivative of a single term in the\n+        # likelihood function.\n+        return -p_vec / numpy.dot(p_vec, a_vec[:len(p_vec)])\n+\n+    def _jacobian_term(self, p_vec, a_vec):\n+        # The second derivative of the above function,\n+        # evaluated for a single p vector - to evaluate\n+        # and store\n+        return numpy.dot(p_vec[:, numpy.newaxis], p_vec[numpy.newaxis, :]) /\\\n+            numpy.dot(p_vec, a_vec[:len(p_vec)]) ** 2\n+\n+    def _calculate_jacobian(self):\n+        # Recalculates the Jacobian based on all previously\n+        # calculated p_vecs.\n+        self._jacobian = sum(\n+            [self._jacobian_term(p_vec, self._amplitude_estimates)\n+             for p_vec in self._p_vecs]) + self._jinit_mlikelihood()\n+\n+    def _init_mlikelihood(self, a_vec):\n+        # A normal distributed initial guess at the amplitudes\n+        return numpy.dot(\n+            0.5*(a_vec-self._amplitude_guess)[numpy.newaxis, :],\n+            numpy.dot(self._inv_covar_mat,\n+                      (a_vec-self._amplitude_guess)[:, numpy.newaxis])).item()\n+\n+    def _dinit_mlikelihood(self, a_vec):\n+        # The derivative of the above likelihood function\n+        return numpy.dot(self._inv_covar_mat, (a_vec-self._amplitude_guess))\n+\n+    def _jinit_mlikelihood(self):\n+        # The jacobian of the above likelihood function\n+        return self._inv_covar_mat\n+\n+    def _make_projector(self):\n+        # Calculates the projector onto the plane sum_j|a_j|^2=0\n+        num_vectors = self._num_vectors\n+        self._projector = numpy.identity(num_vectors) -\\\n+            1/num_vectors * numpy.ones([num_vectors, num_vectors])\n+\n+    def _make_dist(self, vector, angle):\n+        \"\"\"\n+        converts a frequency vector into a function evaluated at theta\n+        Args:\n+            vector (numpy array): a fourier vector P(phi)\n+            angle (float): the angle to evaluate P at\n+\n+        Returns:\n+            (float) P(angle)\n+        \"\"\"\n+        res = vector[0]\n+        for j in range(1, self._num_freqs):\n+            res += vector[2*j-1] * sin(j*angle)\n+            res += vector[2*j] * cos(j*angle)\n+        return res / (2*pi)\n+\n+\n+class BayesEstimator(FourierProbabilityDist):","path":"src/openfermion/measurements/_bayesian_estimators.py","position":390,"original_position":390,"commit_id":"f98d18e21cdd285942d34ccac19e4dd7a846f792","original_commit_id":"f98d18e21cdd285942d34ccac19e4dd7a846f792","user":{"login":"kevinsung","id":4296166,"node_id":"MDQ6VXNlcjQyOTYxNjY=","avatar_url":"https://avatars1.githubusercontent.com/u/4296166?v=4","gravatar_id":"","url":"https://api.github.com/users/kevinsung","html_url":"https://github.com/kevinsung","followers_url":"https://api.github.com/users/kevinsung/followers","following_url":"https://api.github.com/users/kevinsung/following{/other_user}","gists_url":"https://api.github.com/users/kevinsung/gists{/gist_id}","starred_url":"https://api.github.com/users/kevinsung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevinsung/subscriptions","organizations_url":"https://api.github.com/users/kevinsung/orgs","repos_url":"https://api.github.com/users/kevinsung/repos","events_url":"https://api.github.com/users/kevinsung/events{/privacy}","received_events_url":"https://api.github.com/users/kevinsung/received_events","type":"User","site_admin":false},"body":"I'm not sure about having BayesEstimator be a subclass of FourierProbabilityDist. It seems to be mixing together two quite distinct concepts: the concept of a probability distribution, and the concept of something which maintains a probability distribution internally and uses it to estimate values of things. I think it makes more sense for BayesEstimator to keep an instance of FourierProbabilityDist, which it updates as it gets more information and which it uses to obtain phase estimates. What do you think?","created_at":"2018-10-23T00:05:50Z","updated_at":"2018-10-23T00:05:56Z","html_url":"https://github.com/quantumlib/OpenFermion/pull/468#discussion_r227179167","pull_request_url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/comments/227179167"},"html":{"href":"https://github.com/quantumlib/OpenFermion/pull/468#discussion_r227179167"},"pull_request":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468"}}},"pull_request":{"url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468","id":218449519,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE4NDQ5NTE5","html_url":"https://github.com/quantumlib/OpenFermion/pull/468","diff_url":"https://github.com/quantumlib/OpenFermion/pull/468.diff","patch_url":"https://github.com/quantumlib/OpenFermion/pull/468.patch","issue_url":"https://api.github.com/repos/quantumlib/OpenFermion/issues/468","number":468,"state":"open","locked":false,"title":"Bayesian estimator","user":{"login":"obriente","id":16646542,"node_id":"MDQ6VXNlcjE2NjQ2NTQy","avatar_url":"https://avatars1.githubusercontent.com/u/16646542?v=4","gravatar_id":"","url":"https://api.github.com/users/obriente","html_url":"https://github.com/obriente","followers_url":"https://api.github.com/users/obriente/followers","following_url":"https://api.github.com/users/obriente/following{/other_user}","gists_url":"https://api.github.com/users/obriente/gists{/gist_id}","starred_url":"https://api.github.com/users/obriente/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obriente/subscriptions","organizations_url":"https://api.github.com/users/obriente/orgs","repos_url":"https://api.github.com/users/obriente/repos","events_url":"https://api.github.com/users/obriente/events{/privacy}","received_events_url":"https://api.github.com/users/obriente/received_events","type":"User","site_admin":false},"body":"Here's the Bayesian estimator split from #466.","created_at":"2018-09-26T20:46:32Z","updated_at":"2018-10-23T00:05:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9143808fd1bd558ba855464f496425436a883d14","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":923815919,"node_id":"MDU6TGFiZWw5MjM4MTU5MTk=","url":"https://api.github.com/repos/quantumlib/OpenFermion/labels/cla:%20yes","name":"cla: yes","color":"0e8a16","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468/commits","review_comments_url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468/comments","review_comment_url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/comments{/number}","comments_url":"https://api.github.com/repos/quantumlib/OpenFermion/issues/468/comments","statuses_url":"https://api.github.com/repos/quantumlib/OpenFermion/statuses/f98d18e21cdd285942d34ccac19e4dd7a846f792","head":{"label":"obriente:bayesian_estimator","ref":"bayesian_estimator","sha":"f98d18e21cdd285942d34ccac19e4dd7a846f792","user":{"login":"obriente","id":16646542,"node_id":"MDQ6VXNlcjE2NjQ2NTQy","avatar_url":"https://avatars1.githubusercontent.com/u/16646542?v=4","gravatar_id":"","url":"https://api.github.com/users/obriente","html_url":"https://github.com/obriente","followers_url":"https://api.github.com/users/obriente/followers","following_url":"https://api.github.com/users/obriente/following{/other_user}","gists_url":"https://api.github.com/users/obriente/gists{/gist_id}","starred_url":"https://api.github.com/users/obriente/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obriente/subscriptions","organizations_url":"https://api.github.com/users/obriente/orgs","repos_url":"https://api.github.com/users/obriente/repos","events_url":"https://api.github.com/users/obriente/events{/privacy}","received_events_url":"https://api.github.com/users/obriente/received_events","type":"User","site_admin":false},"repo":{"id":119523806,"node_id":"MDEwOlJlcG9zaXRvcnkxMTk1MjM4MDY=","name":"OpenFermion","full_name":"obriente/OpenFermion","private":false,"owner":{"login":"obriente","id":16646542,"node_id":"MDQ6VXNlcjE2NjQ2NTQy","avatar_url":"https://avatars1.githubusercontent.com/u/16646542?v=4","gravatar_id":"","url":"https://api.github.com/users/obriente","html_url":"https://github.com/obriente","followers_url":"https://api.github.com/users/obriente/followers","following_url":"https://api.github.com/users/obriente/following{/other_user}","gists_url":"https://api.github.com/users/obriente/gists{/gist_id}","starred_url":"https://api.github.com/users/obriente/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/obriente/subscriptions","organizations_url":"https://api.github.com/users/obriente/orgs","repos_url":"https://api.github.com/users/obriente/repos","events_url":"https://api.github.com/users/obriente/events{/privacy}","received_events_url":"https://api.github.com/users/obriente/received_events","type":"User","site_admin":false},"html_url":"https://github.com/obriente/OpenFermion","description":"OpenFermion: The Electronic Structure Package For Quantum Computers.","fork":true,"url":"https://api.github.com/repos/obriente/OpenFermion","forks_url":"https://api.github.com/repos/obriente/OpenFermion/forks","keys_url":"https://api.github.com/repos/obriente/OpenFermion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/obriente/OpenFermion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/obriente/OpenFermion/teams","hooks_url":"https://api.github.com/repos/obriente/OpenFermion/hooks","issue_events_url":"https://api.github.com/repos/obriente/OpenFermion/issues/events{/number}","events_url":"https://api.github.com/repos/obriente/OpenFermion/events","assignees_url":"https://api.github.com/repos/obriente/OpenFermion/assignees{/user}","branches_url":"https://api.github.com/repos/obriente/OpenFermion/branches{/branch}","tags_url":"https://api.github.com/repos/obriente/OpenFermion/tags","blobs_url":"https://api.github.com/repos/obriente/OpenFermion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/obriente/OpenFermion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/obriente/OpenFermion/git/refs{/sha}","trees_url":"https://api.github.com/repos/obriente/OpenFermion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/obriente/OpenFermion/statuses/{sha}","languages_url":"https://api.github.com/repos/obriente/OpenFermion/languages","stargazers_url":"https://api.github.com/repos/obriente/OpenFermion/stargazers","contributors_url":"https://api.github.com/repos/obriente/OpenFermion/contributors","subscribers_url":"https://api.github.com/repos/obriente/OpenFermion/subscribers","subscription_url":"https://api.github.com/repos/obriente/OpenFermion/subscription","commits_url":"https://api.github.com/repos/obriente/OpenFermion/commits{/sha}","git_commits_url":"https://api.github.com/repos/obriente/OpenFermion/git/commits{/sha}","comments_url":"https://api.github.com/repos/obriente/OpenFermion/comments{/number}","issue_comment_url":"https://api.github.com/repos/obriente/OpenFermion/issues/comments{/number}","contents_url":"https://api.github.com/repos/obriente/OpenFermion/contents/{+path}","compare_url":"https://api.github.com/repos/obriente/OpenFermion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/obriente/OpenFermion/merges","archive_url":"https://api.github.com/repos/obriente/OpenFermion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/obriente/OpenFermion/downloads","issues_url":"https://api.github.com/repos/obriente/OpenFermion/issues{/number}","pulls_url":"https://api.github.com/repos/obriente/OpenFermion/pulls{/number}","milestones_url":"https://api.github.com/repos/obriente/OpenFermion/milestones{/number}","notifications_url":"https://api.github.com/repos/obriente/OpenFermion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/obriente/OpenFermion/labels{/name}","releases_url":"https://api.github.com/repos/obriente/OpenFermion/releases{/id}","deployments_url":"https://api.github.com/repos/obriente/OpenFermion/deployments","created_at":"2018-01-30T10:59:46Z","updated_at":"2018-09-30T18:11:09Z","pushed_at":"2018-10-19T08:40:45Z","git_url":"git://github.com/obriente/OpenFermion.git","ssh_url":"git@github.com:obriente/OpenFermion.git","clone_url":"https://github.com/obriente/OpenFermion.git","svn_url":"https://github.com/obriente/OpenFermion","homepage":"","size":3989,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"quantumlib:master","ref":"master","sha":"8a790335cc2ac7f82c53a22f821ce51e8486e79d","user":{"login":"quantumlib","id":31279789,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxMjc5Nzg5","avatar_url":"https://avatars1.githubusercontent.com/u/31279789?v=4","gravatar_id":"","url":"https://api.github.com/users/quantumlib","html_url":"https://github.com/quantumlib","followers_url":"https://api.github.com/users/quantumlib/followers","following_url":"https://api.github.com/users/quantumlib/following{/other_user}","gists_url":"https://api.github.com/users/quantumlib/gists{/gist_id}","starred_url":"https://api.github.com/users/quantumlib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantumlib/subscriptions","organizations_url":"https://api.github.com/users/quantumlib/orgs","repos_url":"https://api.github.com/users/quantumlib/repos","events_url":"https://api.github.com/users/quantumlib/events{/privacy}","received_events_url":"https://api.github.com/users/quantumlib/received_events","type":"Organization","site_admin":false},"repo":{"id":104403768,"node_id":"MDEwOlJlcG9zaXRvcnkxMDQ0MDM3Njg=","name":"OpenFermion","full_name":"quantumlib/OpenFermion","private":false,"owner":{"login":"quantumlib","id":31279789,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxMjc5Nzg5","avatar_url":"https://avatars1.githubusercontent.com/u/31279789?v=4","gravatar_id":"","url":"https://api.github.com/users/quantumlib","html_url":"https://github.com/quantumlib","followers_url":"https://api.github.com/users/quantumlib/followers","following_url":"https://api.github.com/users/quantumlib/following{/other_user}","gists_url":"https://api.github.com/users/quantumlib/gists{/gist_id}","starred_url":"https://api.github.com/users/quantumlib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quantumlib/subscriptions","organizations_url":"https://api.github.com/users/quantumlib/orgs","repos_url":"https://api.github.com/users/quantumlib/repos","events_url":"https://api.github.com/users/quantumlib/events{/privacy}","received_events_url":"https://api.github.com/users/quantumlib/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/quantumlib/OpenFermion","description":"The electronic structure package for quantum computers.","fork":false,"url":"https://api.github.com/repos/quantumlib/OpenFermion","forks_url":"https://api.github.com/repos/quantumlib/OpenFermion/forks","keys_url":"https://api.github.com/repos/quantumlib/OpenFermion/keys{/key_id}","collaborators_url":"https://api.github.com/repos/quantumlib/OpenFermion/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/quantumlib/OpenFermion/teams","hooks_url":"https://api.github.com/repos/quantumlib/OpenFermion/hooks","issue_events_url":"https://api.github.com/repos/quantumlib/OpenFermion/issues/events{/number}","events_url":"https://api.github.com/repos/quantumlib/OpenFermion/events","assignees_url":"https://api.github.com/repos/quantumlib/OpenFermion/assignees{/user}","branches_url":"https://api.github.com/repos/quantumlib/OpenFermion/branches{/branch}","tags_url":"https://api.github.com/repos/quantumlib/OpenFermion/tags","blobs_url":"https://api.github.com/repos/quantumlib/OpenFermion/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/quantumlib/OpenFermion/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/quantumlib/OpenFermion/git/refs{/sha}","trees_url":"https://api.github.com/repos/quantumlib/OpenFermion/git/trees{/sha}","statuses_url":"https://api.github.com/repos/quantumlib/OpenFermion/statuses/{sha}","languages_url":"https://api.github.com/repos/quantumlib/OpenFermion/languages","stargazers_url":"https://api.github.com/repos/quantumlib/OpenFermion/stargazers","contributors_url":"https://api.github.com/repos/quantumlib/OpenFermion/contributors","subscribers_url":"https://api.github.com/repos/quantumlib/OpenFermion/subscribers","subscription_url":"https://api.github.com/repos/quantumlib/OpenFermion/subscription","commits_url":"https://api.github.com/repos/quantumlib/OpenFermion/commits{/sha}","git_commits_url":"https://api.github.com/repos/quantumlib/OpenFermion/git/commits{/sha}","comments_url":"https://api.github.com/repos/quantumlib/OpenFermion/comments{/number}","issue_comment_url":"https://api.github.com/repos/quantumlib/OpenFermion/issues/comments{/number}","contents_url":"https://api.github.com/repos/quantumlib/OpenFermion/contents/{+path}","compare_url":"https://api.github.com/repos/quantumlib/OpenFermion/compare/{base}...{head}","merges_url":"https://api.github.com/repos/quantumlib/OpenFermion/merges","archive_url":"https://api.github.com/repos/quantumlib/OpenFermion/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/quantumlib/OpenFermion/downloads","issues_url":"https://api.github.com/repos/quantumlib/OpenFermion/issues{/number}","pulls_url":"https://api.github.com/repos/quantumlib/OpenFermion/pulls{/number}","milestones_url":"https://api.github.com/repos/quantumlib/OpenFermion/milestones{/number}","notifications_url":"https://api.github.com/repos/quantumlib/OpenFermion/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/quantumlib/OpenFermion/labels{/name}","releases_url":"https://api.github.com/repos/quantumlib/OpenFermion/releases{/id}","deployments_url":"https://api.github.com/repos/quantumlib/OpenFermion/deployments","created_at":"2017-09-21T22:10:28Z","updated_at":"2018-10-22T23:39:22Z","pushed_at":"2018-10-19T08:40:46Z","git_url":"git://github.com/quantumlib/OpenFermion.git","ssh_url":"git@github.com:quantumlib/OpenFermion.git","clone_url":"https://github.com/quantumlib/OpenFermion.git","svn_url":"https://github.com/quantumlib/OpenFermion","homepage":"","size":3686,"stargazers_count":650,"watchers_count":650,"language":"Python","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":152,"mirror_url":null,"archived":false,"open_issues_count":53,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":152,"open_issues":53,"watchers":650,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468"},"html":{"href":"https://github.com/quantumlib/OpenFermion/pull/468"},"issue":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/issues/468"},"comments":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/issues/468/comments"},"review_comments":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468/comments"},"review_comment":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/pulls/468/commits"},"statuses":{"href":"https://api.github.com/repos/quantumlib/OpenFermion/statuses/f98d18e21cdd285942d34ccac19e4dd7a846f792"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"kevinsung"}}