permutation: in-place inversion
This commit is contained in:
@@ -72,6 +72,48 @@ for(T i=1; i<=n; ++i) if(used[i]!=1) return 0;
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//in-place o(n^2) cf. arxiv 1901.01926v2
|
||||||
|
//better alg. exists but more complicated
|
||||||
|
template <typename T>
|
||||||
|
void NRPerm<T>::reverse_cycle(int start)
|
||||||
|
{
|
||||||
|
int cur=(*this)[start];
|
||||||
|
int prev=start;
|
||||||
|
while(cur!=start)
|
||||||
|
{
|
||||||
|
int next=(*this)[cur];
|
||||||
|
(*this)[cur]=prev;
|
||||||
|
prev=cur;
|
||||||
|
cur=next;
|
||||||
|
}
|
||||||
|
(*this)[start]=prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int NRPerm<T>::cycle_leader(int start) const
|
||||||
|
{
|
||||||
|
int cur=(*this)[start];
|
||||||
|
int smallest=start;
|
||||||
|
while(cur!=start)
|
||||||
|
{
|
||||||
|
if(cur<smallest) smallest=cur;
|
||||||
|
cur=(*this)[cur];
|
||||||
|
}
|
||||||
|
return smallest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void NRPerm<T>::inverseme()
|
||||||
|
{
|
||||||
|
for(int i=1; i<=size(); ++i) if(cycle_leader(i)==i) reverse_cycle(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NRPerm<T> NRPerm<T>::inverse() const
|
NRPerm<T> NRPerm<T>::inverse() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ public:
|
|||||||
bool is_identity() const;
|
bool is_identity() const;
|
||||||
CompressedPartition<T> cycles() const {return CyclePerm<T>(*this).cycles(size());};
|
CompressedPartition<T> cycles() const {return CyclePerm<T>(*this).cycles(size());};
|
||||||
NRPerm inverse() const;
|
NRPerm inverse() const;
|
||||||
|
void reverse_cycle(int i); //aux for inverseme
|
||||||
|
int cycle_leader(int i) const; //aux for inverseme
|
||||||
|
void inverseme(); //in-place
|
||||||
NRPerm reverse() const; //backward order
|
NRPerm reverse() const; //backward order
|
||||||
NRPerm operator&(const NRPerm &rhs) const; //concatenate the permutations this,rhs, renumbering rhs (not commutative)
|
NRPerm operator&(const NRPerm &rhs) const; //concatenate the permutations this,rhs, renumbering rhs (not commutative)
|
||||||
NRPerm operator|(const NRPerm &rhs) const; //concatenate the permutations rhs,this, renumbering rhs (not commutative)
|
NRPerm operator|(const NRPerm &rhs) const; //concatenate the permutations rhs,this, renumbering rhs (not commutative)
|
||||||
|
|||||||
@@ -4788,7 +4788,7 @@ cout<<tt;
|
|||||||
cout <<"Error = "<<(t-tt).norm()<<endl;
|
cout <<"Error = "<<(t-tt).norm()<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1)
|
if(0)
|
||||||
{
|
{
|
||||||
Tensor<double> tt;
|
Tensor<double> tt;
|
||||||
tt.numpy_read(argv[1]);
|
tt.numpy_read(argv[1]);
|
||||||
@@ -4798,4 +4798,15 @@ cout<<"part\n"<<tt.subtensor1(1);
|
|||||||
cout<<"part\n"<<tt.subtensor1(2);
|
cout<<"part\n"<<tt.subtensor1(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(1)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
cin >>n;
|
||||||
|
NRPerm<int> p(n); p.randomize();
|
||||||
|
NRPerm<int> q=p.inverse();
|
||||||
|
p.inverseme();
|
||||||
|
if(p!=q) laerror("inverseme failed");
|
||||||
|
else cout <<p<<"OK\n";
|
||||||
|
}
|
||||||
|
|
||||||
}//main
|
}//main
|
||||||
|
|||||||
Reference in New Issue
Block a user