iterative permutation library update

This commit is contained in:
2025-05-07 21:17:05 -04:00
parent 759bf06b76
commit a0d02475cc
20 changed files with 770 additions and 72 deletions
+1 -7
View File
@@ -3,14 +3,8 @@
{ {
"path": "." "path": "."
}, },
{
"path": "../../sourceprojs23/camsimglib3"
},
{ {
"path": "../../sourceprojs23/amsmathutil2" "path": "../../sourceprojs23/amsmathutil2"
},
{
"path": "../../sourceprojs23/amscppfilesys3"
} }
] ]
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+121 -25
View File
@@ -4,6 +4,61 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <new>
extern "C"
{
////////////////////////////////////////////
//Basic operations on preallocated buffers//
//for C library export //
////////////////////////////////////////////
static const int amsperm1_success = 0;
static const int amsperm1_failure = -1;
//basic factorial found with integer loop
int amsperm1_factorial(int n);
//Is the multi-index in the appropriate factoriadic range?
// position 0 can range from [0 to length)
// position 1 can range from [0 to (length-1))
//parameters:
// int mindex[length] - multi-index input
// int length - multi-index length output
bool amsperm1_mindex_valid(int *mindex, int length);
bool amsperm1_perm_valid(int *perm, int *wrk, int length);
//returns a factoriadic multi-index for a given index.
//Each factoriadic multi-index corresponds to a permutation according to a simple algorithm
// factoriadic indices range from (ex 4 length case) {0,0,0,0} to {3,2,1,0}
// parameters:
// index - [0 to factorial(length)) index of permutation
// mindex - factoriadic multi-index output (size=length)
// length - length of the permutation (number of elements to permute)
// return value:
// 0: success
// -1 : privided index was out of the valid range
int amsperm1_index_to_mindex(int index, int *mindex, int length);
int amsperm1_mindex_to_index(int *mindex, int length);
int amsperm1_mindex_to_perm(int *mindex, int *perm, int *wrk, int length);
int amsperm1_perm_to_mindex(int *perm, int *mindex, int *wrk, int length);
int amsperm1_index_to_perm(int index, int *perm, int *mindex, int *wrk, int length);
int amsperm1_perm_to_index(int *perm, int *mindex, int *wrk, int length);
void amsperm1_test_basicperm1();
}; //end extern C
namespace ams namespace ams
@@ -11,42 +66,83 @@ namespace ams
namespace perm namespace perm
{ {
//Basic operations on preallocated buffers
//for later C library export
static const int perm_success = 0; static const int perm_success = 0;
static const int perm_failure = -1; static const int perm_failure = -1;
int factorial(int n); int factorial(int n);
int index_to_mindex(int index, int *mindex, int ndim); //Iteratable Permutation Class
//Provides an object for iterating over permutations of low dimension
int mindex_to_index(int *mindex, int ndim); //These can be stepped along
int mindex_to_perm(int *mindex, int *perm, int *wrk, int ndim); class ipermutation
int perm_to_mindex(int *perm, int *mindex, int *wrk, int ndim);
bool perm_valid(int *perm, int ndim);
bool mindex_valid(int *mindex, int ndim);
void index_to_perm(int index, int *perm, int ndim);
int perm_to_index(int *perm, int ndim);
//Permutation class
class permutation
{ {
public: public:
int dim; int length;
int *data; int *perm; //permutation
int index; //do I want these also stored with the permutation variable?
int *mind; //factoriadic multi-index
int *wrk; //working memory buffer
ipermutation();
ipermutation(const int _length);
ipermutation(const int _index, const int _length);
ipermutation(const int *parray, const int _length);
~ipermutation();
ipermutation(const ipermutation& other);
int resize(const int _nlength);
ipermutation operator=(const ipermutation &other);
int& operator[](const int ind);
const int& operator[](const int ind) const;
bool valid() const;
bool operator==(const ipermutation other) const;
//pre-increment operator
ipermutation& operator++();
ipermutation& operator--();
//post-increment operators
ipermutation operator++(int);
ipermutation operator--(int);
ipermutation operator*(const ipermutation b) const; //compose permutations
ipermutation inverse() const; //invert permutation
//returns first and last permutations of a given lengthension
static ipermutation first(int _nlength);
static ipermutation last(int _nlength);
int levi_civita() const;
void print(int style=0);
permutation();
permutation(int _dim);
~permutation();
}; };
ipermutation ipermutation_first(int _nlength);
ipermutation ipermutation_last(int _nlength);
int levi_civita(const ipermutation p);
void test_ipermutation1();
// non-indexable permutation class
// the same permutation logic, but for larger permutation sets
// can't index, can't increment or decrement a sequence, but can still
// compose, test validity, test levi_civita sign, apply to arrays, etc.
class permutation
{
public:
int length;
int *data;
};
}; //end namespace perm }; //end namespace perm
}; //end namespace ams }; //end namespace ams
+430 -6
View File
@@ -5,21 +5,445 @@ namespace ams
namespace perm namespace perm
{ {
permutation::permutation() ipermutation::ipermutation()
{ {
dim = 0; length = 0;
data = NULL; perm = NULL;
index = -1;
mind = NULL;
wrk = NULL;
return; return;
} }
permutation::~permutation() ipermutation::~ipermutation()
{ {
if(data!=NULL) {delete[] data; data = NULL;} if(perm!=NULL) {delete[] perm; perm = NULL;}
dim = 0; if(mind!=NULL) {delete[] mind; mind = NULL;}
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
length = 0;
index = -1;
return; return;
} }
ipermutation::ipermutation(const int _length)
{
length = 0;
perm = NULL;
index = -1;
mind = NULL;
wrk = NULL;
this->resize(_length);
}
ipermutation::ipermutation(const int _index, const int _length)
{
int res = perm_failure;
length = 0;
perm = NULL;
index = -1;
mind = NULL;
wrk = NULL;
if(_length>0)
{
res = this->resize(_length);
if(res==perm_success)
{
index = _index;
amsperm1_index_to_mindex(index,mind,length);
amsperm1_mindex_to_perm(mind,perm,wrk,length);
}
}
}
ipermutation::ipermutation(const int *parray, const int _length)
{
int I;
int res = perm_failure;
length = 0;
perm = NULL;
index = -1;
mind = NULL;
wrk = NULL;
if(_length>0)
{
res = this->resize(_length);
if(res==perm_success)
{
for(I=0;I<length;I++) perm[I] = parray[I];
amsperm1_perm_to_mindex(perm,mind,wrk,length);
index = amsperm1_mindex_to_index(mind,length);
}
}
return;
}
int ipermutation::resize(const int _nlength)
{
int ret = perm_success;
int *newperm = NULL;
int *newmind = NULL;
int *newwrk = NULL;
int newind;
int I;
if(_nlength<=0)
{
length = 0;
index = -1;
if(perm!=NULL) {delete[] perm; perm=NULL;}
if(mind!=NULL) {delete[] mind; mind=NULL;}
if(wrk!=NULL) {delete[] wrk; wrk=NULL;}
return ret;
}
newperm = new(std::nothrow) int[_nlength];
newmind = new(std::nothrow) int[_nlength];
newwrk = new(std::nothrow) int[_nlength];
if(newperm==NULL || newmind == NULL || newwrk == NULL)
{
if(newperm!=NULL) {delete[] newperm; newperm=NULL;}
if(newmind!=NULL) {delete[] newmind; newmind=NULL;}
if(newwrk!=NULL) {delete[] newwrk; newwrk=NULL;}
ret = perm_failure;
return ret;
}
for(I=0;I<length && I<_nlength; I++)
{
newmind[I] = mind[I];
}
for(I=length;I<_nlength;I++) newmind[I] = 0;
newind = amsperm1_mindex_to_index(newmind,_nlength);
amsperm1_mindex_to_perm(newmind,newperm,newwrk,_nlength);
if(perm!=NULL) {delete[] perm; perm = NULL;}
if(mind!=NULL) {delete[] mind; mind = NULL;}
if(wrk!=NULL) {delete[] wrk; wrk = NULL;}
length = 0;
index = -1;
length = _nlength;
index = newind;
perm = newperm;
mind = newmind;
wrk = newwrk;
return ret;
}
ipermutation::ipermutation(const ipermutation& other)
{
int res;
length = 0;
perm = NULL;
index = -1;
mind = NULL;
wrk = NULL;
int I;
if(this!=&other)
{
res = this->resize(other.length);
if(res==perm_success)
{
for(I=0;I<length;I++)
{
this->perm[I] = other.perm[I];
this->wrk[I] = other.wrk[I];
this->mind[I] = other.mind[I];
this->index = other.index;
}
}
}
}
ipermutation ipermutation::operator=(const ipermutation &other)
{
int res;
int I;
if(this!=&other)
{
res = this->resize(other.length);
if(res==perm_success)
{
for(I=0;I<length;I++)
{
this->perm[I] = other.perm[I];
this->wrk[I] = other.wrk[I];
this->mind[I] = other.mind[I];
this->index = other.index;
}
}
}
return *this;
}
int& ipermutation::operator[](const int ind)
{
return perm[ind];
}
const int& ipermutation::operator[](const int ind) const
{
return perm[ind];
}
int factorial(int n)
{
return amsperm1_factorial(n);
}
bool ipermutation::valid() const
{
bool ret = 1;
int *lmind = NULL;
int *lwrk = NULL;
int *lperm = NULL;
if(index<0 || index>=factorial(length))
{
ret = 0; return ret;
}
//other tests - skip for speed?
return ret;
}
bool ipermutation::operator==(const ipermutation other) const
{
bool ret = 1;
int I;
if(length!=other.length)
{
ret = 0; return ret;
}
if(index != other.index)
{
ret = 0; return ret;
}
//additional tests (skip for speed?)
for(I=0;I<length && I<other.length;I++)
{
if(perm[I]!=other.perm[I]) {ret = 0; break;}
if(mind[I]!=other.mind[I]) {ret = 0; break;}
}
return ret;
}
ipermutation ipermutation_first(int _nlength)
{
ipermutation ret = ipermutation(0,_nlength);
return ret;
}
ipermutation ipermutation_last(int _nlength)
{
int f = factorial(_nlength);
ipermutation ret = ipermutation(f-1,_nlength);
return ret;
}
int levi_civita(const ipermutation p)
{
int ret = 0;
bool v = p.valid();
if(v)
{
ret = 2*(!(p.index%2))-1;
}
return ret;
}
//pre-increment operator
ipermutation& ipermutation::operator++()
{
int I;
if(valid())
{
if(index+1>=0 && index+1<factorial(length))
{
index = index + 1;
amsperm1_index_to_mindex(index,mind,length);
amsperm1_mindex_to_perm(mind,perm,wrk,length);
}
else
{
index = -1;
for(I=0;I<length;I++)
{
perm[I] = -1;
mind[I] = -1;
wrk[I] = 0;
}
}
}
return *this;
}
ipermutation& ipermutation::operator--()
{
int I;
if(valid())
{
if(index-1>=0 && index-1<factorial(length))
{
index = index - 1;
amsperm1_index_to_mindex(index,mind,length);
amsperm1_mindex_to_perm(mind,perm,wrk,length);
}
else
{
index = -1;
for(I=0;I<length;I++)
{
perm[I] = -1;
mind[I] = -1;
wrk[I] = 0;
}
}
}
return *this;
}
//post-increment operators
ipermutation ipermutation::operator++(int)
{
ipermutation ret = *this;
//++ret;
this->operator++();
return ret;
}
ipermutation ipermutation::operator--(int)
{
ipermutation ret = *this;
//--ret;
this->operator--();
return ret;
}
void ipermutation::print(int style)
{
int I;
if(style==0)
{
printf("{");
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
printf("%d}",perm[length-1]);
}
else if(style==1)
{
printf("%d:{",index);
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
printf("%d}",perm[length-1]);
}
else if(style==2)
{
printf("ipermutation[%d]:{",index);
for(I=0;I<length-1;I++) printf("%d,",perm[I]);
printf("%d}",perm[length-1]);
}
return;
}
void test_ipermutation1()
{
ipermutation a = ipermutation(4);
ipermutation *b = NULL;
b = new(std::nothrow) ipermutation(4);
a.print(); printf("\n");
b->print(); printf("\n");
a++;
a.print(); printf("\n");
++a; a.print(); printf("\n");
a++;
a++;
a++;
*b = a;
b->print(2); printf("\n");
b->resize(3);
a.resize(5);
a.print(); printf("\n");
b->print(); printf("\n");
int I;
*b = ipermutation_first(3);
for(I=0;I<8;I++)
{
b->print(2); printf("\n");
(*b)++;
}
for(a=ipermutation_last(3);a.valid();a--)
{
a.print(2); printf("\n");
}
delete(b);
return;
}
//compose permutations
ipermutation ipermutation::operator*(const ipermutation b) const
{
ipermutation ret = ipermutation(this->length);
return ret;
}
//invert permutation
ipermutation ipermutation::inverse() const
{
ipermutation ret = ipermutation(this->length);
return ret;
}
//returns first and last permutations of a given lengthension
ipermutation ipermutation::first(int _nlength)
{
ipermutation ret = ipermutation(0,_nlength);
return ret;
}
ipermutation ipermutation::last(int _nlength)
{
int f = factorial(_nlength);
ipermutation ret = ipermutation(f-1,_nlength);
return ret;
}
int ipermutation::levi_civita() const
{
int ret = 0;
if(valid())
{
ret = 2*(!(index%2))-1;
}
return ret;
}
}; //end namespace perm }; //end namespace perm
}; //end namespace ams }; //end namespace ams
+215 -32
View File
@@ -1,16 +1,14 @@
#include <amscppperm1/amscppperm1.hpp> #include <amscppperm1/amscppperm1.hpp>
namespace ams extern "C"
{
namespace perm
{ {
//basic factorial found with integer loop //basic factorial found with integer loop
int factorial(int n) int amsperm1_factorial(int n)
{ {
int I; int I;
int ret = 0; int ret = 0;
if(n>=0) if(n>=0 && n<=12)
{ {
ret = 1; ret = 1;
for(I=0;I<n;I++) for(I=0;I<n;I++)
@@ -18,29 +16,33 @@ namespace perm
ret = ret*(I+1); ret = ret*(I+1);
} }
} }
if(n>12)
{
ret = -1; //overflow error
}
return ret; return ret;
} }
//returns a factoriadic multi-index for a given index. //returns a factoriadic multi-index for a given index.
//Each factoriadic multi-index corresponds to a permutation according to a simple algorithm //Each factoriadic multi-index corresponds to a permutation according to a simple algorithm
// factoriadic indices range from (ex 4 dim case) {0,0,0,0} to {3,2,1,0} // factoriadic indices range from (ex 4 length case) {0,0,0,0} to {3,2,1,0}
// parameters: // parameters:
// index - [0 to factorial(ndim)) index of permutation // index - [0 to factorial(length)) index of permutation
// mindex - factoriadic multi-index output (size=ndim) // mindex - factoriadic multi-index output (size=length)
// ndim - dimension of the permutation (number of elements to permute) // length - length of the permutation (number of elements to permute)
// return value: // return value:
// 0: success // 0: success
// -1 : privided index was out of the valid range // -1 : privided index was out of the valid range
int index_to_mindex(int index, int *mindex, int ndim) int amsperm1_index_to_mindex(int index, int *mindex, int length)
{ {
int ret = -1; int ret = amsperm1_failure;
int I,J,K; int I,J,K;
if(index>=0 && index<factorial(ndim)) if(index>=0 && index<amsperm1_factorial(length))
{ {
ret = 0; //success ret = amsperm1_success; //success
K = ndim; K = length;
J = index; J = index;
for(I=0;I<ndim;I++) for(I=0;I<length;I++)
{ {
mindex[I] = J%K; mindex[I] = J%K;
J = (J - mindex[I])/K; J = (J - mindex[I])/K;
@@ -49,9 +51,9 @@ namespace perm
} }
else else
{ {
ret = -1; //error ret = amsperm1_failure; //error
//invalid index //invalid index
for(I=0;I<ndim;I++) for(I=0;I<length;I++)
mindex[I] = -1; mindex[I] = -1;
} }
@@ -60,15 +62,18 @@ namespace perm
} }
//Is the multi-index in the appropriate factoriadic range? //Is the multi-index in the appropriate factoriadic range?
// position 0 can range from [0 to ndim) // position 0 can range from [0 to length)
// position 1 can range from [0 to (ndim-1)) // position 1 can range from [0 to (length-1))
bool mindex_valid(int *mindex, int ndim) //parameters:
// int mindex[length] - multi-index input
// int length - multi-index length output
bool amsperm1_mindex_valid(int *mindex, int length)
{ {
int I; int I;
bool ret = 1; bool ret = 1;
for(I=0;I<ndim;I++) for(I=0;I<length;I++)
{ {
if(mindex[I]<0 || mindex[I]>=(ndim-I)) if(mindex[I]<0 || mindex[I]>=(length-I))
{ {
ret = 0; ret = 0;
break; break;
@@ -77,19 +82,19 @@ namespace perm
return ret; return ret;
} }
int mindex_to_index(int *mindex, int ndim) int amsperm1_mindex_to_index(int *mindex, int length)
{ {
int ret = -1; int ret = -1;
int I; int I;
int K; int K;
if(mindex_valid(mindex,ndim)) if(amsperm1_mindex_valid(mindex,length))
{ {
K = 1; K = 1;
ret = 0; ret = 0;
for(I=0;I<ndim;I++) for(I=0;I<length;I++)
{ {
ret = ret + mindex[I]*K; ret = ret + mindex[I]*K;
K = K*(ndim-I); K = K*(length-I);
} }
} }
else else
@@ -101,20 +106,198 @@ namespace perm
return ret; return ret;
} }
int mindex_to_perm(int *mindex, int *perm, int *wrk, int ndim) //multi-index to permutation
//parameters:
// mindex[length] - input factoriadic multi-index
// perm[length] - output permutation
// wrk[length] - working memory buffer
// length - length of permutation
//return values:
// amsperm1_success - result should be a valid permutation
// amsperm1_failure - invalid multi-index supplied
int amsperm1_mindex_to_perm(int *mindex, int *perm, int *wrk, int length)
{ {
int ret = -1; int I,J,K,L;
int ret = amsperm1_failure;
if(!amsperm1_mindex_valid(mindex,length))
{
ret = amsperm1_failure;
for(I=0;I<length;I++) perm[I] = -1;
return ret;
}
else
{
for(I=0;I<length;I++) wrk[I] = 0;
for(I=0;I<length;I++)
{
J = mindex[I];
L = 0;
for(K=0;K<length;K++)
{
if(wrk[K]==0)
{
L = L + 1;
if(L==(J+1))
{
perm[I] = K;
wrk[K] = 1;
break;
}
}
}
}
ret = amsperm1_success;
}
return ret; return ret;
} }
int perm_to_mindex(int *perm, int *mindex, int *wrk, int ndim) //check validity of permutation
//parameters:
//int perm[length] - input permutation
//int wrk[length] - working buffer
//int length - permutation array length
//return values:
// 1 - is a valid permutation
// 0 - is not a valid permutation
bool amsperm1_perm_valid(int *perm, int *wrk, int length)
{ {
int ret = -1; bool ret = 1;
int I;
for(I=0;I<length;I++) wrk[I] = 0;
for(I=0;I<length;I++)
{
if(perm[I]<0 || perm[I]>=length)
{
ret = 0;
break;
}
if(wrk[perm[I]]==1)
{
ret = 0;
break;
}
else
{
wrk[perm[I]]=1;
}
}
return ret;
}
int amsperm1_perm_to_mindex(int *perm, int *mindex, int *wrk, int length)
{
int ret = amsperm1_failure;
int I,J,K,L;
if(!amsperm1_perm_valid(perm,wrk,length))
{
for(I=0;I<length;I++) mindex[I] = -1;
ret = amsperm1_failure;
return ret;
}
for(I=0;I<length;I++) wrk[I]=0;
for(I=0;I<length;I++)
{
J = perm[I];
L = 0;
for(K=0;K<=J;K++)
{
if(wrk[K]==0)
{
L = L + 1;
}
}
wrk[J] = 1;
mindex[I] = L-1;
}
ret = amsperm1_success;
return ret; return ret;
} }
int amsperm1_index_to_perm(int index, int *perm, int *mindex, int *wrk, int length)
{
int ret = amsperm1_failure;
}; //end namespace perm if(index<0 || index>=amsperm1_factorial(length))
}; //end namespace ams {
return ret;
}
amsperm1_index_to_mindex(index,mindex,length);
amsperm1_mindex_to_perm(mindex,perm,wrk,length);
ret = amsperm1_success;
return ret;
}
int amsperm1_perm_to_index(int *perm, int *mindex, int *wrk, int length)
{
int ret = -1;
if(!amsperm1_perm_valid(perm,wrk,length))
{
return ret;
}
amsperm1_perm_to_mindex(perm,mindex,wrk,length);
ret = amsperm1_mindex_to_index(mindex,length);
return ret;
}
static void _intl_print_array(int *array, int length)
{
int I;
printf("{");
for(I=0;I<length-1;I++)
{
printf("%d,",array[I]);
}
printf("%d}",array[length-1]);
return;
}
void amsperm1_test_basicperm1()
{
int I,J;
int length = 4;
int *perm1 = NULL;
int *perm2 = NULL;
int *mind1 = NULL;
int *mind2 = NULL;
int *wrk = NULL;
perm1 = new(std::nothrow) int[length];
perm2 = new(std::nothrow) int[length];
mind1 = new(std::nothrow) int[length];
mind2 = new(std::nothrow) int[length];
wrk = new(std::nothrow) int[length];
printf("Tests of basic permutation and multi-index operations..\n");
for(I=-1;I<amsperm1_factorial(length)+1;I++)
{
amsperm1_index_to_mindex(I,mind1,length);
J = amsperm1_mindex_to_index(mind1,length);
amsperm1_mindex_to_perm(mind1,perm1,wrk,length);
amsperm1_perm_to_mindex(perm1,mind2,wrk,length);
printf("%d\t",I);
_intl_print_array(mind1,length); printf("\t");
_intl_print_array(perm1,length); printf("\t");
_intl_print_array(mind2,length); printf("\t");
printf("%d\n",J);
}
delete[] perm1;
delete[] perm2;
delete[] mind1;
delete[] mind2;
delete[] wrk;
return;
}
}; //end extern "C"
+3 -2
View File
@@ -3,7 +3,8 @@
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
int ret = 0; int ret = 0;
printf("ams c++ project template tests.\n"); printf("ams c++ permutation library tests.\n");
//amsperm1_test_basicperm1();
//ams::perm::test_ipermutation1();
return ret; return ret;
} }