Code to generate permutations

 

In order to generate different combinations, I believe I need to work with permutations.

Every setup has A entries with 2 possibilities ( true/false).

Examples:

A = 5

entry1 entry2 entry3 entry4 entry 5

Combination 1: false false false false false
Combination 2: false false false false true
Combination 3: false false false true false
Combination 4: false false true false false
Combination 5: false true false false false
Combination 6: true false false false false
Combination 7: false false false true true
Combination 8: false false true false true
Combination 9: false true false false true
etc etc

Now I was wondering how to put this in code.

At the moment I can't get any further than this:

int A = 5;
bool Switch[1000,5];
int Combinations = 0;

   for(int X1 = 0; X1 < A; X1 ++){
      for(int X2 = 0; X2< 2; X2++){
         if(){                     // condition to set entry to be false
            Switch[Combinations,X1] = False;
         }
         if(){                     // condition to set entry to be True
            Switch[Combinations,X1] = True;
         }
      Combinations++;
      }
    }

Does anybody have an idea? I think you need to be good a thinking in a wider dimension here. I'm not able to.

 

If A is never greater than 31 - one option is to use bitwise operators... ( a single ampersand, a single | etc) in an increasing integer. As when you count in binary you are generating the same pattern you want...

eg.

1 = 001

2 = 010

3 = 011

4 = 100

5 = 101

6 = 110

7 = 111 etc. where '1' bit is true, and 0 bit is false.


So you treat the integer as an array of up to 31 bits. (its actually 32 bits, but we want to avoid the last bit as this may create issues with -ve numbers )


Eg for A = 5 = 5 bits = in binary is from 00000(0) to 11111(31) - so you want to count through from 0 to 31 to generate all 5 bit combinations.....

31 (ie 11111) = 2^5-1 so...

EDIT: Fixed boolean expression - still untested!

//untested - constants here are in Hex format as its relatively easy to 'visualise' the underlying binary format 
#define ENTRY_1 0x01
#define ENTRY_2 0x02
#define ENTRY_3 0x04
#define ENTRY_4 0x08
#define ENTRY_5 0x10

int max = MathPow(2,A);

// Repeatedly adding 1 cycles through all combinations of bits.

for(int  combination = 0 ; combination < max ; combination++ ) {

   if ( (combination & ENTRY_1) != 0 )  {  then entry1 is enabled }

   if ( (combination & ENTRY_2) != 0 )  {  then entry2 is enabled }

   if ( (combination & ENTRY_3) != 0 )  {  then entry3 is enabled }

   if ( (combination & ENTRY_4) != 0 )  {  then entry4 is enabled }

   if ( (combination & ENTRY_5) != 0 )  {  then entry5 is enabled }

}


I tend to use extra brackets around bitwise operations - there are not needed here - but anything more complicated I like to see them ....


Instead of all the ENTRY_X constants you could also replace if (combination & ENTRY_X) with a function if(entryEnabled(combination,1)) eg

//untested

bool entryEnabled(int combination,int entryNumber)
{

  int bit = MathPow(2,entryNumber - 1);

  return ((combination & bit)!=0); //fixed boolean 

}


