Thread: Mutation Operator

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    82

    Post Mutation Operator

    Hi all.

    Trying to move on and create a simple Mutation operator for the string that was created and then edited in the first two functions.

    Basically a for loop which checks each element in the array Output.

    Then comes my attempt at random numbers.

    RandMax was defined as 100 so it is like 100%.

    Basically starts off with i think, initializing variable Mut1 to random number.

    If Mut1 > 80
    {
    //Then mutate but now choose what to mutate to.

    If Mut2 > 50
    {
    then Output[index] = 1
    }
    else
    {
    Output[index] = 0
    }

    as you can prb see better in the code i wanted it to check each element then produce a random number to see if it would get changed, the problem is this needs to be done for each loop, each time it loops the variable Mut1 and Mut2 need to be random/ differant then last time so to speak.

    Reinitialised with new numbers.

    This is where i think i'am going wrong and was wondering if anyone knew a better way of getting it to work.

    Code:
    #include <iostream>
    #include <stdio.h>
    #include <string>
    #define RAND_MAX 100
    
    
    using namespace std;
    using std::string;
    using std::cout;
    using std::endl;
    using std::cin;
    
    void GetUserInput(string &Input)
    
    {
        cout << "Please enter Amino Acid Sequence \"H,P\": " << endl;
        cin >> Input;
         
        cin.get();
    }
    
    void GetSetupString(string theInput, int (&Output)[50])
    // To declare an Array as a reference from Main, syntax is differant then other 
    // references, ie: Type (&ArryName)[Size], try finding that in any tutorial :) 
    
    
    {
    
    
       int index;
       
       for (index = 0; index < theInput.length(); ++index)
       {
           switch (theInput[index])
           {
               case 'H':
                   Output[index] = 1; 
                   break;
               case 'P':
                   Output[index] = 0;
                   break;
               default:
                   break;
        
           }   
            cout << Output[index] ;
       }  
    
    cin.get();
    }    
    
    
    int GetMutation (int (&Output)[50])
    
    {
        
        int index;
        
        for ( index = 0; index < 49; ++index)
        {
            int Mut1;
            Mut1 = rand();
            int Mut2;
            Mut2 = rand();
            
            if (Mut1 > 80)
            
            {
                
                
                if ( Mut2 > 50)
                {
                    Output[index] = 0;
                }
                else
                {
                    Output[index] = 1;
                }
            }
            else
            {
                //do nothing
            }
            
            cout << Output[index] ;
        }                    
        
    cin.get();
          
    }
    
        
    
    int main ()
    
    {
        string Input;
        int Output[50];
    
        GetUserInput(Input);
        GetSetupString(Input, Output);
        GetMutation(Output);
    }
    Thank you for any help.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The rand() function doesn't work like that.
    You may define the MAX value and then use the modulus operator: z = rand() % MAX

    By the way, aren't you making this complicated for yourself? Why do you convert the string to an array of ints? You could just modify the letters in the string?

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    82
    Quote Originally Posted by anon
    The rand() function doesn't work like that.
    You may define the MAX value and then use the modulus operator: z = rand() % MAX

    By the way, aren't you making this complicated for yourself? Why do you convert the string to an array of ints? You could just modify the letters in the string?
    It was made into an array as a way to test my referencing and try other stuff (Switch/Case)

    I don't quite think rand() % MAX works

    I'll scan through search again and see what comes up with random.

    Thanks any way.

    Hadn't seeded rand

    Works now ish, if only i could tell it to stop reading the rest of the array
    Last edited by Cdrwolfe; 07-10-2006 at 01:28 PM.

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I can't believe your rand() thing works - I tested it, and it doesn't.

    Firstly, it will give a compiler error "redefinition of RAND_MAX". So I could only compile your code by adding #undef RAND_MAX first.

    However, if you had checked the random numbers, you would have seen that they are still not from 1 to 100. It seems that redefining RAND_MAX doesn't affect how the random number generator works. It just takes away the oportunity to see what's the highest possible value.

    Secondly, what you are doing with the arrays in the functions is really weird. Normally you would pass the pointer to the first member of the array and an int telling how many elements there are. Then you would access individual elements in the function using pointer arithmetic.

    To solve your problem with printing all 50 numbers, if the string is shorter: consider using a dynamically allocated array that has the needed size (Input.size()).

    I made some changes to your code to get it to work properly. Some of it is here:

    Code:
    #include <iostream>
    //#include <stdio.h>   //not really needed
    #include <string>
    #include <ctime> 
    //#undef RAND_MAX       //not a good idea
    //#define RAND_MAX 100
    
    
    //using namespace std;   //not needed
    using std::string;            //if you are doing it this way
    using std::cout;
    using std::endl;
    using std::cin;
    
    const int MAX = 100;      //global max random number
    And here's the modified main function:
    Code:
    int main ()
    
    {
        srand((unsigned) time(NULL));
        string Input;
        GetUserInput(Input);
        int size = Input.size();
        int* Output = new int[size];       //allocate memory
        GetSetupString(Input, Output);
        GetMutation(Output, size);        //pass size of array
        delete [] Output;                       //free memory
    }

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    82
    Thanks, before hand i changed RAND_MAX to = 100, and seeded rand by defining srand = 12, then changed rand() to rand() % 100 like you suggested.

    It worked after that, of course i need to change the seed to give new results but one step at a time

    Anon you missed a previous thread where i basically went through learning pointers and references on what is essentially the same code above there or abouts.

    Some people suggested i used referencing, i agreed because it is easir to understand then pointers. Could be wrong it's not the first time .

    Is it really weird what i'am doing with the arrays?
    All i'am doing is referencing them.

    Anyway if you like weird arrays in functions have a look at my latest bodge

    Code:
    void GetPopulation(int (&Output)[21], int (&Pop)[PopSize][21])
    
    {
        int index;
        int j;
        
        for ( index = 0; index > PopSize; ++index)
        {
            for ( j = 0; j > 21; ++j)
            
                {
                        int Out;
                        Out = Output[j];
             
                        Pop[index][j] = Pop[index][Out];
                        cout << Pop[index][j];
            
                }    
                       
        cout << Pop[index][j];
        }    
    }
    Popsize is defined
    Aswell as int Pop[PopSize][21] which is in main

    It is my attempt at an Array within an array.
    What i'am trying to do is create a population of individual arrays that of which are like "Output"

    It compiles but to be honest it doesn't do anything prb some rubbish mistake but i'am tired and can't concentrate at the moment.

    Perhaps tomorrow everything will be clearer

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Look at the code I posted. The standard way to seed the random number generator is using system time.

    I suggested allocating memory with new, because then you can have an array that is exactly as large as needed (what if user entered more than 50 characters?)

    By the way, you could use vectors instead of arrays. Here's a small program to show how easy it is:

    Code:
    #include <iostream>
    #include <vector>
    using namespace std;
    
    void VectorInput(vector<int>& v)
    {
        int n = 0;
        cout << "Enter ingegers (0 to stop)" << endl;
        do {
            cin >> n;
            if (n) v.push_back(n);
        } while (n);
    }
    
    void OutputDouble(vector<int>& v)
    {
        cout << "Printing doubles..." << endl;
        for (int i = 0; i < v.size(); i++)
            cout << v[i]*2 << " ";
        cout << endl;
    }
    
    int main()
    {
        vector<int> MyVector;
        VectorInput(MyVector);
        OutputDouble(MyVector);
        cin.ignore();
        cin.get();
        return 0;
    }

  7. #7
    Registered User
    Join Date
    Oct 2005
    Posts
    82
    I'll have to read up on vectors, is it able to do the array of arrays thing i was trying to do above?

    Anyway thanks for the help i shall read up on it tomorrow.

    thanks

    Regards Wolfe

  8. #8
    Registered User
    Join Date
    Dec 2005
    Posts
    24
    Code:
    void GetPopulation(int (&Output)[21], int (&Pop)[PopSize][21])
    
    {
        int index;
        int j;
    
        /*
        This next loop only runs while the value of index is greater    than Popsize. Since index is set to zero at the start of the   
        loop, the loop will only run if Popsize is less than zero, which I   
        doubt. I think changing the > to a < in the loop condition will 
        suffice.
        */
        
        for ( index = 0; index > PopSize; ++index)
        {
        /*
        Again, loop only executes if j is greater than 21. Change > to <
        to fix this.
        */
            for ( j = 0; j > 21; ++j)
            
                {
                        int Out;
                        Out = Output[j];
             
                        Pop[index][j] = Pop[index][Out];
                        cout << Pop[index][j];
            
                }    
                       
        cout << Pop[index][j];
        }    
    }
    Incidentally, have you done any work with pointers yet? As I recall, you can't pass an actual array to a function (though it may look as if you are depending on how you declare the function parameters), rather a pointer to the start of the array is passed and you can access elements of the array through the pointer using 'array indexing', as I believe it is called. For example:

    Code:
    char string[14] = "Test string\n";
    /*
    Note that I do not assign the address of the array to ptr, but the program will still work.
    */
    char *ptr = string;
    for(int i = 0; i < 14; i++) {
      std::cout << ptr[i];
    }
    Note that there is no bounds checking, so if the pointer is told to read (or write) a location outside the array, nothing will stop it from doing so, which will probably result in undesirable operation of your program (anything from garbage values being read to program crashes). If any of this seems unclear, say so and I'll try to explain more basically.
    Last edited by ruthgrin; 07-11-2006 at 05:49 AM. Reason: Accidentally typed an unneeded dereference

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    82
    Found out about the ">" last night, knew it would be something stupid i did .

    I'am referencing the array into the function instead of using a pointer both have the same effect i believe.

    Thanks

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Yes, vectors can do the same things as arrays and much more:
    they know their own size (MyVector.size()) and they expand as you add more elements.

    By the way, I don't think you need all the array stuff for the mutation code. Input is string, why can't output also be a string?

    Here's another modification of your code. As I didn't see any reason why input should be converted to 1-s and 0-s I omitted it. (You could also convert input into a string of '1'-s and '0'-s if you want to - it's not a number after all.)

    The key to the tast is the string::replace() method.

    Code:
    #include <iostream>
    #include <ctime>
    #include <string>
    
    using std::string;
    using std::cout;
    using std::endl;
    using std::cin;
    
    const int MAX = 101;
    const int MUTATION_PROBABILITY = 10;
    
    void GetUserInput(string &Input)
    {
        cout << "Please enter Amino Acid Sequence \"H,P\": " << endl;
        cin >> Input;
         
        cin.get();
    }   
    
    string GetMutation (const string& Input)
    {
        string Output = Input;
        for ( int index = 0; index < Input.size(); ++index)
        {
            if (rand()%MAX < MUTATION_PROBABILITY)        
            {
    /*Simplified the whole thing.
    If random number is smaller than the probability of mutation,
    replace H with P and P with H.*/
                switch (Input[index]) {
                    case 'H':
                        Output.replace(index, 1, "P");
                        break;
                    case 'P':
                        Output.replace(index, 1, "H");
                        break;
                }
            }
        }                    
        return Output;  
    }
    
    
    int main ()
    {
        srand((unsigned)time(NULL));
        string Input;
        string Output;
    
        GetUserInput(Input);
        Output = GetMutation(Input);
        cout << Output << endl;
        cin.get();
        return 0;
    }

  11. #11
    Registered User
    Join Date
    Oct 2005
    Posts
    82
    Sadly the string of "HHPPP" etc has to be converted into (1,0) for the fitness function i intend to right to work. It just makes it easier.

    Also doesn't return Output only return the first element of the string?

    Anyway going to post a new thread on Array of Arrays Hope to see you there

    p.s i like your "mutator" i'll have to work it in.

    thanks for the help

    Regards Wolfe

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. unary operator overloading and classes
    By coletek in forum C++ Programming
    Replies: 9
    Last Post: 01-10-2009, 02:14 AM
  2. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Operator Overloading (Bug, or error in code?)
    By QuietWhistler in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2006, 08:38 AM
  5. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM