About the permutation returned by `torch.sort`

username: dallonsi
cooked: <p>Hi !<br>
Say I want to use sort this list with torch: <code>[1, 5, 3, 4]</code>.<br>
The following code in Python 3.x:</p>
<pre><code class="lang-auto">from torch import tensor
import torch

t = tensor([1,5,3,4])
t = torch.sort(t, descending=True)

print(t)
</code></pre>
<p>returns</p>
<pre><code class="lang-auto">torch.return_types.sort(
values=tensor([5, 4, 3, 1]),
indices=tensor([1, 3, 2, 0]))
</code></pre>
<p>The list <code>indices</code> from the output is a permutation of 0, 1, 2, 3. It maps the output values <code>[5, 4, 3, 1]</code> to the input list  <code>[1, 5, 3, 4]</code>. Indeed : 5 goes to position <strong>1</strong>, 4 to position <strong>3</strong>, 3 to position <strong>2</strong> and 1 to position <strong>0</strong> : <code>[1, 3, 2, 0]</code>.</p>
<p>What would be a simple and <strong>efficient</strong> way to get the inverse of this permutation, that is the permutation that maps the input list <code>[1, 5, 3, 4]</code> to the output list <code>[5, 4, 3, 1]</code> ? This inverse is in our case: <code>[3, 0, 2, 1]</code>.</p>
<p>Thanks a lot !</p>

username: googlebot
cooked: <p>I had this old code, based on rnn.utils:</p>
<pre><code class="lang-auto">def invert_permutation(permutation):
    output = torch.empty_like(permutation)
    output.scatter_(0, permutation,
                    torch.arange(0, len(permutation), dtype=torch.int64, device=permutation.device))
    return output
</code></pre>

username: KFrank
cooked: <p>Hi Damien (and Alex)!</p>
<aside class="quote no-group quote-modified" data-username="dallonsi" data-post="1" data-topic="76162" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/d/e56c9b/48.png" class="avatar"> dallonsi:</div>
<blockquote>
<p>What would be a simple and <strong>efficient</strong> way to get the inverse of this permutation … ?</p>
</blockquote>
</aside>
<p>In my mind, the cleanest approach is to take the <code>argsort</code> of the<br>
permutation:</p>
<pre data-code-wrap="python"><code class="lang-python">import torch
torch.__version__

t = torch.LongTensor ([1, 5, 3, 4])
perm = torch.sort (t, descending = True)[1]
perm
inverse = torch.sort (perm)[1]   # invert permutation
inverse
perm[inverse]    # check inverse
inverse[perm]    # check inverse again
</code></pre>
<p>Here is the output:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'0.3.0b0+591e73e'
&gt;&gt;&gt;
&gt;&gt;&gt; t = torch.LongTensor ([1, 5, 3, 4])
&gt;&gt;&gt; perm = torch.sort (t, descending = True)[1]
&gt;&gt;&gt; perm

 1
 3
 2
 0
[torch.LongTensor of size 4]

&gt;&gt;&gt; inverse = torch.sort (perm)[1]   # invert permutation
&gt;&gt;&gt; inverse

 3
 0
 2
 1
[torch.LongTensor of size 4]

&gt;&gt;&gt; perm[inverse]    # check inverse

 0
 1
 2
 3
[torch.LongTensor of size 4]

&gt;&gt;&gt; inverse[perm]    # check inverse again

 0
 1
 2
 3
[torch.LongTensor of size 4]
</code></pre>
<p>This is, however, an <code>n log (n)</code> algorithm.  Nonetheless, by using<br>
pytorch’s built-in <code>sort</code> function, it ought to be quite fast.</p>
<p>Best.</p>
<p>K. Frank</p>

username: dallonsi
cooked: <p>Thanks <a class="mention" href="/u/kfrank">@KFrank</a>, taking the argsort of a permutation (in increasing order) gives its inverse! <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>