Just be careful MathPow returns correct integer (it should but I've never checked mql4's implementation, but I've come across some implementations in other languages which are not so accurate (issues with doubles) and also are VERY slow using logarithm series calculations even for simple things like powers of two... in which case it may be better, and a lot faster to just use a loop that multiplies by two

//untested

bool entryEnabled(int combination,int entryNumber)
{

  int bit = 1;

  for(int i = 1 ; i < entryNumber ; i++) bit *= 2;
  return ((combination & bit) !=0); //fixed boolean

}

Though for performance, constants are the best.

 

Thanks for the reply Ydrol.


The A value is fixed at 21. I've tried to work with your first option and worked it out to the code blow. However I believe I'm doing something wrong as now the results are:


combination 1: all values false

combination 2: all values true

combination 3: all values true

etc

The total number of combinations generated is correct though (2097152).

Do you see where this is going wrong? I think it has something to do with this part:

 if ( (combination && ENTRY_1) ) {....

combination is here just a number and can have a value from 0 up to 2097152.

#define ENTRY_1 0x01
#define ENTRY_2 0x02
#define ENTRY_3 0x04
#define ENTRY_4 0x08
#define ENTRY_5 0x10
#define ENTRY_6 0x12
#define ENTRY_7 0x14
#define ENTRY_8 0x16
#define ENTRY_9 0x18
#define ENTRY_10 0x20
#define ENTRY_11 0x22
#define ENTRY_12 0x24
#define ENTRY_13 0x26
#define ENTRY_14 0x28
#define ENTRY_15 0x30
#define ENTRY_16 0x32
#define ENTRY_17 0x34
#define ENTRY_18 0x36
#define ENTRY_19 0x38
#define ENTRY_20 0x40
#define ENTRY_21 0x42 

bool Direction[3000000,21];

int init()
  {  
  
  int Combinations = MathPow(2,21);

for(int  combination = 0 ; combination < Combinations ; combination++ ) {

for(int C1=0;C1<21;C1++){
Direction[combination,0] = 0; // set standard value to false;
}
   if ( (combination && ENTRY_1) )  {  Direction[combination,0] = 1;} // set value to true if condition is true
   if ( (combination && ENTRY_2) )  {  Direction[combination,1] = 1;}
   if ( (combination && ENTRY_3) )  {  Direction[combination,2] = 1;}
   if ( (combination && ENTRY_4) )  {  Direction[combination,3] = 1;}
   if ( (combination && ENTRY_5) )  {  Direction[combination,4] = 1;}
   if ( (combination && ENTRY_6) )  {  Direction[combination,5] = 1;}
   if ( (combination && ENTRY_7) )  {  Direction[combination,6] = 1;}
   if ( (combination && ENTRY_8) )  {  Direction[combination,7] = 1;}
   if ( (combination && ENTRY_9) )  {  Direction[combination,8] = 1;}
   if ( (combination && ENTRY_10) )  {  Direction[combination,9] = 1;}
   if ( (combination && ENTRY_11) )  {  Direction[combination,10] = 1;}
   if ( (combination && ENTRY_12) )  {  Direction[combination,11] = 1;}
   if ( (combination && ENTRY_13) )  {  Direction[combination,12] = 1;}
   if ( (combination && ENTRY_14) )  {  Direction[combination,13] = 1;}
   if ( (combination && ENTRY_15) )  {  Direction[combination,14] = 1;}
   if ( (combination && ENTRY_16) )  {  Direction[combination,15] = 1;}
   if ( (combination && ENTRY_17) )  {  Direction[combination,16] = 1;}
   if ( (combination && ENTRY_18) )  {  Direction[combination,17] = 1;}
   if ( (combination && ENTRY_19) )  {  Direction[combination,18] = 1;}
   if ( (combination && ENTRY_20) )  {  Direction[combination,19] = 1;}
   if ( (combination && ENTRY_21) )  {  Direction[combination,20] = 1;} 

}

   return(0);
  } 
  
int deinit()
  { 
   return(0);
  } 
  
int start()
  { 
  
   return(0);
  } 
 
ydrol: If A is never greater than 31 - one option is to use bitwise operators...
  for(int i = 1 ; i < entryNumber ; i++) bit *= 2;
  1. Exactly what I do for setting which days of the week EA can trade. external= 1 .. 63 covers all combinations.
  2. Drop your loop and just use
    bit = 1 << entryNumber;

 

You dont need the multi-dimension array any more, as the integer itself is an array of bits, so it serves as the last dimension.

Also as you are looking at all possible combinations you dont really need the array at all, as it is just a very expensive way of representing the numbers 0 - 2^21-1.

I would ditch the Direction array completely and replace it with a function...


EDIT: Better option in posts below using shift operator as suggested :) ...

//untested
bool Direction(int combination,int entryNumber)
{

  int bit = 1;

  for(int i = 1 ; i < entryNumber ; i++) bit *= 2;
  return ((combination & bit) != 0); // fixed

}
Just be aware, generally, that you are dealing with some kind of exponential algorithm so things can get out of control very quickly :)
 
HammerJack:
  1. Your post
    All masks must be a power of two. Not an increment of two.
    #define ENTRY_1 0x01
    #define ENTRY_2 0x02
    #define ENTRY_3 0x04
    #define ENTRY_4 0x08
    #define ENTRY_5 0x10
    #define ENTRY_6 0x12
    #define ENTRY_7 0x14
    #define ENTRY_8 0x16
    #define ENTRY_9 0x18
    #define ENTRY_10 0x20
    #define ENTRY_1 0x01
    #define ENTRY_2 0x02
    #define ENTRY_3 0x04
    #define ENTRY_4 0x08
    #define ENTRY_5 0x10
    #define ENTRY_6 0x20
    #define ENTRY_7 0x40
    #define ENTRY_8 0x80
    #define ENTRY_9 0x100
    #define ENTRY_10 0x200

  2. Your post
       if ( (combination && ENTRY_2) )  {  Direction[combination,1] = 1;}
       if ( (combination && ENTRY_3) )  {  Direction[combination,2] = 1;}
    Logical ands are wrong
       if ( (combination && TRUE) )  {  Direction[combination,1] = 1;}
       if ( (combination && TRUE) )  {  Direction[combination,2] = 1;}
    Non-zero is true
       if ( (combination != 0) )  {  Direction[combination,1] = 1;}
       if ( (combination != 0) )  {  Direction[combination,2] = 1;}
    Bit wise anding
       if ( (combination & ENTRY_2) != 0 )  {  Direction[combination,1] = 1;}
       if ( (combination & ENTRY_3) != 0 )  {  Direction[combination,2] = 1;}
 

Edit - just the shift operator as suggested by WHRoeder, forgot about that one thanks :)

Suggest, you replace Direction array with function below.

UPDATED: added -1


//untested
bool Direction(int combination,int entryNumber)
{

 return ((combination & ( 1 << (entryNumber-1) )) != 0);

}



EDIT3:As its not an array any more you can have entryNumber with the range 1-21 instead of 0-20 . If the former - subtract 1, if the latter dont.

 
Thanks for the help hereYdrol, WHRoeder. It's working for me now. Hopefully in a while I can actually understand what is going on in the code, now it's working but I don't fully understand everything posted above here.
 

If you are just creating the Direction array to use as a flag and not making any further updates to it after you initialise it, then you dont need it.

You can replace all subsequent references of

Direction[number][entry-1]

with a call to a new function Direction(combination,entry), where Direction is now:

//untested
// check any integer 'combination' and return true if the entryNumber bit is set. (starting from bit # 1)
 bool Direction(int combination,int entryNumber)
{

 return ((combination & ( 1 << (entryNumber-1) )) != 0);

}

and delete/remove your initialisation code, and the array, and the loop.

To understand how the function works read bitwise operators (Might want to google 'bitwise operators' too for more gentle introductions eg here )

Reason: