prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [BUG] Inaccurracy in how to use autokmeans
  ## Expected Behavior
  
  https://github.com/microsoft/graspologic/blob/10de2bf17b972decbab318568154af226dcd71fa/graspologic/cluster/kclust.py#L16
  
  This line is false; higher silhouette score is better, to my knowledge? https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html
  
  ## Actual Behavior
  
  Documentation correctly reports how to use the package.
  
  
  </issue>
  <code>
  [start of graspologic/cluster/kclust.py]
  1 # Copyright (c) Microsoft Corporation and contributors.
  2 # Licensed under the MIT License.
  3 
  4 from typing import Optional, Union
  5 
  6 import numpy as np
  7 from sklearn.cluster import KMeans
  8 from sklearn.metrics import adjusted_rand_score, silhouette_score
  9 
  10 from graspologic.types import List
  11 
  12 from .base import BaseCluster
  13 
  14 
  15 class KMeansCluster(BaseCluster):
  16     ari_: Optional[List[float]]
  17 
  18     """
  19     KMeans Cluster.
  20 
  21     It computes all possible models from one component to
  22     ``max_clusters``. The best model is given by the lowest silhouette score.
  23 
  24     Parameters
  25     ----------
  26     max_clusters : int, defaults to 1.
  27         The maximum number of mixture components to consider.
  28 
  29     random_state : int, RandomState instance or None, optional (default=None)
  30         If int, ``random_state`` is the seed used by the random number generator;
  31         If RandomState instance, ``random_state`` is the random number generator;
  32         If None, the random number generator is the RandomState instance used
  33         by ``np.random``.
  34 
  35     Attributes
  36     ----------
  37     n_clusters_ : int
  38         Optimal number of components. If y is given, it is based on largest
  39         ARI. Otherwise, it is based on smallest loss.
  40 
  41     model_ : KMeans object
  42         Fitted KMeans object fitted with optimal n_components.
  43 
  44     silhouette_ : list
  45         List of silhouette scores computed for all possible number
  46         of clusters given by ``range(2, max_clusters)``.
  47 
  48     ari_ : list
  49         Only computed when y is given. List of ARI values computed for
  50         all possible number of clusters given by ``range(2, max_clusters)``.
  51     """
  52 
  53     def __init__(
  54         self,
  55         max_clusters: int = 2,
  56         random_state: Optional[Union[int, np.random.RandomState]] = None,
  57     ):
  58         if isinstance(max_clusters, int):
  59             if max_clusters <= 1:
  60                 msg = "n_components must be >= 2 or None."
  61                 raise ValueError(msg)
  62             else:
  63                 self.max_clusters = max_clusters
  64         else:
  65             msg = "max_clusters must be an integer, not {}.".format(type(max_clusters))
  66             raise TypeError(msg)
  67         self.random_state = random_state
  68 
  69     def fit(self, X: np.ndarray, y: Optional[np.ndarray] = None) -> "KMeansCluster":
  70         """
  71         Fits kmeans model to the data.
  72 
  73         Parameters
  74         ----------
  75         X : array-like, shape (n_samples, n_features)
  76             List of n_features-dimensional data points. Each row
  77             corresponds to a single data point.
  78 
  79         y : array-like, shape (n_samples,), optional (default=None)
  80             List of labels for `X` if available. Used to compute ARI scores.
  81 
  82         Returns
  83         -------
  84         self
  85         """
  86         # Deal with number of clusters
  87         if self.max_clusters > X.shape[0]:
  88             msg = "n_components must be >= n_samples, but got \
  89                 n_components = {}, n_samples = {}".format(
  90                 self.max_clusters, X.shape[0]
  91             )
  92             raise ValueError(msg)
  93         else:
  94             max_clusters = self.max_clusters
  95 
  96         # Get parameters
  97         random_state = self.random_state
  98 
  99         # Compute all models
  100         models = []
  101         silhouettes = []
  102         aris = []
  103         for n in range(2, max_clusters + 1):
  104             model = KMeans(n_clusters=n, random_state=random_state)
  105 
  106             # Fit and compute values
  107             predictions = model.fit_predict(X)
  108             models.append(model)
  109             silhouettes.append(silhouette_score(X, predictions))
  110             if y is not None:
  111                 aris.append(adjusted_rand_score(y, predictions))
  112 
  113         if y is not None:
  114             self.ari_ = aris
  115             self.silhouette_ = silhouettes
  116             self.n_clusters_ = np.argmax(aris) + 1
  117             self.model_ = models[np.argmax(aris)]
  118         else:
  119             self.ari_ = None
  120             self.silhouette_ = silhouettes
  121             self.n_clusters_ = np.argmax(silhouettes) + 1
  122             self.model_ = models[np.argmax(silhouettes)]
  123 
  124         return self
  125
  [end of graspologic/cluster/kclust.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/graspologic/cluster/kclust.py b/graspologic/cluster/kclust.py
  --- a/graspologic/cluster/kclust.py
  +++ b/graspologic/cluster/kclust.py
  @@ -18,13 +18,15 @@
       """
       KMeans Cluster.
   
  -    It computes all possible models from one component to
  -    ``max_clusters``. The best model is given by the lowest silhouette score.
  +    It computes all possible models from one component to ``max_clusters``.
  +    When the true labels are known, the best model is given by the model with highest
  +    adjusted Rand index (ARI).
  +    Otherwise, the best model is given by the model with highest silhouette score.
   
       Parameters
       ----------
  -    max_clusters : int, defaults to 1.
  -        The maximum number of mixture components to consider.
  +    max_clusters : int, default=2.
  +        The maximum number of clusters to consider. Must be ``>=2``.
   
       random_state : int, RandomState instance or None, optional (default=None)
           If int, ``random_state`` is the seed used by the random number generator;
  @@ -35,11 +37,11 @@
       Attributes
       ----------
       n_clusters_ : int
  -        Optimal number of components. If y is given, it is based on largest
  -        ARI. Otherwise, it is based on smallest loss.
  +        Optimal number of clusters. If y is given, it is based on largest
  +        ARI. Otherwise, it is based on highest silhouette score.
   
       model_ : KMeans object
  -        Fitted KMeans object fitted with optimal n_components.
  +        Fitted KMeans object fitted with ``n_clusters_``.
   
       silhouette_ : list
           List of silhouette scores computed for all possible number
  
verification_info: {"golden_diff": "diff --git a/graspologic/cluster/kclust.py b/graspologic/cluster/kclust.py\n--- a/graspologic/cluster/kclust.py\n+++ b/graspologic/cluster/kclust.py\n@@ -18,13 +18,15 @@\n     \"\"\"\n     KMeans Cluster.\n \n-    It computes all possible models from one component to\n-    ``max_clusters``. The best model is given by the lowest silhouette score.\n+    It computes all possible models from one component to ``max_clusters``.\n+    When the true labels are known, the best model is given by the model with highest\n+    adjusted Rand index (ARI).\n+    Otherwise, the best model is given by the model with highest silhouette score.\n \n     Parameters\n     ----------\n-    max_clusters : int, defaults to 1.\n-        The maximum number of mixture components to consider.\n+    max_clusters : int, default=2.\n+        The maximum number of clusters to consider. Must be ``>=2``.\n \n     random_state : int, RandomState instance or None, optional (default=None)\n         If int, ``random_state`` is the seed used by the random number generator;\n@@ -35,11 +37,11 @@\n     Attributes\n     ----------\n     n_clusters_ : int\n-        Optimal number of components. If y is given, it is based on largest\n-        ARI. Otherwise, it is based on smallest loss.\n+        Optimal number of clusters. If y is given, it is based on largest\n+        ARI. Otherwise, it is based on highest silhouette score.\n \n     model_ : KMeans object\n-        Fitted KMeans object fitted with optimal n_components.\n+        Fitted KMeans object fitted with ``n_clusters_``.\n \n     silhouette_ : list\n         List of silhouette scores computed for all possible number\n", "issue": "[BUG] Inaccurracy in how to use autokmeans\n## Expected Behavior\r\n\r\nhttps://github.com/microsoft/graspologic/blob/10de2bf17b972decbab318568154af226dcd71fa/graspologic/cluster/kclust.py#L16\r\n\r\nThis line is false; higher silhouette score is better, to my knowledge? https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html\r\n\r\n## Actual Behavior\r\n\r\nDocumentation correctly reports how to use the package.\r\n\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation and contributors.\n# Licensed under the MIT License.\n\nfrom typing import Optional, Union\n\nimport numpy as np\nfrom sklearn.cluster import KMeans\nfrom sklearn.metrics import adjusted_rand_score, silhouette_score\n\nfrom graspologic.types import List\n\nfrom .base import BaseCluster\n\n\nclass KMeansCluster(BaseCluster):\n    ari_: Optional[List[float]]\n\n    \"\"\"\n    KMeans Cluster.\n\n    It computes all possible models from one component to\n    ``max_clusters``. The best model is given by the lowest silhouette score.\n\n    Parameters\n    ----------\n    max_clusters : int, defaults to 1.\n        The maximum number of mixture components to consider.\n\n    random_state : int, RandomState instance or None, optional (default=None)\n        If int, ``random_state`` is the seed used by the random number generator;\n        If RandomState instance, ``random_state`` is the random number generator;\n        If None, the random number generator is the RandomState instance used\n        by ``np.random``.\n\n    Attributes\n    ----------\n    n_clusters_ : int\n        Optimal number of components. If y is given, it is based on largest\n        ARI. Otherwise, it is based on smallest loss.\n\n    model_ : KMeans object\n        Fitted KMeans object fitted with optimal n_components.\n\n    silhouette_ : list\n        List of silhouette scores computed for all possible number\n        of clusters given by ``range(2, max_clusters)``.\n\n    ari_ : list\n        Only computed when y is given. List of ARI values computed for\n        all possible number of clusters given by ``range(2, max_clusters)``.\n    \"\"\"\n\n    def __init__(\n        self,\n        max_clusters: int = 2,\n        random_state: Optional[Union[int, np.random.RandomState]] = None,\n    ):\n        if isinstance(max_clusters, int):\n            if max_clusters <= 1:\n                msg = \"n_components must be >= 2 or None.\"\n                raise ValueError(msg)\n            else:\n                self.max_clusters = max_clusters\n        else:\n            msg = \"max_clusters must be an integer, not {}.\".format(type(max_clusters))\n            raise TypeError(msg)\n        self.random_state = random_state\n\n    def fit(self, X: np.ndarray, y: Optional[np.ndarray] = None) -> \"KMeansCluster\":\n        \"\"\"\n        Fits kmeans model to the data.\n\n        Parameters\n        ----------\n        X : array-like, shape (n_samples, n_features)\n            List of n_features-dimensional data points. Each row\n            corresponds to a single data point.\n\n        y : array-like, shape (n_samples,), optional (default=None)\n            List of labels for `X` if available. Used to compute ARI scores.\n\n        Returns\n        -------\n        self\n        \"\"\"\n        # Deal with number of clusters\n        if self.max_clusters > X.shape[0]:\n            msg = \"n_components must be >= n_samples, but got \\\n                n_components = {}, n_samples = {}\".format(\n                self.max_clusters, X.shape[0]\n            )\n            raise ValueError(msg)\n        else:\n            max_clusters = self.max_clusters\n\n        # Get parameters\n        random_state = self.random_state\n\n        # Compute all models\n        models = []\n        silhouettes = []\n        aris = []\n        for n in range(2, max_clusters + 1):\n            model = KMeans(n_clusters=n, random_state=random_state)\n\n            # Fit and compute values\n            predictions = model.fit_predict(X)\n            models.append(model)\n            silhouettes.append(silhouette_score(X, predictions))\n            if y is not None:\n                aris.append(adjusted_rand_score(y, predictions))\n\n        if y is not None:\n            self.ari_ = aris\n            self.silhouette_ = silhouettes\n            self.n_clusters_ = np.argmax(aris) + 1\n            self.model_ = models[np.argmax(aris)]\n        else:\n            self.ari_ = None\n            self.silhouette_ = silhouettes\n            self.n_clusters_ = np.argmax(silhouettes) + 1\n            self.model_ = models[np.argmax(silhouettes)]\n\n        return self\n", "path": "graspologic/cluster/kclust.py"}]}