Repository: pykeen/pykeen
Issue: NodePiece: A potential issue with anchors not being sorted according to distance from target node
Root cause: Algorithmic Error

### Describe the bug

When creating an instance of the NodePiece class (using the FB15k237 training triples as dataset) and taking the 50 nodes with the highest degree as anchors using `DegreeAnchorSelection` (no relations are being used in the example) and choosing for each node it's 5 closest anchors (using the default `CSGraphAnchorSearcher`), the anchors selected to represent nodes seem not to be sorted in descending order by their distance from the respective node.

### How to reproduce

Running the following:

```python
from pykeen.models import NodePiece
from pykeen.datasets import FB15k237

model = NodePiece(
    random_seed=126,
    triples_factory=dataset.training,
    tokenizers=["AnchorTokenizer", " RelationTokenizer"],
    num_tokens=[5, 0],
    tokenizers_kwargs=[
        dict(
            selection="DegreeAnchorSelection",
            selection_kwargs=dict(
                num_anchors=50,
            ),
            searcher="CSGraphAnchorSearcher",
            searcher_kwargs=dict(),
        ),
        dict(),
    ],
    embedding_dim=16,
)
```
Example 1:

Using the above model with the training triples of FB15k237 results in the following list containing the IDs (IDs are used as they are defined in `dataset.training.mapped_triples`) of the 5 anchor nodes that are selected to represent the node with ID 0

`
[10390, 10532, 11497, 12940, 5460]
`

The respective distance (in order as they appear in the above ID list) from node 0 is

`
[2,2,2,1,2]
`

Although node 12940 is a direct neighbour of node 0, it is not listed in the first position.

Example 2:

The IDs of the 5 anchors that are chosen to represent node 2 are

`
[10033,7835,10165,12940,10390]
`

The respective distance (in order as they appear in the above ID list) from node 2 is

`
[2,2,1,1,2]
`

While the order of anchors has no effect when the standard aggregation function (mean) is used as the encoder, it should have an effect when e.g. a MLP is used instead. Could there be a problem with the order of the anchors or did I just specify something wrong?

### Environment

| Key             | Value                    |
|-----------------|--------------------------|
| OS              | posix                    |
| Platform        | Darwin                   |
| Release         | 22.6.0                   |
| Time            | Tue Sep 12 15:08:55 2023 |
| Python          | 3.9.5                    |
| PyKEEN          | 1.10.2-dev               |
| PyKEEN Hash     | 5ff3597b                 |
| PyKEEN Branch   | master                   |
| PyTorch         | 2.0.1                    |
| CUDA Available? | false                    |
| CUDA Version    | N/A                      |
| cuDNN Version   | N/A                      |

### Additional information

_No response_

### Issue Template Checks

- [X] This is not a feature request (use a different issue template if it is)
- [X] This is not a question (use the [discussions](https://github.com/pykeen/pykeen/discussions/new) forum instead)
- [X] I've read the text explaining why including environment information is important and understand if I omit this information that my issue will be dismissed

Hi @martytom ,

indeed it looks like the `CSGraphAnchorSearcher` computes the k-closest anchor nodes, but does not guarantee any order between them:

https://github.com/pykeen/pykeen/blob/5ff3597b18ab9a220e34361d3c3f262060811df1/src/pykeen/nn/node_piece/anchor_search.py#L82-L85

I do not remember whether this was an explicit choice, but @migalkin may be able to tell whether this is consistent with the NodePiece reference implementation / paper version 😉 

Indeed, that's not consistent with the OG implementation, anchors after `argpartition()` should be further sorted by distance. iirc, @mberr went for argpartition for efficiency reasons, though adding a sorting on top of the output should be a negligible compute effort

@migalkin I opened a PR to fix this: https://github.com/pykeen/pykeen/pull/1318 🙂 

@martytom , the issue has been fixed with #1318 ; until our next release, you need to install from source to get access to it, cf. https://github.com/pykeen/pykeen#installation--