Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

See Randomizing and mutating algo class - style

I'm looking for a review of the functionality of this code, answers to the above question which also describes the code use focus on style instead.

Below is the updated code since the style feedback.

algo is an algorithm that is dynamic. algo instances can be created, asked to become random, mutated and also run. They can be set to remember changes they make to themselves between runs or not. They also output values, these could be used for anything from value sequences such as mathematical number sequences to controls for a bot in a game. It's straightforward to specify limits on memory or computation steps for each as well and needless to say are entirely sandboxed.

By sandboxed I mean that they only compute and produce output as described, they cannot for example use local or global variables, print to the console, #include or write to files.

algos can be used where algorithms need to be portable and must be only able to calculate/compute. There is no distinction between data and instructions in an algo.

A use is as values for directed search for algorithms such as with evolutionary algorithms, MCTS or others.

Another is in a data file that includes algorithms, like an image that includes its own way to decompress itself, that can therefore be constructed using the specific image that is to be decompressed.

They are deliberately general, being a component that could be used in many contexts and conceptually simple, as a number is.

// by Alan Tennant
// Nov 2012

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib> // for rand and abs
#include <ctime>

class algo
{
    public:
        std::vector<unsigned short> code;
        std::vector<unsigned int> output;
        bool debug_info;

        algo()
        {
            reset1(false);
            instructions_p = 11;
            debug_info = true;
        }

        void random(unsigned int size)
        {
            code.clear();
            output.clear();
            for(unsigned int n = 0; n < size; n++)
                code.push_back(rand() % instructions_p);
            reset1(true);
        }

        void run(
            unsigned long most_run_time,
            unsigned int largest_program,
            unsigned int largest_output_size,
            bool reset)
        {
            if (reset && !is_reset_p)
            {
                reset1(true);
                output.clear();
                code2 = code;
                code_pos = 0;
            }
            is_reset_p = false;
            size_t code_size = code2.size();
            if (debug_info && !can_resume_p)
                std::cout<<"can't resume, reset first"<<std::endl;
            if(code_size == 0 || most_run_time == 0)
            {
                out_of_time_p = true;
                out_of_space_p = false;
                run_time_p = most_run_time;
            }
            else if (can_resume_p)
            {
                unsigned short instruction;
                bool cont = true;
                if(debug_info) {
                    std::cout<<"size: "<<code_size<<std::endl<<std::endl;}
                while(cont)
                {
                    instruction = code2[code_pos] % instructions_p;
                    if(debug_info) {std::cout<<code_pos<<", ";}
                    code_pos = (code_pos + 1) % code_size;
                    switch(instruction)
                    {
                        case 0:
                            if(debug_info) {std::cout<<"end";}
                            cont = false;
                            can_resume_p = false;
                        break;
                        case 1:
                            if(debug_info) {
                                std::cout<<"goto p1";}
                            code_pos = code2[(code_pos + 1) % code_size];
                        break;
                        case 2:
                            if(debug_info) {
                                std::cout<<"if value at p1 % 2 = 0 then goto p2";}
                            if(code2[code2[code_pos] % code_size] % 2 == 0) {
                                code_pos = code2[(code_pos + 1) % code_size];}
                            else {
                                code_pos += 2;}
                        break;
                        case 3:
                            if(debug_info) {std::cout<<"value at p1 = value at p2";}
                            code2[code2[code_pos] % code_size] =
                            code2[code2[(code_pos + 1) % code_size] % code_size];
                            code_pos += 2;
                        break;
                        case 4:
                            if(debug_info) {
                                std::cout<<"value at p1 = value at p2 + value at p3";}
                            code2[code2[code_pos] % code_size] = (
                            code2[code2[(code_pos + 1) % code_size] % code_size] +
                            code2[code2[(code_pos + 2) % code_size] % code_size]
                            ) % USHRT_MAX;
                            code_pos += 3;
                        break;
                        case 5:
                        {
                            if(debug_info)
                            {std::cout<<"value at p1 = value at p2 - value at p3";}
                            long v1 =
                            (long)code2[code2[(code_pos + 1) % code_size] % code_size] -
                            code2[code2[(code_pos + 2) % code_size] % code_size];
                            code2[code2[code_pos] % code_size] = abs(v1) % USHRT_MAX;
                            code_pos += 3;
                        }
                        break;
                        case 6:
                        {
                            if(debug_info) {std::cout<<"toggle value at p1";}
                            size_t v1 = code2[code_pos] % code_size;
                            unsigned short v2 = code2[v1];
                            if(v2 == 0) {code2[v1] = 1;}
                            else {code2[v1] = 0;}
                            code_pos++;
                        }
                        break;
                        case 7:
                            if(debug_info) {
                                std::cout<<"output value at p1";}
                            output.push_back(code2[code2[code_pos] % code_size]);
                            code_pos++;
                        break;
                        case 8:
                            if(debug_info) {std::cout<<"increase size";}
                            code2.push_back(0);
                        break;
                        case 9:
                        {
                            if(debug_info) {std::cout<<"increment value at p1";}
                            size_t v1 = code2[code_pos] % code_size;
                            code2[v1] = (code2[v1] + 1) % USHRT_MAX;
                            code_pos++;
                        }
                        break;
                        case 10:
                        {
                            if(debug_info) {std::cout<<"decrement value at p1";}
                            size_t v1 = code2[code_pos] % code_size;
                            code2[v1] = abs((code2[v1] - 1) % USHRT_MAX);
                            code_pos++;
                        }
                        break;
                    }
                    if(debug_info) {std::cout<<std::endl;}
                    run_time_p++;
                    code_size = code2.size();
                    code_pos = code_pos % code_size;
                    if(run_time_p == most_run_time) {
                        cont = false; out_of_time_p = true;}
                    if(code_size > largest_program)
                    {
                        cont = false;
                        can_resume_p = false;
                        out_of_space_p = true;
                        if (debug_info)
                            std::cout<<"became too large"<<std::endl;
                    }
                    if(output.size() > largest_output_size)
                    {
                        cont = false;
                        can_resume_p = false;
                        output.pop_back();
                        if (debug_info)
                            std::cout<<"too much output"<<std::endl;
                    }
                }
                if (debug_info)
                {
                    std::cout<<std::endl<<"size: "<<code_size<<std::endl<<
                        std::endl<<"output: "<<std::endl;
                    size_t output_size = output.size();
                    for (size_t t = 0; t < output_size; t++)
                        std::cout<<output[t]<<std::endl;
                }
            }
        }

