<h3 dir="auto">Describe the bug</h3>
<p dir="auto">When trying to compute AgglomerativeClustering with affinity='precomputed', linkage='ward' I get the following error:</p>
<p dir="auto"><code class="notranslate">ValueError: precomputed was provided as affinity. Ward can only work with euclidean distances.</code><br>
I think this is intended. What is the reason behind it?</p>
<h3 dir="auto">Steps/Code to Reproduce</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics.pairwise import euclidean_distances
import numpy as np

X = np.random.normal(size=(2,4))
dist=euclidean_distances(X)
cluster_dist = AgglomerativeClustering(n_clusters=2, affinity='precomputed', linkage='ward')
results_dist = cluster_dist.fit(dist)"><pre class="notranslate"><code class="notranslate">from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics.pairwise import euclidean_distances
import numpy as np

X = np.random.normal(size=(2,4))
dist=euclidean_distances(X)
cluster_dist = AgglomerativeClustering(n_clusters=2, affinity='precomputed', linkage='ward')
results_dist = cluster_dist.fit(dist)
</code></pre></div>
<h3 dir="auto">Expected Results</h3>
<p dir="auto">The resulting clusters</p>
<h3 dir="auto">Actual Results</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [122], in &lt;module&gt;
      2 dist=euclidean_distances(X)
      3 cluster_dist = AgglomerativeClustering(n_clusters=n_cluster, affinity='precomputed', linkage='ward')
----&gt; 4 results_dist = cluster_dist.fit(dist)

File ~/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/lib/python3.9/site-packages/sklearn/cluster/_agglomerative.py:918, in AgglomerativeClustering.fit(self, X, y)
    900 &quot;&quot;&quot;Fit the hierarchical clustering from features, or distance matrix.
    901 
    902 Parameters
   (...)
    915     Returns the fitted instance.
    916 &quot;&quot;&quot;
    917 X = self._validate_data(X, ensure_min_samples=2, estimator=self)
--&gt; 918 return self._fit(X)

File ~/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/lib/python3.9/site-packages/sklearn/cluster/_agglomerative.py:955, in AgglomerativeClustering._fit(self, X)
    950     raise ValueError(
    951         &quot;compute_full_tree must be True if distance_threshold is set.&quot;
    952     )
    954 if self.linkage == &quot;ward&quot; and self.affinity != &quot;euclidean&quot;:
--&gt; 955     raise ValueError(
    956         &quot;%s was provided as affinity. Ward can only &quot;
    957         &quot;work with euclidean distances.&quot; % (self.affinity,)
    958     )
    960 if self.linkage not in _TREE_BUILDERS:
    961     raise ValueError(
    962         &quot;Unknown linkage type %s. Valid options are %s&quot;
    963         % (self.linkage, _TREE_BUILDERS.keys())
    964     )

ValueError: precomputed was provided as affinity. Ward can only work with euclidean distances."><pre class="notranslate"><code class="notranslate">---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [122], in &lt;module&gt;
      2 dist=euclidean_distances(X)
      3 cluster_dist = AgglomerativeClustering(n_clusters=n_cluster, affinity='precomputed', linkage='ward')
----&gt; 4 results_dist = cluster_dist.fit(dist)

File ~/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/lib/python3.9/site-packages/sklearn/cluster/_agglomerative.py:918, in AgglomerativeClustering.fit(self, X, y)
    900 """Fit the hierarchical clustering from features, or distance matrix.
    901 
    902 Parameters
   (...)
    915     Returns the fitted instance.
    916 """
    917 X = self._validate_data(X, ensure_min_samples=2, estimator=self)
--&gt; 918 return self._fit(X)

File ~/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/lib/python3.9/site-packages/sklearn/cluster/_agglomerative.py:955, in AgglomerativeClustering._fit(self, X)
    950     raise ValueError(
    951         "compute_full_tree must be True if distance_threshold is set."
    952     )
    954 if self.linkage == "ward" and self.affinity != "euclidean":
--&gt; 955     raise ValueError(
    956         "%s was provided as affinity. Ward can only "
    957         "work with euclidean distances." % (self.affinity,)
    958     )
    960 if self.linkage not in _TREE_BUILDERS:
    961     raise ValueError(
    962         "Unknown linkage type %s. Valid options are %s"
    963         % (self.linkage, _TREE_BUILDERS.keys())
    964     )

ValueError: precomputed was provided as affinity. Ward can only work with euclidean distances.
</code></pre></div>
<h3 dir="auto">Versions</h3>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="System:
    python: 3.9.7 (default, Oct 13 2021, 06:45:31)  [Clang 13.0.0 (clang-1300.0.29.3)]
executable: /Users/cristianpachon/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/bin/python
   machine: macOS-11.4-x86_64-i386-64bit

