We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
check that input graph is same size as P matrix when using score in the model selection code


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `graspy/models/base.py`
Content:
```
1 from abc import abstractmethod
2 
3 import numpy as np
4 from sklearn.base import BaseEstimator
5 from sklearn.utils.validation import check_is_fitted
6 
7 from ..utils import import_graph, is_unweighted
8 from ..simulations import sample_edges
9 
10 
11 def _calculate_p(block):
12     n_edges = np.count_nonzero(block)
13     return n_edges / block.size
14 
15 
16 def _check_n_samples(n_samples):
17     if not isinstance(n_samples, (int, float)):
18         raise TypeError("n_samples must be a scalar value")
19     if n_samples < 1:
20         raise ValueError(
21             "Invalid value for 'n_samples': %d . The sampling requires at "
22             "least one sample." % (n_samples)
23         )
24 
25 
26 def _n_to_labels(n):
27     n_cumsum = n.cumsum()
28     labels = np.zeros(n.sum(), dtype=np.int64)
29     for i in range(1, len(n)):
30         labels[n_cumsum[i - 1] : n_cumsum[i]] = i
31     return labels
32 
33 
34 class BaseGraphEstimator(BaseEstimator):
35     def __init__(self, directed=True, loops=False):
36         if not isinstance(directed, bool):
37             raise TypeError("`directed` must be of type bool")
38         if not isinstance(loops, bool):
39             raise TypeError("`loops` must be of type bool")
40         self.directed = directed
41         self.loops = loops
42 
43     def bic(self, graph):
44         """
45         Bayesian information criterion for the current model on the input graph.
46         
47         Note that this implicitly assumes the input graph is indexed like the 
48         fit model.
49 
50         Parameters
51         ----------
52         graph : np.ndarray
53             Input graph
54         
55         Returns
56         -------
57         bic : float
58             The lower the better
59         """
60         check_is_fitted(self, "p_mat_")
61         return 2 * np.log(self.n_verts) * self._n_parameters() - 2 * self.score(graph)
62 
63     def mse(self, graph):
64         """
65         Compute mean square error for the current model on the input graph
66         
67         Note that this implicitly assumes the input graph is indexed like the 
68         fit model.
69 
70         Parameters
71         ----------
72         graph : np.ndarray
73             Input graph
74         
75         Returns
76         -------
77         mse : float
78             Mean square error for the model's fit P matrix
79         """
80         check_is_fitted(self, "p_mat_")
81         return np.linalg.norm(graph - self.p_mat_) ** 2
82 
83     def score_samples(self, graph, clip=None):
84         """
85         Compute the weighted log probabilities for each potential edge.
86 
87         Note that this implicitly assumes the input graph is indexed like the 
88         fit model.
89 
90         Parameters
91         ----------
92         graph : np.ndarray
93             input graph
94         
95         clip : scalar or None, optional (default=None)
96             Values for which to clip probability matrix, entries less than c or more
97             than 1 - c are set to c or 1 - c, respectively.
98             If None, values will not be clipped in the likelihood calculation, which may
99             result in poorly behaved likelihoods depending on the model. 
100         
101         Returns
102         -------
103         sample_scores : np.ndarray (size of ``graph``)
104             log-likelihood per potential edge in the graph
105         """
106         check_is_fitted(self, "p_mat_")
107         # P.ravel() <dot> graph * (1 - P.ravel()) <dot> (1 - graph)
108         graph = import_graph(graph)
109         if not is_unweighted(graph):
110             raise ValueError("Model only implemented for unweighted graphs")
111         p_mat = self.p_mat_.copy()
112 
113         inds = None
114         if not self.directed and self.loops:
115             inds = np.triu_indices_from(graph)  # ignore lower half of graph, symmetric
116         elif not self.directed and not self.loops:
117             inds = np.triu_indices_from(graph, k=1)  # ignore the diagonal
118         elif self.directed and not self.loops:
119             xu, yu = np.triu_indices_from(graph, k=1)
120             xl, yl = np.tril_indices_from(graph, k=-1)
121             x = np.concatenate((xl, xu))
122             y = np.concatenate((yl, yu))
123             inds = (x, y)
124         if inds is not None:
125             p_mat = p_mat[inds]
126             graph = graph[inds]
127 
128         # clip the probabilities that are degenerate
129         if clip is not None:
130             p_mat[p_mat < clip] = clip
131             p_mat[p_mat > 1 - clip] = 1 - clip
132 
133         # TODO: use nonzero inds here will be faster
134         successes = np.multiply(p_mat, graph)
135         failures = np.multiply((1 - p_mat), (1 - graph))
136         likelihood = successes + failures
137         return np.log(likelihood)
138 
139     def score(self, graph):
140         """
141         Compute the average log-likelihood over each potential edge of the 
142         given graph.
143 
144         Note that this implicitly assumes the input graph is indexed like the 
145         fit model.
146 
147         Parameters
148         ----------
149         graph : np.ndarray
150             input graph
151 
152         Returns
153         -------
154         score : float
155             sum of log-loglikelihoods for each potential edge in input graph
156         """
157         check_is_fitted(self, "p_mat_")
158         return np.sum(self.score_samples(graph))
159 
160     @property
161     def _pairwise(self):
162         """This is for sklearn compliance."""
163         return True
164 
165     @abstractmethod
166     def fit(self, graph, y=None):
167         """
168         Calculate the parameters for the given graph model 
169         """
170         return self
171 
172     def sample(self, n_samples=1):
173         """
174         Sample graphs (realizations) from the fitted model
175 
176         Can only be called after the the model has been fit 
177 
178         Parameters
179         ----------
180         n_samples : int (default 1), optional
181             The number of graphs to sample 
182 
183         Returns 
184         -------
185         graphs : np.array (n_samples, n_verts, n_verts)
186             Array of sampled graphs, where the first dimension 
187             indexes each sample, and the other dimensions represent
188             (n_verts x n_verts) adjacency matrices for the sampled graphs. 
189 
190             Note that if only one sample is drawn, a (1, n_verts, n_verts) 
191             array will still be returned. 
192         """
193         check_is_fitted(self, "p_mat_")
194         _check_n_samples(n_samples)
195         n_verts = self.p_mat_.shape[0]
196         graphs = np.zeros((n_samples, n_verts, n_verts))
197         p_mat = self.p_mat_.copy()
198         p_mat[p_mat > 1] = 1
199         p_mat[p_mat < 0] = 0
200         for i in range(n_samples):
201             graphs[i, :, :] = sample_edges(
202                 p_mat, directed=self.directed, loops=self.loops
203             )
204         return graphs
205 
206     @abstractmethod
207     def _n_parameters(self):
208         n_parameters = 1
209         return n_parameters
210
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/graspy/models/base.py b/graspy/models/base.py
--- a/graspy/models/base.py
+++ b/graspy/models/base.py
@@ -90,7 +90,7 @@
         Parameters
         ----------
         graph : np.ndarray
-            input graph
+            Input graph. Must be same shape as model's ``p_mat_`` attribute
         
         clip : scalar or None, optional (default=None)
             Values for which to clip probability matrix, entries less than c or more
@@ -110,6 +110,9 @@
             raise ValueError("Model only implemented for unweighted graphs")
         p_mat = self.p_mat_.copy()
 
+        if np.shape(p_mat) != np.shape(graph):
+            raise ValueError("Input graph size must be the same size as P matrix")
+
         inds = None
         if not self.directed and self.loops:
             inds = np.triu_indices_from(graph)  # ignore lower half of graph, symmetric
@@ -147,7 +150,7 @@
         Parameters
         ----------
         graph : np.ndarray
-            input graph
+            Input graph. Must be same shape as model's ``p_mat_`` attribute
 
         Returns
         -------

{"golden_diff": "diff --git a/graspy/models/base.py b/graspy/models/base.py\n--- a/graspy/models/base.py\n+++ b/graspy/models/base.py\n@@ -90,7 +90,7 @@\n         Parameters\n         ----------\n         graph : np.ndarray\n-            input graph\n+            Input graph. Must be same shape as model's ``p_mat_`` attribute\n         \n         clip : scalar or None, optional (default=None)\n             Values for which to clip probability matrix, entries less than c or more\n@@ -110,6 +110,9 @@\n             raise ValueError(\"Model only implemented for unweighted graphs\")\n         p_mat = self.p_mat_.copy()\n \n+        if np.shape(p_mat) != np.shape(graph):\n+            raise ValueError(\"Input graph size must be the same size as P matrix\")\n+\n         inds = None\n         if not self.directed and self.loops:\n             inds = np.triu_indices_from(graph)  # ignore lower half of graph, symmetric\n@@ -147,7 +150,7 @@\n         Parameters\n         ----------\n         graph : np.ndarray\n-            input graph\n+            Input graph. Must be same shape as model's ``p_mat_`` attribute\n \n         Returns\n         -------\n", "issue": "check that input graph is same size as P matrix when using score in the model selection code\n\n", "before_files": [{"content": "from abc import abstractmethod\n\nimport numpy as np\nfrom sklearn.base import BaseEstimator\nfrom sklearn.utils.validation import check_is_fitted\n\nfrom ..utils import import_graph, is_unweighted\nfrom ..simulations import sample_edges\n\n\ndef _calculate_p(block):\n    n_edges = np.count_nonzero(block)\n    return n_edges / block.size\n\n\ndef _check_n_samples(n_samples):\n    if not isinstance(n_samples, (int, float)):\n        raise TypeError(\"n_samples must be a scalar value\")\n    if n_samples < 1:\n        raise ValueError(\n            \"Invalid value for 'n_samples': %d . The sampling requires at \"\n            \"least one sample.\" % (n_samples)\n        )\n\n\ndef _n_to_labels(n):\n    n_cumsum = n.cumsum()\n    labels = np.zeros(n.sum(), dtype=np.int64)\n    for i in range(1, len(n)):\n        labels[n_cumsum[i - 1] : n_cumsum[i]] = i\n    return labels\n\n\nclass BaseGraphEstimator(BaseEstimator):\n    def __init__(self, directed=True, loops=False):\n        if not isinstance(directed, bool):\n            raise TypeError(\"`directed` must be of type bool\")\n        if not isinstance(loops, bool):\n            raise TypeError(\"`loops` must be of type bool\")\n        self.directed = directed\n        self.loops = loops\n\n    def bic(self, graph):\n        \"\"\"\n        Bayesian information criterion for the current model on the input graph.\n        \n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph\n        \n        Returns\n        -------\n        bic : float\n            The lower the better\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return 2 * np.log(self.n_verts) * self._n_parameters() - 2 * self.score(graph)\n\n    def mse(self, graph):\n        \"\"\"\n        Compute mean square error for the current model on the input graph\n        \n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph\n        \n        Returns\n        -------\n        mse : float\n            Mean square error for the model's fit P matrix\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return np.linalg.norm(graph - self.p_mat_) ** 2\n\n    def score_samples(self, graph, clip=None):\n        \"\"\"\n        Compute the weighted log probabilities for each potential edge.\n\n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            input graph\n        \n        clip : scalar or None, optional (default=None)\n            Values for which to clip probability matrix, entries less than c or more\n            than 1 - c are set to c or 1 - c, respectively.\n            If None, values will not be clipped in the likelihood calculation, which may\n            result in poorly behaved likelihoods depending on the model. \n        \n        Returns\n        -------\n        sample_scores : np.ndarray (size of ``graph``)\n            log-likelihood per potential edge in the graph\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        # P.ravel() <dot> graph * (1 - P.ravel()) <dot> (1 - graph)\n        graph = import_graph(graph)\n        if not is_unweighted(graph):\n            raise ValueError(\"Model only implemented for unweighted graphs\")\n        p_mat = self.p_mat_.copy()\n\n        inds = None\n        if not self.directed and self.loops:\n            inds = np.triu_indices_from(graph)  # ignore lower half of graph, symmetric\n        elif not self.directed and not self.loops:\n            inds = np.triu_indices_from(graph, k=1)  # ignore the diagonal\n        elif self.directed and not self.loops:\n            xu, yu = np.triu_indices_from(graph, k=1)\n            xl, yl = np.tril_indices_from(graph, k=-1)\n            x = np.concatenate((xl, xu))\n            y = np.concatenate((yl, yu))\n            inds = (x, y)\n        if inds is not None:\n            p_mat = p_mat[inds]\n            graph = graph[inds]\n\n        # clip the probabilities that are degenerate\n        if clip is not None:\n            p_mat[p_mat < clip] = clip\n            p_mat[p_mat > 1 - clip] = 1 - clip\n\n        # TODO: use nonzero inds here will be faster\n        successes = np.multiply(p_mat, graph)\n        failures = np.multiply((1 - p_mat), (1 - graph))\n        likelihood = successes + failures\n        return np.log(likelihood)\n\n    def score(self, graph):\n        \"\"\"\n        Compute the average log-likelihood over each potential edge of the \n        given graph.\n\n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            input graph\n\n        Returns\n        -------\n        score : float\n            sum of log-loglikelihoods for each potential edge in input graph\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return np.sum(self.score_samples(graph))\n\n    @property\n    def _pairwise(self):\n        \"\"\"This is for sklearn compliance.\"\"\"\n        return True\n\n    @abstractmethod\n    def fit(self, graph, y=None):\n        \"\"\"\n        Calculate the parameters for the given graph model \n        \"\"\"\n        return self\n\n    def sample(self, n_samples=1):\n        \"\"\"\n        Sample graphs (realizations) from the fitted model\n\n        Can only be called after the the model has been fit \n\n        Parameters\n        ----------\n        n_samples : int (default 1), optional\n            The number of graphs to sample \n\n        Returns \n        -------\n        graphs : np.array (n_samples, n_verts, n_verts)\n            Array of sampled graphs, where the first dimension \n            indexes each sample, and the other dimensions represent\n            (n_verts x n_verts) adjacency matrices for the sampled graphs. \n\n            Note that if only one sample is drawn, a (1, n_verts, n_verts) \n            array will still be returned. \n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        _check_n_samples(n_samples)\n        n_verts = self.p_mat_.shape[0]\n        graphs = np.zeros((n_samples, n_verts, n_verts))\n        p_mat = self.p_mat_.copy()\n        p_mat[p_mat > 1] = 1\n        p_mat[p_mat < 0] = 0\n        for i in range(n_samples):\n            graphs[i, :, :] = sample_edges(\n                p_mat, directed=self.directed, loops=self.loops\n            )\n        return graphs\n\n    @abstractmethod\n    def _n_parameters(self):\n        n_parameters = 1\n        return n_parameters\n", "path": "graspy/models/base.py"}], "after_files": [{"content": "from abc import abstractmethod\n\nimport numpy as np\nfrom sklearn.base import BaseEstimator\nfrom sklearn.utils.validation import check_is_fitted\n\nfrom ..utils import import_graph, is_unweighted\nfrom ..simulations import sample_edges\n\n\ndef _calculate_p(block):\n    n_edges = np.count_nonzero(block)\n    return n_edges / block.size\n\n\ndef _check_n_samples(n_samples):\n    if not isinstance(n_samples, (int, float)):\n        raise TypeError(\"n_samples must be a scalar value\")\n    if n_samples < 1:\n        raise ValueError(\n            \"Invalid value for 'n_samples': %d . The sampling requires at \"\n            \"least one sample.\" % (n_samples)\n        )\n\n\ndef _n_to_labels(n):\n    n_cumsum = n.cumsum()\n    labels = np.zeros(n.sum(), dtype=np.int64)\n    for i in range(1, len(n)):\n        labels[n_cumsum[i - 1] : n_cumsum[i]] = i\n    return labels\n\n\nclass BaseGraphEstimator(BaseEstimator):\n    def __init__(self, directed=True, loops=False):\n        if not isinstance(directed, bool):\n            raise TypeError(\"`directed` must be of type bool\")\n        if not isinstance(loops, bool):\n            raise TypeError(\"`loops` must be of type bool\")\n        self.directed = directed\n        self.loops = loops\n\n    def bic(self, graph):\n        \"\"\"\n        Bayesian information criterion for the current model on the input graph.\n        \n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph\n        \n        Returns\n        -------\n        bic : float\n            The lower the better\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return 2 * np.log(self.n_verts) * self._n_parameters() - 2 * self.score(graph)\n\n    def mse(self, graph):\n        \"\"\"\n        Compute mean square error for the current model on the input graph\n        \n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph\n        \n        Returns\n        -------\n        mse : float\n            Mean square error for the model's fit P matrix\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return np.linalg.norm(graph - self.p_mat_) ** 2\n\n    def score_samples(self, graph, clip=None):\n        \"\"\"\n        Compute the weighted log probabilities for each potential edge.\n\n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph. Must be same shape as model's ``p_mat_`` attribute\n        \n        clip : scalar or None, optional (default=None)\n            Values for which to clip probability matrix, entries less than c or more\n            than 1 - c are set to c or 1 - c, respectively.\n            If None, values will not be clipped in the likelihood calculation, which may\n            result in poorly behaved likelihoods depending on the model. \n        \n        Returns\n        -------\n        sample_scores : np.ndarray (size of ``graph``)\n            log-likelihood per potential edge in the graph\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        # P.ravel() <dot> graph * (1 - P.ravel()) <dot> (1 - graph)\n        graph = import_graph(graph)\n        if not is_unweighted(graph):\n            raise ValueError(\"Model only implemented for unweighted graphs\")\n        p_mat = self.p_mat_.copy()\n\n        if np.shape(p_mat) != np.shape(graph):\n            raise ValueError(\"Input graph size must be the same size as P matrix\")\n\n        inds = None\n        if not self.directed and self.loops:\n            inds = np.triu_indices_from(graph)  # ignore lower half of graph, symmetric\n        elif not self.directed and not self.loops:\n            inds = np.triu_indices_from(graph, k=1)  # ignore the diagonal\n        elif self.directed and not self.loops:\n            xu, yu = np.triu_indices_from(graph, k=1)\n            xl, yl = np.tril_indices_from(graph, k=-1)\n            x = np.concatenate((xl, xu))\n            y = np.concatenate((yl, yu))\n            inds = (x, y)\n        if inds is not None:\n            p_mat = p_mat[inds]\n            graph = graph[inds]\n\n        # clip the probabilities that are degenerate\n        if clip is not None:\n            p_mat[p_mat < clip] = clip\n            p_mat[p_mat > 1 - clip] = 1 - clip\n\n        # TODO: use nonzero inds here will be faster\n        successes = np.multiply(p_mat, graph)\n        failures = np.multiply((1 - p_mat), (1 - graph))\n        likelihood = successes + failures\n        return np.log(likelihood)\n\n    def score(self, graph):\n        \"\"\"\n        Compute the average log-likelihood over each potential edge of the \n        given graph.\n\n        Note that this implicitly assumes the input graph is indexed like the \n        fit model.\n\n        Parameters\n        ----------\n        graph : np.ndarray\n            Input graph. Must be same shape as model's ``p_mat_`` attribute\n\n        Returns\n        -------\n        score : float\n            sum of log-loglikelihoods for each potential edge in input graph\n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        return np.sum(self.score_samples(graph))\n\n    @property\n    def _pairwise(self):\n        \"\"\"This is for sklearn compliance.\"\"\"\n        return True\n\n    @abstractmethod\n    def fit(self, graph, y=None):\n        \"\"\"\n        Calculate the parameters for the given graph model \n        \"\"\"\n        return self\n\n    def sample(self, n_samples=1):\n        \"\"\"\n        Sample graphs (realizations) from the fitted model\n\n        Can only be called after the the model has been fit \n\n        Parameters\n        ----------\n        n_samples : int (default 1), optional\n            The number of graphs to sample \n\n        Returns \n        -------\n        graphs : np.array (n_samples, n_verts, n_verts)\n            Array of sampled graphs, where the first dimension \n            indexes each sample, and the other dimensions represent\n            (n_verts x n_verts) adjacency matrices for the sampled graphs. \n\n            Note that if only one sample is drawn, a (1, n_verts, n_verts) \n            array will still be returned. \n        \"\"\"\n        check_is_fitted(self, \"p_mat_\")\n        _check_n_samples(n_samples)\n        n_verts = self.p_mat_.shape[0]\n        graphs = np.zeros((n_samples, n_verts, n_verts))\n        p_mat = self.p_mat_.copy()\n        p_mat[p_mat > 1] = 1\n        p_mat[p_mat < 0] = 0\n        for i in range(n_samples):\n            graphs[i, :, :] = sample_edges(\n                p_mat, directed=self.directed, loops=self.loops\n            )\n        return graphs\n\n    @abstractmethod\n    def _n_parameters(self):\n        n_parameters = 1\n        return n_parameters\n", "path": "graspy/models/base.py"}]}