        void mutate(unsigned int largest_program)
        {
            output.clear();
            size_t size;
            // special mutations
            while(rand() % 4 != 0) // 3/4 chance
            {
                size = code.size();
                if(rand() % 2 == 0) // 1/2 chance
                {
                    // a bit of code is added to the end (would prefer inserted anywhere)
                    if(size < largest_program)
                        code.push_back(rand() % instructions_p);
                }
                else
                {
                    // a bit of code is removed from the end (would prefer removed from anywhere)
                    if(size != 0)
                        code.pop_back();
                }
                // a section of code is moved, not yet implemented.
            }
            // mutate bits of the code
            size = code.size();
            if (size > 0)
            {
                unsigned int most_mutation =
                    static_cast<unsigned int>(size * 0.1); // static_cast to support GCC
                if(most_mutation < 9)
                    most_mutation = 8;
                unsigned int mutation = rand() % most_mutation;
                for(unsigned int n = 0; n < mutation; n++)
                    code[rand() % size] = rand() % instructions_p;
            }
            reset1(true);
        }

        #pragma region
        unsigned long run_time()
        {
            return run_time_p;
        }

        bool out_of_time()
        {
            return out_of_time_p;
        }

        bool out_of_space()
        {
            return out_of_space_p;
        }

        bool can_resume()
        {
            return can_resume_p;
        }

        bool is_reset()
        {
            return is_reset_p;
        }

        private:
            bool can_resume_p, is_reset_p,
                out_of_time_p, out_of_space_p;
            unsigned int code_pos;
            unsigned short instructions_p;
            unsigned long run_time_p;
            std::vector<unsigned short> code2;

            void reset1(bool say)
            {
                out_of_time_p = false;
                out_of_space_p = false;
                run_time_p = 0;
                code2 = code;
                code_pos = 0;
                can_resume_p = true;
                is_reset_p = true;
                if (say && debug_info)
                    std::cout<<"reset"<<std::endl;
            }
        #pragma endregion
};

int main()
{
    srand((unsigned int)time(NULL));
    algo a = algo();
    a.random(50);
    std::cout<<std::endl<<std::endl;
    a.run(10, 100, 10, false);
    std::cout<<std::endl<<std::endl;
    a.run(10, 100, 10, false);
    return 0;
}
share|improve this question
    
"Below is the updated code since the style feedback": it still lacks many improvements suggested in the previous feedbacks (#pragma region is still there, you stil use USHRT_MAX...). –  Morwenn Mar 26 at 12:47
    
This is from some time ago and I'm not working on it anymore. I actioned much of the style feedback, but some I preferred to leave as before. –  alan2here Mar 27 at 19:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.