Python dependencies:
          pip: 21.3.1
   setuptools: 60.5.0
      sklearn: 1.0.2
        numpy: 1.22.2
        scipy: 1.8.0
       Cython: None
       pandas: 1.4.1
   matplotlib: 3.5.1
       joblib: 1.1.0
threadpoolctl: 3.1.0

Built with OpenMP: True"><pre class="notranslate">System:
    python: 3.9.7 (default, Oct 13 2021, 06:45:31)  [Clang 13.0.0 (clang-1300.0.29.3)]
executable: /Users/cristianpachon/Documents/technical/xai_cats_dogs/xai_cats_dogs_venv/bin/python
   machine: macOS-11.4-x86_64-i386-64bit

Python dependencies:
          pip: 21.3.1
   setuptools: 60.5.0
      sklearn: 1.0.2
        numpy: 1.22.2
        scipy: 1.8.0
       Cython: None
       pandas: 1.4.1
   matplotlib: 3.5.1
       joblib: 1.1.0
threadpoolctl: 3.1.0

Built with OpenMP: True</pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=""><pre class="notranslate"><code class="notranslate"></code></pre></div>
<h4 dir="auto">Description</h4>
<p dir="auto">Precomputed distances are treated as "unsupported" by AgglomerativeClustering, regardless of the provenance. (e.g. sklearn.metrics.euclidean_distances)</p>
<p dir="auto">This restriction makes it impossible to pass a off-memory (e.g. memory mapped) precomputed distance matrix, even if it is valid Euclidean distance.</p>
<h4 dir="auto">Steps/Code to Reproduce</h4>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import numpy as np

from sklearn.metrics import euclidean_distances
from sklearn.cluster import AgglomerativeClustering

X = np.array([[1, 2], [1, 4], [1, 0],[4, 2], [4, 4], [4, 0]])
c = AgglomerativeClustering(affinity='precomputed')
c.fit(euclidean_distances(X))"><pre class="notranslate"><code class="notranslate">import numpy as np

from sklearn.metrics import euclidean_distances
from sklearn.cluster import AgglomerativeClustering

X = np.array([[1, 2], [1, 4], [1, 0],[4, 2], [4, 4], [4, 0]])
c = AgglomerativeClustering(affinity='precomputed')
c.fit(euclidean_distances(X))
</code></pre></div>
<h4 dir="auto">Expected Results</h4>
<p dir="auto">This probably a bit complicated, as there is no reliable way to determine if the distance matrix actually contains Euclidean distances or is complete nonsense. As precomputed matrices are a somewhat advanced feature, simply relaxing the requirements and assuming users won't pass in invalid distances might be good enough, but that's a decision to be made by the maintainers.</p>
<p dir="auto">If the matrix was generated from sklearn.metrics, it might be possible to mark a provenance hint somewhere in the object, while it does feel a bit hacky.</p>
<h4 dir="auto">Actual Results</h4>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="In [21]: c.fit(euclidean_distances(X))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
&lt;ipython-input-21-38e0d7bfcae1&gt; in &lt;module&gt;
----&gt; 1 c.fit(euclidean_distances(X))

~/anaconda3/lib/python3.7/site-packages/sklearn/cluster/hierarchical.py in fit(self, X, y)
    823             raise ValueError(&quot;%s was provided as affinity. Ward can only &quot;
    824                              &quot;work with euclidean distances.&quot; %
--&gt; 825                              (self.affinity, ))
    826
    827         if self.linkage not in _TREE_BUILDERS:

ValueError: precomputed was provided as affinity. Ward can only work with euclidean distances."><pre class="notranslate"><code class="notranslate">In [21]: c.fit(euclidean_distances(X))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
&lt;ipython-input-21-38e0d7bfcae1&gt; in &lt;module&gt;
----&gt; 1 c.fit(euclidean_distances(X))

~/anaconda3/lib/python3.7/site-packages/sklearn/cluster/hierarchical.py in fit(self, X, y)
    823             raise ValueError("%s was provided as affinity. Ward can only "
    824                              "work with euclidean distances." %
--&gt; 825                              (self.affinity, ))
    826
    827         if self.linkage not in _TREE_BUILDERS:

ValueError: precomputed was provided as affinity. Ward can only work with euclidean distances.
</code></pre></div>
<h4 dir="auto">Versions</h4>
<p dir="auto">System:<br>
python: 3.7.3 (default, Mar 27 2019, 22:11:17)  [GCC 7.3.0]<br>
executable: /home/user/anaconda3/bin/python<br>
machine: Linux-5.0.0-31-generic-x86_64-with-debian-buster-sid</p>
<p dir="auto">Python deps:<br>
pip: 19.1.1<br>
setuptools: 41.4.0<br>
sklearn: 0.21.3<br>
numpy: 1.16.2<br>
scipy: 1.2.1<br>
Cython: 0.29.12<br>
pandas: 0.24.2</p>
<p dir="auto">This affects all platforms.</p>