diff --git a/common/arguments.cxx b/common/arguments.cxx index c30efb24..59c40542 100644 --- a/common/arguments.cxx +++ b/common/arguments.cxx @@ -1,23 +1,23 @@ -#include -#include #include #include +#include +#include using namespace std; bool argument_exists(vector arguments, string argument) { for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { - // cerr << "parsed argument '" << argument << "' successfully." << endl; +// cerr << "parsed argument '" << argument << "' successfully." << endl; return true; } } return false; } -// template <> -// bool get_argument(vector arguments, string argument, bool required, string &result) { -bool get_argument(vector arguments, string argument, bool required, string& result) { +//template <> +//bool get_argument(vector arguments, string argument, bool required, string &result) { +bool get_argument(vector arguments, string argument, bool required, string &result) { bool found = false; for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { @@ -33,19 +33,20 @@ bool get_argument(vector arguments, string argument, bool required, stri } if (found) { - // cerr << "parsed argument '" << argument << "' successfully: " << result << endl; +// cerr << "parsed argument '" << argument << "' successfully: " << result << endl; } return found; } -// template <> -// bool get_argument_vector(vector arguments, string argument, bool required, vector &results) { -bool get_argument_vector(vector arguments, string argument, bool required, vector& results) { + +//template <> +//bool get_argument_vector(vector arguments, string argument, bool required, vector &results) { +bool get_argument_vector(vector arguments, string argument, bool required, vector &results) { bool found = false; for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { i++; - while (i < arguments.size() && arguments.at(i).substr(0, 2).compare("--") != 0) { + while (i < arguments.size() && arguments.at(i).substr(0,2).compare("--") != 0) { results.push_back(arguments.at(i++)); } found = true; @@ -69,3 +70,5 @@ bool get_argument_vector(vector arguments, string argument, bool require } return found; } + + diff --git a/common/arguments.hxx b/common/arguments.hxx index bb1d105c..934bb786 100644 --- a/common/arguments.hxx +++ b/common/arguments.hxx @@ -1,24 +1,24 @@ #ifndef GIBBS_ARGUMENTS_H #define GIBBS_ARGUMENTS_H -#include #include -#include #include +#include +#include using namespace std; bool argument_exists(vector arguments, string argument); template -bool get_argument_vector(vector arguments, string argument, bool required, vector& results) { +bool get_argument_vector(vector arguments, string argument, bool required, vector &results) { bool found = false; for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { i++; - while (i < arguments.size() && arguments.at(i).substr(0, 2).compare("--") != 0) { + while (i < arguments.size() && arguments.at(i).substr(0,2).compare("--") != 0) { T result; - if (!(stringstream(arguments.at(i++)) >> result)) { + if ( !(stringstream(arguments.at(i++)) >> result) ) { cerr << "ERROR: invalid argument '" << argument << "': " << arguments.at(i) << endl; exit(1); } @@ -46,16 +46,16 @@ bool get_argument_vector(vector arguments, string argument, bool require return found; } -bool get_argument_vector(vector arguments, string argument, bool required, vector& results); +bool get_argument_vector(vector arguments, string argument, bool required, vector &results); -bool get_argument(vector arguments, string argument, bool required, string& result); +bool get_argument(vector arguments, string argument, bool required, string &result); template -bool get_argument(vector arguments, string argument, bool required, T& result) { +bool get_argument(vector arguments, string argument, bool required, T &result) { bool found = false; for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { - if (!(stringstream(arguments.at(++i)) >> result)) { + if ( !(stringstream(arguments.at(++i)) >> result) ) { cerr << "ERROR: invalid argument '" << argument << "': " << arguments.at(i) << endl; exit(1); } @@ -70,21 +70,22 @@ bool get_argument(vector arguments, string argument, bool required, T& r } if (found) { - // cerr << "parsed argument '" << argument << "' successfully: " << result << endl; +// cerr << "parsed argument '" << argument << "' successfully: " << result << endl; } return found; } + template -bool get_arguments(vector arguments, string argument, bool required, T1& result1, T2& result2) { +bool get_arguments(vector arguments, string argument, bool required, T1 &result1, T2 &result2) { bool found = false; for (unsigned int i = 0; i < arguments.size(); i++) { if (argument.compare(arguments.at(i)) == 0) { - if (!(stringstream(arguments.at(++i)) >> result1)) { + if ( !(stringstream(arguments.at(++i)) >> result1) ) { cerr << "ERROR: invalid argument '" << argument << "': " << arguments.at(i) << endl; exit(1); } - if (!(stringstream(arguments.at(++i)) >> result2)) { + if ( !(stringstream(arguments.at(++i)) >> result2) ) { cerr << "ERROR: invalid argument '" << argument << "': " << arguments.at(i) << endl; exit(1); } @@ -99,7 +100,7 @@ bool get_arguments(vector arguments, string argument, bool required, T1& } if (found) { - // cerr << "parsed argument '" << argument << "' successfully: " << result1 << " " << result2 << endl; +// cerr << "parsed argument '" << argument << "' successfully: " << result1 << " " << result2 << endl; } return found; } diff --git a/common/color_table.cxx b/common/color_table.cxx index d9e743b0..a09554d5 100644 --- a/common/color_table.cxx +++ b/common/color_table.cxx @@ -1,1032 +1,267 @@ #include "color_table.hxx" -// bent cool warm -// scalar,RGB_r,RGB_g,RGB_b +//bent cool warm +//scalar,RGB_r,RGB_g,RGB_b const static double bent_cool_warm[] = { - 0.0, - 85, - 72, - 193, - 0.00392156862745, - 86, - 74, - 194, - 0.0078431372549, - 87, - 75, - 194, - 0.0117647058824, - 88, - 77, - 195, - 0.0156862745098, - 88, - 78, - 196, - 0.0196078431373, - 89, - 79, - 196, - 0.0235294117647, - 90, - 81, - 197, - 0.0274509803922, - 90, - 82, - 197, - 0.0313725490196, - 91, - 84, - 198, - 0.0352941176471, - 92, - 85, - 199, - 0.0392156862745, - 93, - 87, - 199, - 0.043137254902, - 94, - 88, - 200, - 0.0470588235294, - 94, - 90, - 200, - 0.0509803921569, - 95, - 91, - 201, - 0.0549019607843, - 96, - 92, - 202, - 0.0588235294118, - 97, - 94, - 202, - 0.0627450980392, - 98, - 95, - 203, - 0.0666666666667, - 98, - 97, - 203, - 0.0705882352941, - 99, - 98, - 204, - 0.0745098039216, - 100, - 99, - 204, - 0.078431372549, - 101, - 101, - 205, - 0.0823529411765, - 102, - 102, - 206, - 0.0862745098039, - 103, - 104, - 206, - 0.0901960784314, - 104, - 105, - 207, - 0.0941176470588, - 104, - 106, - 207, - 0.0980392156863, - 105, - 108, - 208, - 0.101960784314, - 106, - 109, - 208, - 0.105882352941, - 107, - 110, - 209, - 0.109803921569, - 108, - 112, - 209, - 0.113725490196, - 109, - 113, - 210, - 0.117647058824, - 110, - 115, - 210, - 0.121568627451, - 111, - 116, - 211, - 0.125490196078, - 112, - 117, - 211, - 0.129411764706, - 113, - 119, - 212, - 0.133333333333, - 114, - 120, - 212, - 0.137254901961, - 115, - 121, - 213, - 0.141176470588, - 116, - 123, - 213, - 0.145098039216, - 117, - 124, - 214, - 0.149019607843, - 118, - 125, - 214, - 0.152941176471, - 119, - 127, - 215, - 0.156862745098, - 120, - 128, - 215, - 0.160784313725, - 121, - 129, - 215, - 0.164705882353, - 122, - 131, - 216, - 0.16862745098, - 123, - 132, - 216, - 0.172549019608, - 124, - 134, - 217, - 0.176470588235, - 125, - 135, - 217, - 0.180392156863, - 126, - 136, - 218, - 0.18431372549, - 127, - 138, - 218, - 0.188235294118, - 128, - 139, - 218, - 0.192156862745, - 129, - 140, - 219, - 0.196078431373, - 130, - 142, - 219, - 0.2, - 132, - 143, - 220, - 0.203921568627, - 133, - 144, - 220, - 0.207843137255, - 134, - 146, - 221, - 0.211764705882, - 135, - 147, - 221, - 0.21568627451, - 136, - 148, - 221, - 0.219607843137, - 137, - 150, - 222, - 0.223529411765, - 138, - 151, - 222, - 0.227450980392, - 140, - 152, - 222, - 0.23137254902, - 141, - 154, - 223, - 0.235294117647, - 142, - 155, - 223, - 0.239215686275, - 143, - 156, - 224, - 0.243137254902, - 144, - 158, - 224, - 0.247058823529, - 146, - 159, - 224, - 0.250980392157, - 147, - 160, - 225, - 0.254901960784, - 148, - 162, - 225, - 0.258823529412, - 149, - 163, - 225, - 0.262745098039, - 151, - 164, - 226, - 0.266666666667, - 152, - 166, - 226, - 0.270588235294, - 153, - 167, - 226, - 0.274509803922, - 154, - 168, - 227, - 0.278431372549, - 156, - 170, - 227, - 0.282352941176, - 157, - 171, - 227, - 0.286274509804, - 158, - 172, - 228, - 0.290196078431, - 160, - 174, - 228, - 0.294117647059, - 161, - 175, - 228, - 0.298039215686, - 162, - 176, - 229, - 0.301960784314, - 164, - 177, - 229, - 0.305882352941, - 165, - 179, - 229, - 0.309803921569, - 166, - 180, - 230, - 0.313725490196, - 168, - 181, - 230, - 0.317647058824, - 169, - 183, - 230, - 0.321568627451, - 170, - 184, - 230, - 0.325490196078, - 172, - 185, - 231, - 0.329411764706, - 173, - 187, - 231, - 0.333333333333, - 175, - 188, - 231, - 0.337254901961, - 176, - 189, - 232, - 0.341176470588, - 177, - 191, - 232, - 0.345098039216, - 179, - 192, - 232, - 0.349019607843, - 180, - 193, - 232, - 0.352941176471, - 182, - 194, - 233, - 0.356862745098, - 183, - 196, - 233, - 0.360784313725, - 185, - 197, - 233, - 0.364705882353, - 186, - 198, - 234, - 0.36862745098, - 188, - 200, - 234, - 0.372549019608, - 189, - 201, - 234, - 0.376470588235, - 191, - 202, - 234, - 0.380392156863, - 192, - 204, - 235, - 0.38431372549, - 194, - 205, - 235, - 0.388235294118, - 195, - 206, - 235, - 0.392156862745, - 197, - 207, - 235, - 0.396078431373, - 198, - 209, - 236, - 0.4, - 200, - 210, - 236, - 0.403921568627, - 201, - 211, - 236, - 0.407843137255, - 203, - 213, - 236, - 0.411764705882, - 205, - 214, - 237, - 0.41568627451, - 206, - 215, - 237, - 0.419607843137, - 208, - 216, - 237, - 0.423529411765, - 209, - 218, - 237, - 0.427450980392, - 211, - 219, - 238, - 0.43137254902, - 213, - 220, - 238, - 0.435294117647, - 214, - 221, - 238, - 0.439215686275, - 216, - 223, - 238, - 0.443137254902, - 217, - 224, - 239, - 0.447058823529, - 219, - 225, - 239, - 0.450980392157, - 221, - 227, - 239, - 0.454901960784, - 222, - 228, - 239, - 0.458823529412, - 224, - 229, - 240, - 0.462745098039, - 226, - 230, - 240, - 0.466666666667, - 227, - 232, - 240, - 0.470588235294, - 229, - 233, - 240, - 0.474509803922, - 231, - 234, - 241, - 0.478431372549, - 233, - 235, - 241, - 0.482352941176, - 234, - 237, - 241, - 0.486274509804, - 236, - 238, - 241, - 0.490196078431, - 238, - 239, - 242, - 0.494117647059, - 240, - 240, - 242, - 0.498039215686, - 241, - 242, - 242, - 0.501960784314, - 242, - 242, - 241, - 0.505882352941, - 242, - 240, - 239, - 0.509803921569, - 241, - 239, - 237, - 0.513725490196, - 241, - 237, - 235, - 0.517647058824, - 240, - 236, - 232, - 0.521568627451, - 240, - 234, - 230, - 0.525490196078, - 239, - 233, - 228, - 0.529411764706, - 239, - 231, - 226, - 0.533333333333, - 239, - 230, - 224, - 0.537254901961, - 238, - 228, - 221, - 0.541176470588, - 238, - 226, - 219, - 0.545098039216, - 237, - 225, - 217, - 0.549019607843, - 237, - 223, - 215, - 0.552941176471, - 237, - 222, - 213, - 0.556862745098, - 236, - 220, - 211, - 0.560784313725, - 236, - 219, - 209, - 0.564705882353, - 235, - 217, - 207, - 0.56862745098, - 235, - 216, - 205, - 0.572549019608, - 234, - 214, - 203, - 0.576470588235, - 234, - 213, - 200, - 0.580392156863, - 234, - 211, - 198, - 0.58431372549, - 233, - 210, - 196, - 0.588235294118, - 233, - 208, - 194, - 0.592156862745, - 232, - 207, - 192, - 0.596078431373, - 232, - 205, - 190, - 0.6, - 231, - 204, - 188, - 0.603921568627, - 231, - 202, - 186, - 0.607843137255, - 231, - 201, - 184, - 0.611764705882, - 230, - 199, - 182, - 0.61568627451, - 230, - 198, - 180, - 0.619607843137, - 229, - 196, - 178, - 0.623529411765, - 229, - 195, - 176, - 0.627450980392, - 228, - 193, - 175, - 0.63137254902, - 228, - 192, - 173, - 0.635294117647, - 228, - 190, - 171, - 0.639215686275, - 227, - 188, - 169, - 0.643137254902, - 227, - 187, - 167, - 0.647058823529, - 226, - 185, - 165, - 0.650980392157, - 226, - 184, - 163, - 0.654901960784, - 225, - 182, - 161, - 0.658823529412, - 225, - 181, - 159, - 0.662745098039, - 224, - 179, - 158, - 0.666666666667, - 224, - 178, - 156, - 0.670588235294, - 224, - 176, - 154, - 0.674509803922, - 223, - 175, - 152, - 0.678431372549, - 223, - 173, - 150, - 0.682352941176, - 222, - 171, - 148, - 0.686274509804, - 222, - 170, - 147, - 0.690196078431, - 221, - 168, - 145, - 0.694117647059, - 221, - 167, - 143, - 0.698039215686, - 220, - 165, - 141, - 0.701960784314, - 220, - 164, - 140, - 0.705882352941, - 219, - 162, - 138, - 0.709803921569, - 219, - 161, - 136, - 0.713725490196, - 219, - 159, - 134, - 0.717647058824, - 218, - 157, - 133, - 0.721568627451, - 218, - 156, - 131, - 0.725490196078, - 217, - 154, - 129, - 0.729411764706, - 217, - 153, - 128, - 0.733333333333, - 216, - 151, - 126, - 0.737254901961, - 216, - 149, - 124, - 0.741176470588, - 215, - 148, - 123, - 0.745098039216, - 215, - 146, - 121, - 0.749019607843, - 214, - 145, - 119, - 0.752941176471, - 214, - 143, - 118, - 0.756862745098, - 213, - 141, - 116, - 0.760784313725, - 213, - 140, - 115, - 0.764705882353, - 212, - 138, - 113, - 0.76862745098, - 212, - 137, - 111, - 0.772549019608, - 211, - 135, - 110, - 0.776470588235, - 211, - 133, - 108, - 0.780392156863, - 210, - 132, - 107, - 0.78431372549, - 210, - 130, - 105, - 0.788235294118, - 209, - 129, - 104, - 0.792156862745, - 209, - 127, - 102, - 0.796078431373, - 208, - 125, - 101, - 0.8, - 208, - 124, - 99, - 0.803921568627, - 207, - 122, - 98, - 0.807843137255, - 207, - 120, - 96, - 0.811764705882, - 206, - 119, - 95, - 0.81568627451, - 206, - 117, - 93, - 0.819607843137, - 205, - 115, - 92, - 0.823529411765, - 205, - 114, - 91, - 0.827450980392, - 204, - 112, - 89, - 0.83137254902, - 203, - 110, - 88, - 0.835294117647, - 203, - 109, - 86, - 0.839215686275, - 202, - 107, - 85, - 0.843137254902, - 202, - 105, - 84, - 0.847058823529, - 201, - 103, - 82, - 0.850980392157, - 201, - 102, - 81, - 0.854901960784, - 200, - 100, - 80, - 0.858823529412, - 200, - 98, - 78, - 0.862745098039, - 199, - 96, - 77, - 0.866666666667, - 198, - 95, - 76, - 0.870588235294, - 198, - 93, - 74, - 0.874509803922, - 197, - 91, - 73, - 0.878431372549, - 197, - 89, - 72, - 0.882352941176, - 196, - 87, - 71, - 0.886274509804, - 196, - 86, - 69, - 0.890196078431, - 195, - 84, - 68, - 0.894117647059, - 194, - 82, - 67, - 0.898039215686, - 194, - 80, - 66, - 0.901960784314, - 193, - 78, - 65, - 0.905882352941, - 193, - 76, - 63, - 0.909803921569, - 192, - 74, - 62, - 0.913725490196, - 191, - 72, - 61, - 0.917647058824, - 191, - 70, - 60, - 0.921568627451, - 190, - 68, - 59, - 0.925490196078, - 189, - 66, - 58, - 0.929411764706, - 189, - 64, - 57, - 0.933333333333, - 188, - 62, - 56, - 0.937254901961, - 188, - 59, - 55, - 0.941176470588, - 187, - 57, - 54, - 0.945098039216, - 186, - 55, - 53, - 0.949019607843, - 186, - 52, - 52, - 0.952941176471, - 185, - 50, - 50, - 0.956862745098, - 184, - 47, - 49, - 0.960784313725, - 184, - 45, - 49, - 0.964705882353, - 183, - 42, - 48, - 0.96862745098, - 182, - 39, - 47, - 0.972549019608, - 182, - 36, - 46, - 0.976470588235, - 181, - 33, - 45, - 0.980392156863, - 181, - 29, - 44, - 0.98431372549, - 180, - 25, - 43, - 0.988235294118, - 179, - 21, - 42, - 0.992156862745, - 178, - 15, - 41, - 0.996078431373, - 178, - 8, - 40, - 1.0, - 177, - 1, - 39}; + 0.0,85,72,193, + 0.00392156862745,86,74,194, + 0.0078431372549,87,75,194, + 0.0117647058824,88,77,195, + 0.0156862745098,88,78,196, + 0.0196078431373,89,79,196, + 0.0235294117647,90,81,197, + 0.0274509803922,90,82,197, + 0.0313725490196,91,84,198, + 0.0352941176471,92,85,199, + 0.0392156862745,93,87,199, + 0.043137254902,94,88,200, + 0.0470588235294,94,90,200, + 0.0509803921569,95,91,201, + 0.0549019607843,96,92,202, + 0.0588235294118,97,94,202, + 0.0627450980392,98,95,203, + 0.0666666666667,98,97,203, + 0.0705882352941,99,98,204, + 0.0745098039216,100,99,204, + 0.078431372549,101,101,205, + 0.0823529411765,102,102,206, + 0.0862745098039,103,104,206, + 0.0901960784314,104,105,207, + 0.0941176470588,104,106,207, + 0.0980392156863,105,108,208, + 0.101960784314,106,109,208, + 0.105882352941,107,110,209, + 0.109803921569,108,112,209, + 0.113725490196,109,113,210, + 0.117647058824,110,115,210, + 0.121568627451,111,116,211, + 0.125490196078,112,117,211, + 0.129411764706,113,119,212, + 0.133333333333,114,120,212, + 0.137254901961,115,121,213, + 0.141176470588,116,123,213, + 0.145098039216,117,124,214, + 0.149019607843,118,125,214, + 0.152941176471,119,127,215, + 0.156862745098,120,128,215, + 0.160784313725,121,129,215, + 0.164705882353,122,131,216, + 0.16862745098,123,132,216, + 0.172549019608,124,134,217, + 0.176470588235,125,135,217, + 0.180392156863,126,136,218, + 0.18431372549,127,138,218, + 0.188235294118,128,139,218, + 0.192156862745,129,140,219, + 0.196078431373,130,142,219, + 0.2,132,143,220, + 0.203921568627,133,144,220, + 0.207843137255,134,146,221, + 0.211764705882,135,147,221, + 0.21568627451,136,148,221, + 0.219607843137,137,150,222, + 0.223529411765,138,151,222, + 0.227450980392,140,152,222, + 0.23137254902,141,154,223, + 0.235294117647,142,155,223, + 0.239215686275,143,156,224, + 0.243137254902,144,158,224, + 0.247058823529,146,159,224, + 0.250980392157,147,160,225, + 0.254901960784,148,162,225, + 0.258823529412,149,163,225, + 0.262745098039,151,164,226, + 0.266666666667,152,166,226, + 0.270588235294,153,167,226, + 0.274509803922,154,168,227, + 0.278431372549,156,170,227, + 0.282352941176,157,171,227, + 0.286274509804,158,172,228, + 0.290196078431,160,174,228, + 0.294117647059,161,175,228, + 0.298039215686,162,176,229, + 0.301960784314,164,177,229, + 0.305882352941,165,179,229, + 0.309803921569,166,180,230, + 0.313725490196,168,181,230, + 0.317647058824,169,183,230, + 0.321568627451,170,184,230, + 0.325490196078,172,185,231, + 0.329411764706,173,187,231, + 0.333333333333,175,188,231, + 0.337254901961,176,189,232, + 0.341176470588,177,191,232, + 0.345098039216,179,192,232, + 0.349019607843,180,193,232, + 0.352941176471,182,194,233, + 0.356862745098,183,196,233, + 0.360784313725,185,197,233, + 0.364705882353,186,198,234, + 0.36862745098,188,200,234, + 0.372549019608,189,201,234, + 0.376470588235,191,202,234, + 0.380392156863,192,204,235, + 0.38431372549,194,205,235, + 0.388235294118,195,206,235, + 0.392156862745,197,207,235, + 0.396078431373,198,209,236, + 0.4,200,210,236, + 0.403921568627,201,211,236, + 0.407843137255,203,213,236, + 0.411764705882,205,214,237, + 0.41568627451,206,215,237, + 0.419607843137,208,216,237, + 0.423529411765,209,218,237, + 0.427450980392,211,219,238, + 0.43137254902,213,220,238, + 0.435294117647,214,221,238, + 0.439215686275,216,223,238, + 0.443137254902,217,224,239, + 0.447058823529,219,225,239, + 0.450980392157,221,227,239, + 0.454901960784,222,228,239, + 0.458823529412,224,229,240, + 0.462745098039,226,230,240, + 0.466666666667,227,232,240, + 0.470588235294,229,233,240, + 0.474509803922,231,234,241, + 0.478431372549,233,235,241, + 0.482352941176,234,237,241, + 0.486274509804,236,238,241, + 0.490196078431,238,239,242, + 0.494117647059,240,240,242, + 0.498039215686,241,242,242, + 0.501960784314,242,242,241, + 0.505882352941,242,240,239, + 0.509803921569,241,239,237, + 0.513725490196,241,237,235, + 0.517647058824,240,236,232, + 0.521568627451,240,234,230, + 0.525490196078,239,233,228, + 0.529411764706,239,231,226, + 0.533333333333,239,230,224, + 0.537254901961,238,228,221, + 0.541176470588,238,226,219, + 0.545098039216,237,225,217, + 0.549019607843,237,223,215, + 0.552941176471,237,222,213, + 0.556862745098,236,220,211, + 0.560784313725,236,219,209, + 0.564705882353,235,217,207, + 0.56862745098,235,216,205, + 0.572549019608,234,214,203, + 0.576470588235,234,213,200, + 0.580392156863,234,211,198, + 0.58431372549,233,210,196, + 0.588235294118,233,208,194, + 0.592156862745,232,207,192, + 0.596078431373,232,205,190, + 0.6,231,204,188, + 0.603921568627,231,202,186, + 0.607843137255,231,201,184, + 0.611764705882,230,199,182, + 0.61568627451,230,198,180, + 0.619607843137,229,196,178, + 0.623529411765,229,195,176, + 0.627450980392,228,193,175, + 0.63137254902,228,192,173, + 0.635294117647,228,190,171, + 0.639215686275,227,188,169, + 0.643137254902,227,187,167, + 0.647058823529,226,185,165, + 0.650980392157,226,184,163, + 0.654901960784,225,182,161, + 0.658823529412,225,181,159, + 0.662745098039,224,179,158, + 0.666666666667,224,178,156, + 0.670588235294,224,176,154, + 0.674509803922,223,175,152, + 0.678431372549,223,173,150, + 0.682352941176,222,171,148, + 0.686274509804,222,170,147, + 0.690196078431,221,168,145, + 0.694117647059,221,167,143, + 0.698039215686,220,165,141, + 0.701960784314,220,164,140, + 0.705882352941,219,162,138, + 0.709803921569,219,161,136, + 0.713725490196,219,159,134, + 0.717647058824,218,157,133, + 0.721568627451,218,156,131, + 0.725490196078,217,154,129, + 0.729411764706,217,153,128, + 0.733333333333,216,151,126, + 0.737254901961,216,149,124, + 0.741176470588,215,148,123, + 0.745098039216,215,146,121, + 0.749019607843,214,145,119, + 0.752941176471,214,143,118, + 0.756862745098,213,141,116, + 0.760784313725,213,140,115, + 0.764705882353,212,138,113, + 0.76862745098,212,137,111, + 0.772549019608,211,135,110, + 0.776470588235,211,133,108, + 0.780392156863,210,132,107, + 0.78431372549,210,130,105, + 0.788235294118,209,129,104, + 0.792156862745,209,127,102, + 0.796078431373,208,125,101, + 0.8,208,124,99, + 0.803921568627,207,122,98, + 0.807843137255,207,120,96, + 0.811764705882,206,119,95, + 0.81568627451,206,117,93, + 0.819607843137,205,115,92, + 0.823529411765,205,114,91, + 0.827450980392,204,112,89, + 0.83137254902,203,110,88, + 0.835294117647,203,109,86, + 0.839215686275,202,107,85, + 0.843137254902,202,105,84, + 0.847058823529,201,103,82, + 0.850980392157,201,102,81, + 0.854901960784,200,100,80, + 0.858823529412,200,98,78, + 0.862745098039,199,96,77, + 0.866666666667,198,95,76, + 0.870588235294,198,93,74, + 0.874509803922,197,91,73, + 0.878431372549,197,89,72, + 0.882352941176,196,87,71, + 0.886274509804,196,86,69, + 0.890196078431,195,84,68, + 0.894117647059,194,82,67, + 0.898039215686,194,80,66, + 0.901960784314,193,78,65, + 0.905882352941,193,76,63, + 0.909803921569,192,74,62, + 0.913725490196,191,72,61, + 0.917647058824,191,70,60, + 0.921568627451,190,68,59, + 0.925490196078,189,66,58, + 0.929411764706,189,64,57, + 0.933333333333,188,62,56, + 0.937254901961,188,59,55, + 0.941176470588,187,57,54, + 0.945098039216,186,55,53, + 0.949019607843,186,52,52, + 0.952941176471,185,50,50, + 0.956862745098,184,47,49, + 0.960784313725,184,45,49, + 0.964705882353,183,42,48, + 0.96862745098,182,39,47, + 0.972549019608,182,36,46, + 0.976470588235,181,33,45, + 0.980392156863,181,29,44, + 0.98431372549,180,25,43, + 0.988235294118,179,21,42, + 0.992156862745,178,15,41, + 0.996078431373,178,8,40, + 1.0,177,1,39 +}; + + Color get_colormap(double value) { Color c; diff --git a/common/db_conn.cxx b/common/db_conn.cxx index 8f31a7f8..52c4352b 100644 --- a/common/db_conn.cxx +++ b/common/db_conn.cxx @@ -1,4 +1,5 @@ #include + #include using std::ifstream; @@ -8,37 +9,36 @@ using std::ostringstream; #include using std::string; -#include "common/db_conn.hxx" + #include "mysql.h" +#include "common/db_conn.hxx" + string db_info_filename = "../exact_mnist_batch2_db_info"; -MYSQL* exact_db_conn = NULL; +MYSQL *exact_db_conn = NULL; void set_db_info_filename(string _filename) { db_info_filename = _filename; } -void __mysql_check(string query, const char* file, const int line) { - if (exact_db_conn == NULL) { - initialize_exact_database(); - } +void __mysql_check(string query, const char *file, const int line) { + if (exact_db_conn == NULL) initialize_exact_database(); mysql_query(exact_db_conn, query.c_str()); if (mysql_errno(exact_db_conn) != 0) { ostringstream ex_msg; - ex_msg << "ERROR in MySQL query: '" << query.c_str() << "'. Error: " << mysql_errno(exact_db_conn) << " -- '" - << mysql_error(exact_db_conn) << "'. Thrown on " << file << ":" << line; + ex_msg << "ERROR in MySQL query: '" << query.c_str() << "'. Error: " << mysql_errno(exact_db_conn) << " -- '" << mysql_error(exact_db_conn) << "'. Thrown on " << file << ":" << line; fprintf(stderr, "%s\n", ex_msg.str().c_str()); exit(1); - } + } } void initialize_exact_database() { exact_db_conn = mysql_init(NULL); - // shoud get database info from a file + //shoud get database info from a file string db_host, db_name, db_password, db_user, db_port_s; ifstream db_info_file(db_info_filename); @@ -52,22 +52,15 @@ void initialize_exact_database() { db_info_file.close(); - fprintf( - stderr, "parsed db info, host: '%s', name: '%s', user: '%s', pass: '%s', port: '%d'\n", db_host.c_str(), - db_name.c_str(), db_user.c_str(), db_password.c_str(), db_port - ); - - if (mysql_real_connect( - exact_db_conn, db_host.c_str(), db_user.c_str(), db_password.c_str(), db_name.c_str(), db_port, NULL, 0 - ) - == NULL) { - fprintf( - stderr, "Error connecting to database: %d, '%s'\n", mysql_errno(exact_db_conn), mysql_error(exact_db_conn) - ); + fprintf(stderr, "parsed db info, host: '%s', name: '%s', user: '%s', pass: '%s', port: '%d'\n", db_host.c_str(), db_name.c_str(), db_user.c_str(), db_password.c_str(), db_port); + + if (mysql_real_connect(exact_db_conn, db_host.c_str(), db_user.c_str(), db_password.c_str(), db_name.c_str(), db_port, NULL, 0) == NULL) { + fprintf(stderr, "Error connecting to database: %d, '%s'\n", mysql_errno(exact_db_conn), mysql_error(exact_db_conn)); exit(1); - } + } } int mysql_exact_last_insert_id() { return mysql_insert_id(exact_db_conn); } + diff --git a/common/db_conn.hxx b/common/db_conn.hxx index 9fa1e0e4..7be72456 100644 --- a/common/db_conn.hxx +++ b/common/db_conn.hxx @@ -5,11 +5,11 @@ #define mysql_exact_query(query) __mysql_check(query, __FILE__, __LINE__) -extern MYSQL* exact_db_conn; +extern MYSQL *exact_db_conn; void set_db_info_filename(string _filename); -void __mysql_check(string query, const char* file, const int line); +void __mysql_check(string query, const char *file, const int line); void initialize_exact_database(); diff --git a/common/exp.cxx b/common/exp.cxx index a970fd62..fac3cf3f 100644 --- a/common/exp.cxx +++ b/common/exp.cxx @@ -1,6 +1,7 @@ #ifdef EXACT_MATH_TEST #include #include + #include using std::cout; using std::endl; @@ -12,14 +13,12 @@ using std::endl; #define iterations 50 -// calculate exp slowly using a taylor series to prevent -// os/compiler inconsistencies +//calculate exp slowly using a taylor series to prevent +//os/compiler inconsistencies float exact_exp(float z) { bool is_negative = z < 0; - if (is_negative) { - z = -z; - } + if (is_negative) z = -z; // exp(x) = sum (k = 0 to inf) z^k/k! float result = 1.0 + z; @@ -37,10 +36,9 @@ float exact_exp(float z) { } } + float exact_sqrt(float s) { - if (s == 0) { - return 0.0; - } + if (s == 0) return 0.0; float s_prev = s; @@ -63,7 +61,8 @@ float exact_sqrt(float s) { #ifdef EXACT_MATH_TEST -int main(int argc, char** argv) { +int main(int argc, char **argv) { + float value = 0.932; for (int i = 0; i < 100; i++) { diff --git a/common/files.cxx b/common/files.cxx index 76cffbaa..6ada1efd 100644 --- a/common/files.cxx +++ b/common/files.cxx @@ -1,11 +1,14 @@ #include + #include using std::runtime_error; + + #include using std::ifstream; -using std::ios; using std::istreambuf_iterator; +using std::ios; #include using std::cerr; @@ -18,19 +21,20 @@ using std::ostringstream; #include using std::string; -// for mkdir -#include +//for mkdir #include +#include #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ typedef struct stat Stat; + #include "files.hxx" string get_file_as_string(string file_path) noexcept(false) { - // read the entire contents of the file into a string + //read the entire contents of the file into a string ifstream sites_file(file_path.c_str()); if (!sites_file.is_open()) { @@ -39,7 +43,7 @@ string get_file_as_string(string file_path) noexcept(false) { string fc; - sites_file.seekg(0, ios::end); + sites_file.seekg(0, ios::end); fc.reserve(sites_file.tellg()); sites_file.seekg(0, ios::beg); @@ -47,18 +51,17 @@ string get_file_as_string(string file_path) noexcept(false) { ostringstream oss; for (uint32_t i = 0; i < fc.size(); i++) { - if (fc[i] != '\r') { - oss << fc[i]; - } + if (fc[i] != '\r') oss << fc[i]; } return oss.str(); } -// tweaked from: https://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux/29828907 -static int do_mkdir(const char* path, mode_t mode) { - Stat st; - int status = 0; + +//tweaked from: https://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux/29828907 +static int do_mkdir(const char *path, mode_t mode) { + Stat st; + int status = 0; if (stat(path, &st) != 0) { /* Directory does not exist. EEXIST for race condition */ @@ -71,7 +74,7 @@ static int do_mkdir(const char* path, mode_t mode) { status = -1; } - return (status); + return(status); } /** @@ -80,16 +83,16 @@ static int do_mkdir(const char* path, mode_t mode) { * ** each directory in path exists, rather than optimistically creating * ** the last element and working backwards. * */ -int mkpath(const char* path, mode_t mode) { - char* pp; - char* sp; - int status; - char* copypath = strdup(path); +int mkpath(const char *path, mode_t mode) { + char *pp; + char *sp; + int status; + char *copypath = strdup(path); status = 0; pp = copypath; while (status == 0 && (sp = strchr(pp, '/')) != 0) { - // cerr << "trying to create directory: " << copypath << endl; + //cerr << "trying to create directory: " << copypath << endl; if (sp != pp) { /* Neither root nor double slash in path */ *sp = '\0'; @@ -106,3 +109,5 @@ int mkpath(const char* path, mode_t mode) { free(copypath); return (status); } + + diff --git a/common/files.hxx b/common/files.hxx index ac23ff0d..d662486c 100644 --- a/common/files.hxx +++ b/common/files.hxx @@ -7,8 +7,9 @@ using std::runtime_error; #include using std::string; + string get_file_as_string(string file_path) noexcept(false); -int mkpath(const char* path, mode_t mode); +int mkpath(const char *path, mode_t mode); #endif diff --git a/common/log.cxx b/common/log.cxx index 623475e8..928a46c0 100644 --- a/common/log.cxx +++ b/common/log.cxx @@ -4,7 +4,7 @@ using std::printf; using std::snprintf; using std::vsnprintf; -// for va_list, va_start +//for va_list, va_start #include #include @@ -17,6 +17,7 @@ using std::thread; #include "files.hxx" #include "log.hxx" + using std::cerr; using std::endl; @@ -40,12 +41,12 @@ LogFile::LogFile(FILE* _file) { } void Log::register_command_line_arguments() { - // CommandLine::create_group("Log", ""); - // CommandLine:: + //CommandLine::create_group("Log", ""); + //CommandLine:: } int8_t Log::parse_level_from_string(string level) { - if (level.compare("0") == 0 || level.compare("NONE") == 0 || level.compare("none") == 0) { + if (level.compare("0") == 0 || level.compare("NONE") == 0|| level.compare("none") == 0) { return Log::NONE; } else if (level.compare("1") == 0 || level.compare("FATAL") == 0 || level.compare("fatal") == 0) { return Log::FATAL; @@ -76,8 +77,8 @@ int8_t Log::parse_level_from_string(string level) { } } -void Log::initialize(const vector& arguments) { - // TODO: should read these from the CommandLine (to be created) +void Log::initialize(const vector &arguments) { + //TODO: should read these from the CommandLine (to be created) string std_message_level_str, file_message_level_str; @@ -88,11 +89,12 @@ void Log::initialize(const vector& arguments) { std_message_level = parse_level_from_string(std_message_level_str); file_message_level = parse_level_from_string(file_message_level_str); - // cerr << "std_message_level: " << std_message_level << ", file_message_level: " << file_message_level << endl; + //cerr << "std_message_level: " << std_message_level << ", file_message_level: " << file_message_level << endl; get_argument(arguments, "--max_header_length", false, max_header_length); get_argument(arguments, "--max_message_length", false, max_message_length); + mkpath(output_directory.c_str(), 0777); } @@ -111,7 +113,7 @@ void Log::clear_rank_restriction() { void Log::set_id(string human_readable_id) { thread::id id = std::this_thread::get_id(); - // cerr << "setting thread id " << id << " to human readable id: '" << human_readable_id << "'" << endl; + //cerr << "setting thread id " << id << " to human readable id: '" << human_readable_id << "'" << endl; log_ids_mutex.lock(); @@ -121,17 +123,19 @@ void Log::set_id(string human_readable_id) { } void Log::release_id(string human_readable_id) { - // cerr << "locking thread from human readable id: '" << human_readable_id << "'" << endl; + + //cerr << "locking thread from human readable id: '" << human_readable_id << "'" << endl; log_ids_mutex.lock(); - // cerr << "releasing thread from human readable id: '" << human_readable_id << "'" << endl; + //cerr << "releasing thread from human readable id: '" << human_readable_id << "'" << endl; if (output_files.count(human_readable_id) == 0) { - // this file was never created and written to + //this file was never created and written to - // cerr << "ERROR: log id '" << human_readable_id << "' was either already released or not previously set!" << - // endl; exit(1); + //cerr << "ERROR: log id '" << human_readable_id << "' was either already released or not previously set!" << endl; + //exit(1); } else { - LogFile* log_file = output_files[human_readable_id]; + + LogFile *log_file = output_files[human_readable_id]; fflush(log_file->file); fclose(log_file->file); @@ -142,16 +146,13 @@ void Log::release_id(string human_readable_id) { log_ids_mutex.unlock(); } -void Log::write_message( - bool print_header, int8_t message_level, const char* message_type, const char* format, va_list arguments -) { + +void Log::write_message(bool print_header, int8_t message_level, const char *message_type, const char *format, va_list arguments) { + thread::id id = std::this_thread::get_id(); if (log_ids.count(id) == 0) { - cerr << "ERROR: could not write message from thread '" << id - << "' because it did not have a human readable id assigned (please use the Log::set_id(string) function " - "before writing to the Log on any thread)." - << endl; + cerr << "ERROR: could not write message from thread '" << id << "' because it did not have a human readable id assigned (please use the Log::set_id(string) function before writing to the Log on any thread)." << endl; cerr << "message:" << endl; vprintf(format, arguments); cerr << endl; @@ -160,15 +161,15 @@ void Log::write_message( string human_readable_id = log_ids[id]; - // print the message header into a string + //print the message header into a string char header_buffer[max_header_length]; - // we only need to print the header for some messages + //we only need to print the header for some messages if (print_header) { - // snprintf(header_buffer, max_header_length, "[%-8s %-20s]", message_type, human_readable_id.c_str()); + //snprintf(header_buffer, max_header_length, "[%-8s %-20s]", message_type, human_readable_id.c_str()); snprintf(header_buffer, max_header_length, "[%-7s %-21s]", message_type, human_readable_id.c_str()); } - // print the actual message contents into a string + //print the actual message contents into a string char message_buffer[max_message_length]; vsnprintf(message_buffer, max_message_length, format, arguments); @@ -183,20 +184,20 @@ void Log::write_message( if (file_message_level >= message_level) { LogFile* log_file = NULL; - // check and see if we've already opened a file for this human readable id, if we haven't - // open a new one for it + //check and see if we've already opened a file for this human readable id, if we haven't + //open a new one for it if (output_files.count(human_readable_id) == 0) { string output_filename = output_directory + "/" + human_readable_id; - FILE* outfile = fopen(output_filename.c_str(), "w"); + FILE *outfile = fopen(output_filename.c_str(), "w"); log_file = new LogFile(outfile); output_files[human_readable_id] = log_file; } else { log_file = output_files[human_readable_id]; } - // lock this log_file in case multiple threads are trying to write - // to the same file + //lock this log_file in case multiple threads are trying to write + //to the same file log_file->file_mutex.lock(); if (print_header) { fprintf(log_file->file, "%s %s", header_buffer, message_buffer); @@ -212,16 +213,12 @@ bool Log::at_level(int8_t level) { return level >= std_message_level || level >= file_message_level; } -void Log::fatal(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } +void Log::fatal(const char *format, ...) { + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < FATAL && file_message_level < FATAL) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < FATAL && file_message_level < FATAL) return; va_list arguments; va_start(arguments, format); @@ -229,15 +226,11 @@ void Log::fatal(const char* format, ...) { } void Log::error(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < ERROR && file_message_level < ERROR) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < ERROR && file_message_level < ERROR) return; va_list arguments; va_start(arguments, format); @@ -245,15 +238,11 @@ void Log::error(const char* format, ...) { } void Log::warning(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < WARNING && file_message_level < WARNING) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < WARNING && file_message_level < WARNING) return; va_list arguments; va_start(arguments, format); @@ -261,15 +250,11 @@ void Log::warning(const char* format, ...) { } void Log::info(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < INFO && file_message_level < INFO) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < INFO && file_message_level < INFO) return; va_list arguments; va_start(arguments, format); @@ -277,15 +262,11 @@ void Log::info(const char* format, ...) { } void Log::debug(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < DEBUG && file_message_level < DEBUG) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < DEBUG && file_message_level < DEBUG) return; va_list arguments; va_start(arguments, format); @@ -293,31 +274,23 @@ void Log::debug(const char* format, ...) { } void Log::trace(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < TRACE && file_message_level < TRACE) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < TRACE && file_message_level < TRACE) return; va_list arguments; va_start(arguments, format); write_message(true, TRACE, "TRACE", format, arguments); } -void Log::fatal_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } +void Log::fatal_no_header(const char *format, ...) { + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < FATAL && file_message_level < FATAL) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < FATAL && file_message_level < FATAL) return; va_list arguments; va_start(arguments, format); @@ -325,15 +298,11 @@ void Log::fatal_no_header(const char* format, ...) { } void Log::error_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < ERROR && file_message_level < ERROR) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < ERROR && file_message_level < ERROR) return; va_list arguments; va_start(arguments, format); @@ -341,15 +310,11 @@ void Log::error_no_header(const char* format, ...) { } void Log::warning_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < WARNING && file_message_level < WARNING) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < WARNING && file_message_level < WARNING) return; va_list arguments; va_start(arguments, format); @@ -357,15 +322,11 @@ void Log::warning_no_header(const char* format, ...) { } void Log::info_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < INFO && file_message_level < INFO) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < INFO && file_message_level < INFO) return; va_list arguments; va_start(arguments, format); @@ -373,15 +334,11 @@ void Log::info_no_header(const char* format, ...) { } void Log::debug_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < DEBUG && file_message_level < DEBUG) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < DEBUG && file_message_level < DEBUG) return; va_list arguments; va_start(arguments, format); @@ -389,17 +346,14 @@ void Log::debug_no_header(const char* format, ...) { } void Log::trace_no_header(const char* format, ...) { - // don't write if this is the wrong process rank - if (restricted_rank >= 0 && restricted_rank != process_rank) { - return; - } + //don't write if this is the wrong process rank + if (restricted_rank >= 0 && restricted_rank != process_rank) return; - // not writing this type of message to either std out or a file - if (std_message_level < TRACE && file_message_level < TRACE) { - return; - } + //not writing this type of message to either std out or a file + if (std_message_level < TRACE && file_message_level < TRACE) return; va_list arguments; va_start(arguments, format); write_message(false, TRACE, "TRACE", format, arguments); } + diff --git a/common/log.hxx b/common/log.hxx index 1ab441f5..42dbbf8d 100644 --- a/common/log.hxx +++ b/common/log.hxx @@ -1,7 +1,8 @@ #ifndef EXONA_LOG #define EXONA_LOG -#include +#include + #include using std::ofstream; @@ -20,221 +21,197 @@ using std::string; #include using std::thread; -#include -using std::vector; - class LogFile { - private: - FILE* file; - mutex file_mutex; + private: + FILE* file; + mutex file_mutex; - public: - LogFile(FILE* file); + public: + LogFile(FILE* file); friend class Log; }; class Log { - private: - /** - * Specifies which messages to log. - * Messages will be written to the standard output log if their type is <= message_level. - */ - static int32_t std_message_level; - - /** - * Specifies which messages to log. - * Messages will be written to the log file if their type is <= message_level. - */ - - static int32_t file_message_level; - - /** - * Specifies if the logs should also be written to a flie. - */ - static bool write_to_file; - - /** - * Specifies the maximum length for the message header. - */ - static int32_t max_header_length; - - /** - * Specifies the maximum message buffer length. - */ - static int32_t max_message_length; - - /** - * Specifies which directory to write the log files to (if the logs - * are being writtten to a file). - */ - static string output_directory; - - /** - * A map of C++ thread ids (which are not human readable) to human - * readable integer ids. - * Thread ids are specified with the Log::set_id(string) - * method. - */ - static map log_ids; - - /** - * The MPI process rank for this Log instance. Set to -1 if not specified or not using MPI. - */ - static int32_t process_rank; - - /** - * Defaults at -1, when set to a process rank (>= 0) the Log will only print messages if its rank is the same as the - * restricted rank. This is useful, for allowing initialization messages to only be printed out by a single process. - */ - static int32_t restricted_rank; - - /** - * A map of human readable ids to output files which the log messages - * will be written to. - */ - static map output_files; - - /** - * A std::shared_mutex protecting the Log::thread_ids map. - * The Log::set_thread_id(int32_t) mehod needs write access so it will use the std::shared_mutex::lock()x and - * std::shared_mutex()::unlock() mechanism, while the Log::get_thread_id() only needs read access and can used the - * std::shared_mutex::lock_shared() and std::shared_mutex::unlock_shared() methods. - */ - static shared_mutex log_ids_mutex; - - /** - * Potentially writes the message to either standard output or the log file if the message level is high enough. - * - * \param print_header specifies if the header to the message should be printed out - * \param message_level the level of the message to potentially be printed out - * \param message_type a string representation of this message type - * \param message_type the format string for this message (as in printf) - * \param arguments the arguments for the print statement - */ - static void write_message( - bool print_header, int8_t message_level, const char* message_type, const char* format, va_list arguments - ); - - public: - static const int8_t NONE = 0; /**< Specifies no messages will be logged. */ - static const int8_t FATAL = 1; /**< Specifies only fatal messages will be logged. */ - static const int8_t ERROR = 2; /**< Specifies error and above messages will be logged. */ - static const int8_t WARNING = 3; /**< Specifies warning and above messages will be logged. */ - static const int8_t INFO = 4; /**< Specifies info and above messages will be logged. */ - static const int8_t DEBUG = 5; /**< Specifies debug and above messages will be logged. */ - static const int8_t TRACE = 6; /**< Specifies trace and above messages will be logged. */ - static const int8_t ALL = 7; /**< Specifies all messages will be logged. */ - - /** - * Registers used command line arguments and instructions with the CommandLine class. - * Needs to be called at the beginning of the main method of any programming using the Log class. Will register the - * following command line arguments and instructions: - * -# log_level : specifies the max message level of messages to be printed - * -# log_directory : specifies the output directory for message logs - */ - static void register_command_line_arguments(); - - /** - * \param a string representation of the message level, either as text (e.g., "INFO") or as a number (e.g., 4) - * - * \return the message level as an int8_t (i.e., one of the message level constants) - */ - static int8_t parse_level_from_string(string level); - - /** - * Initializes the Log given arguments retreived from the CommandLine class. - * \param arguments the command line arguments - * Log::register_command_line_arguments() must be called before Log::initialize() - */ - static void initialize(const vector& arguments); - - /** - * Sets the MPI process rank for this Log. - * - * \param _process_rank is the MPI rank of this process - */ - static void set_rank(int32_t _process_rank); - - /** - * Specifies which MPI process to allow messages from. A value < 0 will allow messages from any rank. - *\param _restricted_rank is the MPI rank to only print messages from - */ - static void restrict_to_rank(int32_t _restricted_rank); - - /** - * Clears the MPI process rank restriction from messages allowing any process to write to the log (sets - * Log::restricted_rank back to -1). - */ - static void clear_rank_restriction(); - - /** - * Sets a human readable thread id for this thread. - * - * This will use std::this_thread::get_id() to get c++'s automatically - * generated thread id, and then put it in the Log::thread_ids map, so - * it can be used to write cleaner logs. - * - * This will report an error and exit if another thread has already - * reserved this human readable id. - * - * \param human_readable_id a human readable thread id - */ - static void set_id(string human_readable_id); - - /** - * Releases a the human readable thread id previously set - * by by the provided human readable id; - * - * This will report an error and exit if this human readable id - * has not already been set, or if it has been relased by another - * thread. - * - * \param human_readable_id is a human readable thread id which has previously been set with Log::set_id(string) - */ - static void release_id(string human_readable_id); - - /** - * Determines if either output level (the file or standard output) level - * is above the level passed as a parameter. - * - * \param level is the level to be greater than or equal to - * - * \return true if either the file or standard output level is greater than or equal to the passed level - */ - static bool at_level(int8_t level); - - static void fatal(const char* format, ...); /**< Logs a fatal message. varargs are the same as in printf. */ - static void error(const char* format, ...); /**< Logs an error message. varargs are the same as in printf. */ - static void warning(const char* format, ...); /**< Logs a warning message. varargs are the same as in printf. */ - static void info(const char* format, ...); /**< Logs an info message. varargs are the same as in printf. */ - static void debug(const char* format, ...); /**< Logs a debug message. varargs are the same as in printf. */ - static void trace(const char* format, ...); /**< Logs a trace message. varargs are the same as in printf. */ - - static void fatal_no_header( - const char* format, ... - ); /**< Logs a fatal message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ - static void error_no_header( - const char* format, ... - ); /**< Logs an error message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ - static void warning_no_header( - const char* format, ... - ); /**< Logs a warning message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ - static void info_no_header( - const char* format, ... - ); /**< Logs an info message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ - static void debug_no_header( - const char* format, ... - ); /**< Logs a debug message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ - static void trace_no_header( - const char* format, ... - ); /**< Logs a trace message. Does not print the message header (useful if doing - multiple log prints to the same line). varargs are the same as in printf. */ + private: + /** + * Specifies which messages to log. + * Messages will be written to the standard output log if their type is <= message_level. + */ + static int32_t std_message_level; + + /** + * Specifies which messages to log. + * Messages will be written to the log file if their type is <= message_level. + */ + + static int32_t file_message_level; + + /** + * Specifies if the logs should also be written to a flie. + */ + static bool write_to_file; + + /** + * Specifies the maximum length for the message header. + */ + static int32_t max_header_length; + + /** + * Specifies the maximum message buffer length. + */ + static int32_t max_message_length; + + /** + * Specifies which directory to write the log files to (if the logs + * are being writtten to a file). + */ + static string output_directory; + + /** + * A map of C++ thread ids (which are not human readable) to human + * readable integer ids. + * Thread ids are specified with the Log::set_id(string) + * method. + */ + static map log_ids; + + /** + * The MPI process rank for this Log instance. Set to -1 if not specified or not using MPI. + */ + static int32_t process_rank; + + /** + * Defaults at -1, when set to a process rank (>= 0) the Log will only print messages if its rank is the same as the restricted rank. This is useful, for allowing initialization messages to only be printed out by a single process. + */ + static int32_t restricted_rank; + + /** + * A map of human readable ids to output files which the log messages + * will be written to. + */ + static map output_files; + + /** + * A std::shared_mutex protecting the Log::thread_ids map. + * The Log::set_thread_id(int32_t) mehod needs write access so it will use the std::shared_mutex::lock()x and std::shared_mutex()::unlock() mechanism, while the Log::get_thread_id() only needs read access and can used the std::shared_mutex::lock_shared() and std::shared_mutex::unlock_shared() methods. + */ + static shared_mutex log_ids_mutex; + + + /** + * Potentially writes the message to either standard output or the log file if the message level is high enough. + * + * \param print_header specifies if the header to the message should be printed out + * \param message_level the level of the message to potentially be printed out + * \param message_type a string representation of this message type + * \param message_type the format string for this message (as in printf) + * \param arguments the arguments for the print statement + */ + static void write_message(bool print_header, int8_t message_level, const char *message_type, const char *format, va_list arguments); + + public: + static const int8_t NONE = 0; /**< Specifies no messages will be logged. */ + static const int8_t FATAL = 1; /**< Specifies only fatal messages will be logged. */ + static const int8_t ERROR = 2; /**< Specifies error and above messages will be logged. */ + static const int8_t WARNING = 3; /**< Specifies warning and above messages will be logged. */ + static const int8_t INFO = 4; /**< Specifies info and above messages will be logged. */ + static const int8_t DEBUG = 5; /**< Specifies debug and above messages will be logged. */ + static const int8_t TRACE = 6; /**< Specifies trace and above messages will be logged. */ + static const int8_t ALL = 7; /**< Specifies all messages will be logged. */ + + /** + * Registers used command line arguments and instructions with the CommandLine class. + * Needs to be called at the beginning of the main method of any programming using the Log class. Will register the following command line arguments and instructions: + * -# log_level : specifies the max message level of messages to be printed + * -# log_directory : specifies the output directory for message logs + */ + static void register_command_line_arguments(); + + /** + * \param a string representation of the message level, either as text (e.g., "INFO") or as a number (e.g., 4) + * + * \return the message level as an int8_t (i.e., one of the message level constants) + */ + static int8_t parse_level_from_string(string level); + + /** + * Initializes the Log given arguments retreived from the CommandLine class. + * \param arguments the command line arguments + * Log::register_command_line_arguments() must be called before Log::initialize() + */ + static void initialize(const vector &arguments); + + /** + * Sets the MPI process rank for this Log. + * + * \param _process_rank is the MPI rank of this process + */ + static void set_rank(int32_t _process_rank); + + /** + * Specifies which MPI process to allow messages from. A value < 0 will allow messages from any rank. + *\param _restricted_rank is the MPI rank to only print messages from + */ + static void restrict_to_rank(int32_t _restricted_rank); + + /** + * Clears the MPI process rank restriction from messages allowing any process to write to the log (sets Log::restricted_rank back to -1). + */ + static void clear_rank_restriction(); + + /** + * Sets a human readable thread id for this thread. + * + * This will use std::this_thread::get_id() to get c++'s automatically + * generated thread id, and then put it in the Log::thread_ids map, so + * it can be used to write cleaner logs. + * + * This will report an error and exit if another thread has already + * reserved this human readable id. + * + * \param human_readable_id a human readable thread id + */ + static void set_id(string human_readable_id); + + /** + * Releases a the human readable thread id previously set + * by by the provided human readable id; + * + * This will report an error and exit if this human readable id + * has not already been set, or if it has been relased by another + * thread. + * + * \param human_readable_id is a human readable thread id which has previously been set with Log::set_id(string) + */ + static void release_id(string human_readable_id); + + + /** + * Determines if either output level (the file or standard output) level + * is above the level passed as a parameter. + * + * \param level is the level to be greater than or equal to + * + * \return true if either the file or standard output level is greater than or equal to the passed level + */ + static bool at_level(int8_t level); + + static void fatal(const char* format, ...); /**< Logs a fatal message. varargs are the same as in printf. */ + static void error(const char* format, ...); /**< Logs an error message. varargs are the same as in printf. */ + static void warning(const char* format, ...); /**< Logs a warning message. varargs are the same as in printf. */ + static void info(const char* format, ...); /**< Logs an info message. varargs are the same as in printf. */ + static void debug(const char* format, ...); /**< Logs a debug message. varargs are the same as in printf. */ + static void trace(const char* format, ...); /**< Logs a trace message. varargs are the same as in printf. */ + + static void fatal_no_header(const char* format, ...); /**< Logs a fatal message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + static void error_no_header(const char* format, ...); /**< Logs an error message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + static void warning_no_header(const char* format, ...); /**< Logs a warning message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + static void info_no_header(const char* format, ...); /**< Logs an info message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + static void debug_no_header(const char* format, ...); /**< Logs a debug message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + static void trace_no_header(const char* format, ...); /**< Logs a trace message. Does not print the message header (useful if doing multiple log prints to the same line). varargs are the same as in printf. */ + }; + #endif diff --git a/common/process_arguments.cxx b/common/process_arguments.cxx index f4bf87a8..4d124442 100644 --- a/common/process_arguments.cxx +++ b/common/process_arguments.cxx @@ -7,10 +7,7 @@ using std::vector; #include "process_arguments.hxx" #include "rnn/generate_nn.hxx" -EXAMM* generate_examm_from_arguments( - const vector& arguments, TimeSeriesSets* time_series_sets, WeightRules* weight_rules, - RNN_Genome* seed_genome -) { +EXAMM* generate_examm_from_arguments(const vector &arguments, TimeSeriesSets *time_series_sets, WeightRules *weight_rules, RNN_Genome *seed_genome) { Log::info("Getting arguments for EXAMM\n"); int32_t island_size; get_argument(arguments, "--island_size", true, island_size); @@ -22,55 +19,48 @@ EXAMM* generate_examm_from_arguments( get_argument(arguments, "--output_directory", false, output_directory); vector possible_node_types; get_argument_vector(arguments, "--possible_node_types", false, possible_node_types); + double learning_rate = 0.0069; - Log::info( - "Setting up examm with %d islands, island size %d, and max_genome %d\n", number_islands, island_size, - max_genomes - ); + Log::info("Setting up examm with %d islands, island size %d, and max_genome %d\n", number_islands, island_size, max_genomes); // random_sequence_length = argument_exists(arguments, "--random_sequence_length"); // get_argument(arguments, "--sequence_length_lower_bound", false, sequence_length_lower_bound); // get_argument(arguments, "--sequence_length_upper_bound", false, sequence_length_upper_bound); - GenomeProperty* genome_property = new GenomeProperty(); + GenomeProperty *genome_property = new GenomeProperty(); genome_property->generate_genome_property_from_arguments(arguments); genome_property->get_time_series_parameters(time_series_sets); - SpeciationStrategy* speciation_strategy = generate_speciation_strategy_from_arguments(arguments, seed_genome); + SpeciationStrategy *speciation_strategy = generate_speciation_strategy_from_arguments(arguments, seed_genome); - EXAMM* examm = new EXAMM( - island_size, number_islands, max_genomes, speciation_strategy, weight_rules, genome_property, output_directory - ); - if (possible_node_types.size() > 0) { - examm->set_possible_node_types(possible_node_types); - } + EXAMM* examm = new EXAMM(island_size, number_islands, max_genomes, learning_rate, speciation_strategy, weight_rules, genome_property, output_directory); + if (possible_node_types.size() > 0) examm->set_possible_node_types(possible_node_types); return examm; } -SpeciationStrategy* generate_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -) { - SpeciationStrategy* speciation_strategy = NULL; +SpeciationStrategy* generate_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome) { + SpeciationStrategy *speciation_strategy = NULL; string speciation_method = ""; get_argument(arguments, "--speciation_method", false, speciation_method); if (is_island_strategy(speciation_method)) { Log::info("Using Island speciation strategy\n"); - speciation_strategy = generate_island_speciation_strategy_from_arguments(arguments, seed_genome); - } else if (is_neat_strategy(speciation_method)) { + speciation_strategy= generate_island_speciation_strategy_from_arguments(arguments, seed_genome); + } + else if (is_neat_strategy(speciation_method)) { Log::info("Using Neat speciation strategy\n"); speciation_strategy = generate_neat_speciation_strategy_from_arguments(arguments, seed_genome); - } else { + } + else { Log::fatal("Wrong speciation strategy method %s\n", speciation_method.c_str()); exit(1); } return speciation_strategy; } -IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -) { +IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome) { + int32_t island_size; get_argument(arguments, "--island_size", true, island_size); int32_t number_islands; @@ -101,21 +91,19 @@ IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments( int32_t seed_stirs = 0; get_argument(arguments, "--seed_stirs", false, seed_stirs); bool start_filled = argument_exists(arguments, "--start_filled"); - bool tl_epigenetic_weights = argument_exists(arguments, "--tl_epigenetic_weights"); - - IslandSpeciationStrategy* island_strategy = new IslandSpeciationStrategy( - number_islands, island_size, mutation_rate, intra_island_co_rate, inter_island_co_rate, seed_genome, - island_ranking_method, repopulation_method, extinction_event_generation_number, num_mutations, - islands_to_exterminate, max_genomes, repeat_extinction, start_filled, transfer_learning, - transfer_learning_version, seed_stirs, tl_epigenetic_weights - ); - + bool tl_epigenetic_weights = argument_exists(arguments, "--tl_epigenetic_weights"); + + IslandSpeciationStrategy *island_strategy = new IslandSpeciationStrategy( + number_islands, island_size, mutation_rate, intra_island_co_rate, inter_island_co_rate, + seed_genome, island_ranking_method, repopulation_method, extinction_event_generation_number, + num_mutations, islands_to_exterminate, max_genomes, repeat_extinction, start_filled, + transfer_learning, transfer_learning_version, seed_stirs, tl_epigenetic_weights); + return island_strategy; } -NeatSpeciationStrategy* generate_neat_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -) { +NeatSpeciationStrategy* generate_neat_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome) { + // bool seed_genome_was_minimal = true; double species_threshold = 0.0; get_argument(arguments, "--species_threshold", false, species_threshold); @@ -129,30 +117,21 @@ NeatSpeciationStrategy* generate_neat_speciation_strategy_from_arguments( get_argument(arguments, "--neat_c3", false, neat_c3); double mutation_rate = 0.70, intra_island_co_rate = 0.20, inter_island_co_rate = 0.10; - NeatSpeciationStrategy* neat_strategy = new NeatSpeciationStrategy( - mutation_rate, intra_island_co_rate, inter_island_co_rate, seed_genome, species_threshold, fitness_threshold, - neat_c1, neat_c2, neat_c3 - ); + NeatSpeciationStrategy *neat_strategy = new NeatSpeciationStrategy(mutation_rate, intra_island_co_rate, inter_island_co_rate, seed_genome, species_threshold, fitness_threshold, neat_c1, neat_c2, neat_c3); return neat_strategy; } -bool is_island_strategy(string strategy_name) { - if (strategy_name.compare("") == 0 || strategy_name.compare("island") == 0) { - return true; - } else { - return false; - } +bool is_island_strategy (string strategy_name) { + if (strategy_name.compare("") == 0 || strategy_name.compare("island") == 0) return true; + else return false; } -bool is_neat_strategy(string strategy_name) { - if (strategy_name.compare("neat") == 0) { - return true; - } else { - return false; - } +bool is_neat_strategy (string strategy_name) { + if (strategy_name.compare("neat") == 0) return true; + else return false; } -void write_time_series_to_file(const vector& arguments, TimeSeriesSets* time_series_sets) { +void write_time_series_to_file(const vector &arguments, TimeSeriesSets *time_series_sets) { if (argument_exists(arguments, "--write_time_series")) { string base_filename; get_argument(arguments, "--write_time_series", true, base_filename); @@ -160,11 +139,7 @@ void write_time_series_to_file(const vector& arguments, TimeSeriesSets* } } -void get_train_validation_data( - const vector& arguments, TimeSeriesSets* time_series_sets, vector > >& train_inputs, - vector > >& train_outputs, vector > >& validation_inputs, - vector > >& validation_outputs -) { +void get_train_validation_data(const vector &arguments, TimeSeriesSets *time_series_sets, vector< vector< vector > > &train_inputs, vector< vector< vector > > &train_outputs, vector< vector< vector > > &validation_inputs, vector< vector< vector > > &validation_outputs) { int32_t time_offset = 1; get_argument(arguments, "--time_offset", true, time_offset); @@ -174,24 +149,22 @@ void get_train_validation_data( int32_t sequence_length = 0; if (get_argument(arguments, "--sequence_length", false, sequence_length)) { Log::info("Slicing input training data with time sequence length: %d\n", sequence_length); - slice_input_data(train_inputs, train_outputs, sequence_length); + slice_input_data(train_inputs, train_outputs, sequence_length); } Log::info("Generating time series data finished! \n"); } -void slice_input_data( - vector > >& inputs, vector > >& outputs, int32_t sequence_length -) { - vector > > sliced_inputs; - vector > > sliced_outputs; - for (int32_t n = 0; n < (int32_t) inputs.size(); n++) { - int32_t num_row = (int32_t) inputs[n][0].size(); - int32_t num_inputs = (int32_t) inputs[n].size(); - int32_t num_outputs = (int32_t) outputs[n].size(); +void slice_input_data(vector< vector< vector > > &inputs, vector< vector< vector > > &outputs, int32_t sequence_length) { + vector< vector< vector > > sliced_inputs; + vector< vector< vector > > sliced_outputs; + for (int32_t n = 0; n < (int32_t)inputs.size(); n++) { + int32_t num_row = (int32_t)inputs[n][0].size(); + int32_t num_inputs = (int32_t)inputs[n].size(); + int32_t num_outputs = (int32_t)outputs[n].size(); int32_t current_row = 0; while (current_row + sequence_length <= num_row) { - vector > current_time_series_input; // > - vector > current_time_series_output; // > + vector< vector > current_time_series_input; // > + vector< vector > current_time_series_output; // > current_time_series_input = slice_time_series(current_row, sequence_length, num_inputs, inputs[n]); current_time_series_output = slice_time_series(current_row, sequence_length, num_outputs, outputs[n]); sliced_inputs.push_back(current_time_series_input); @@ -203,29 +176,20 @@ void slice_input_data( inputs.clear(); outputs.clear(); - - inputs.assign(sliced_inputs.begin(), sliced_inputs.end()); + + inputs.assign(sliced_inputs.begin(), sliced_inputs.end()); outputs.assign(sliced_outputs.begin(), sliced_outputs.end()); - Log::info( - "After slicing, sliced training input data has %d sets, and %d parameters and length %d \n", inputs.size(), - inputs[0].size(), inputs[0][0].size() - ); - Log::info( - "After slicing, sliced training output data has %d sets, and %d parameters and length %d \n", outputs.size(), - outputs[0].size(), outputs[0][0].size() - ); + Log::info("After slicing, sliced training input data has %d sets, and %d parameters and length %d \n", inputs.size(), inputs[0].size(), inputs[0][0].size()); + Log::info("After slicing, sliced training output data has %d sets, and %d parameters and length %d \n", outputs.size(), outputs[0].size(), outputs[0][0].size()); } -vector > slice_time_series( - int32_t start_index, int32_t sequence_length, int32_t num_parameter, const vector >& time_series -) { - vector > current_time_series; +vector< vector > slice_time_series(int32_t start_index, int32_t sequence_length, int32_t num_parameter, const vector< vector > &time_series) { + vector< vector > current_time_series; for (int32_t j = 0; j < num_parameter; j++) { vector current_parameter_slice; - current_parameter_slice.assign( - time_series[j].begin() + start_index, time_series[j].begin() + start_index + sequence_length - ); + current_parameter_slice.assign(time_series[j].begin() + start_index, time_series[j].begin()+ start_index + sequence_length); current_time_series.push_back(current_parameter_slice); } return current_time_series; } + diff --git a/common/process_arguments.hxx b/common/process_arguments.hxx index 2760f966..39e481af 100644 --- a/common/process_arguments.hxx +++ b/common/process_arguments.hxx @@ -12,44 +12,24 @@ using std::vector; #include "common/arguments.hxx" #include "common/log.hxx" -#include "examm/examm.hxx" #include "examm/island_speciation_strategy.hxx" #include "examm/neat_speciation_strategy.hxx" -#include "rnn/rnn_genome.hxx" +#include "examm/examm.hxx" #include "time_series/time_series.hxx" +#include "rnn/rnn_genome.hxx" + +EXAMM* generate_examm_from_arguments(const vector &arguments, TimeSeriesSets *time_series_sets, WeightRules *weight_rules, RNN_Genome *seed_genome); +SpeciationStrategy* generate_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome); +IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome); +NeatSpeciationStrategy* generate_neat_speciation_strategy_from_arguments(const vector &arguments, RNN_Genome *seed_genome); + +bool is_island_strategy (string strategy_name); +bool is_neat_strategy (string strategy_name); +void set_island_transfer_learning_parameters(const vector &arguments, IslandSpeciationStrategy *island_strategy); -EXAMM* generate_examm_from_arguments( - const vector& arguments, TimeSeriesSets* time_series_sets, WeightRules* weight_rules, - RNN_Genome* seed_genome -); -SpeciationStrategy* generate_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -); -IslandSpeciationStrategy* generate_island_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -); -NeatSpeciationStrategy* generate_neat_speciation_strategy_from_arguments( - const vector& arguments, RNN_Genome* seed_genome -); - -bool is_island_strategy(string strategy_name); -bool is_neat_strategy(string strategy_name); -void set_island_transfer_learning_parameters( - const vector& arguments, IslandSpeciationStrategy* island_strategy -); - -void write_time_series_to_file(const vector& arguments, TimeSeriesSets* time_series_sets); -void get_train_validation_data( - const vector& arguments, TimeSeriesSets* time_series_sets, vector > >& traing_inputs, - vector > >& train_outputs, vector > >& test_inputs, - vector > >& test_outputs -); -void slice_input_data( - vector > >& traing_inputs, vector > >& train_outputs, - int32_t sequence_length -); -vector > slice_time_series( - int32_t start_index, int32_t sequence_length, int32_t num_parameter, const vector >& time_series -); +void write_time_series_to_file(const vector &arguments, TimeSeriesSets *time_series_sets); +void get_train_validation_data(const vector &arguments, TimeSeriesSets *time_series_sets, vector< vector< vector > > &traing_inputs, vector< vector< vector > > &train_outputs, vector< vector< vector > > &test_inputs, vector< vector< vector > > &test_outputs); +void slice_input_data(vector< vector< vector > > &traing_inputs, vector< vector< vector > > &train_outputs, int32_t sequence_length); +vector< vector > slice_time_series(int32_t start_index, int32_t sequence_length, int32_t num_parameter, const vector< vector > &time_series); #endif \ No newline at end of file diff --git a/common/random.cxx b/common/random.cxx index fce44fe1..46d4857d 100644 --- a/common/random.cxx +++ b/common/random.cxx @@ -1,13 +1,14 @@ +#include #include +#include #include -#include + #include -#include using std::setprecision; #include -using std::istream; using std::ostream; +using std::istream; #include using std::minstd_rand0; @@ -17,18 +18,18 @@ using std::vector; #include "random.hxx" -float random_0_1(minstd_rand0& generator) { - return ((float) generator() - (float) generator.min()) / ((float) generator.max() - (float) generator.min()); +float random_0_1(minstd_rand0 &generator) { + return ((float)generator() - (float)generator.min()) / ((float)generator.max() - (float)generator.min()); } -void fisher_yates_shuffle(minstd_rand0& generator, vector& v) { +void fisher_yates_shuffle(minstd_rand0 &generator, vector &v) { for (int32_t i = v.size() - 1; i > 0; i--) { - float t = ((float) generator() - (float) generator.min()) / ((float) generator.max() - (float) generator.min()); - t *= (float) i - 1.0; + float t = ((float)generator() - (float)generator.min()) / ((float)generator.max() - (float)generator.min()); + t *= (float)i - 1.0; - int32_t target = (int32_t) t; + int32_t target = (int32_t)t; - // cerr << "target: " << target << endl; + //cerr << "target: " << target << endl; int temp = v[target]; v[target] = v[i]; @@ -36,14 +37,15 @@ void fisher_yates_shuffle(minstd_rand0& generator, vector& v) { } } -void fisher_yates_shuffle(minstd_rand0& generator, vector& v) { + +void fisher_yates_shuffle(minstd_rand0 &generator, vector &v) { for (int32_t i = v.size() - 1; i > 0; i--) { - float t = ((float) generator() - (float) generator.min()) / ((float) generator.max() - (float) generator.min()); - t *= (float) i - 1.0; + float t = ((float)generator() - (float)generator.min()) / ((float)generator.max() - (float)generator.min()); + t *= (float)i - 1.0; - int32_t target = (int32_t) t; + int32_t target = (int32_t)t; - // cerr << "target: " << target << endl; + //cerr << "target: " << target << endl; long temp = v[target]; v[target] = v[i]; @@ -57,9 +59,9 @@ NormalDistribution::NormalDistribution() { z1 = 0; } -float NormalDistribution::random(minstd_rand0& generator, float mu, float sigma) { +float NormalDistribution::random(minstd_rand0 &generator, float mu, float sigma) { const float epsilon = std::numeric_limits::min(); - const float two_pi = 2.0 * 3.14159265358979323846; + const float two_pi = 2.0*3.14159265358979323846; generate = !generate; @@ -69,32 +71,35 @@ float NormalDistribution::random(minstd_rand0& generator, float mu, float sigma) float u1, u2; do { - u1 = ((float) generator() - (float) generator.min()) / ((float) generator.max() - (float) generator.min()); - u2 = ((float) generator() - (float) generator.min()) / ((float) generator.max() - (float) generator.min()); - } while (u1 <= epsilon); + u1 = ((float)generator() - (float)generator.min()) / ((float)generator.max() - (float)generator.min()); + u2 = ((float)generator() - (float)generator.min()) / ((float)generator.max() - (float)generator.min()); + } while ( u1 <= epsilon ); z0 = sqrt(-2.0 * log(u1)) * cos(two_pi * u2); z1 = sqrt(-2.0 * log(u1)) * sin(two_pi * u2); return z0 * sigma + mu; } -ostream& operator<<(ostream& os, const NormalDistribution& normal_distribution) { - os << normal_distribution.generate << " " << setprecision(15) << normal_distribution.z0 << " " << setprecision(15) - << normal_distribution.z1; +ostream &operator<<(ostream &os, const NormalDistribution &normal_distribution) { + os << normal_distribution.generate << " " << setprecision(15) << normal_distribution.z0 << " " << setprecision(15) << normal_distribution.z1; return os; } -istream& operator>>(istream& is, NormalDistribution& normal_distribution) { +istream &operator>>(istream &is, NormalDistribution &normal_distribution) { is >> normal_distribution.generate >> normal_distribution.z0 >> normal_distribution.z1; return is; } -bool NormalDistribution::operator==(const NormalDistribution& other) const { + +bool NormalDistribution::operator==(const NormalDistribution &other) const { return generate == other.generate && z0 == other.z0 && z1 == other.z1; } -bool NormalDistribution::operator!=(const NormalDistribution& other) const { +bool NormalDistribution::operator!=(const NormalDistribution &other) const { return generate != other.generate || z0 != other.z0 || z1 != other.z1; } + + + diff --git a/common/random.hxx b/common/random.hxx index 910a0d65..1ca3d2fd 100644 --- a/common/random.hxx +++ b/common/random.hxx @@ -2,8 +2,8 @@ #define EXACT_RANDOM_HXX #include -using std::istream; using std::ostream; +using std::istream; #include using std::minstd_rand0; @@ -11,27 +11,28 @@ using std::minstd_rand0; #include using std::vector; -void fisher_yates_shuffle(minstd_rand0& generator, vector& v); -void fisher_yates_shuffle(minstd_rand0& generator, vector& v); +void fisher_yates_shuffle(minstd_rand0 &generator, vector &v); +void fisher_yates_shuffle(minstd_rand0 &generator, vector &v); -float random_0_1(minstd_rand0& generator); +float random_0_1(minstd_rand0 &generator); class NormalDistribution { - private: - bool generate; - float z0; - float z1; + private: + bool generate; + float z0; + float z1; + + public: - public: - NormalDistribution(); + NormalDistribution(); - float random(minstd_rand0& generator, float mu, float sigma); + float random(minstd_rand0 &generator, float mu, float sigma); - friend ostream& operator<<(ostream& os, const NormalDistribution& normal_distribution); - friend istream& operator>>(istream& is, NormalDistribution& normal_distribution); + friend ostream &operator<<(ostream &os, const NormalDistribution &normal_distribution); + friend istream &operator>>(istream &is, NormalDistribution &normal_distribution); - bool operator==(const NormalDistribution& other) const; - bool operator!=(const NormalDistribution& other) const; + bool operator==(const NormalDistribution &other) const; + bool operator!=(const NormalDistribution &other) const; }; #endif diff --git a/examm/examm.cxx b/examm/examm.cxx index ce137d6f..293fdedc 100644 --- a/examm/examm.cxx +++ b/examm/examm.cxx @@ -3,6 +3,7 @@ using std::sort; #include #include + #include using std::bind; using std::function; @@ -11,36 +12,39 @@ using std::function; using std::ofstream; #include -using std::setprecision; using std::setw; +using std::setprecision; #include using std::endl; #include using std::minstd_rand0; -using std::uniform_int_distribution; using std::uniform_real_distribution; +using std::uniform_int_distribution; #include using std::string; using std::to_string; -#include "common/files.hxx" -#include "common/log.hxx" #include "examm.hxx" +#include "rnn/rnn_genome.hxx" +#include "rnn/generate_nn.hxx" +#include "speciation_strategy.hxx" #include "island_speciation_strategy.hxx" #include "neat_speciation_strategy.hxx" -#include "rnn/delta_node.hxx" -#include "rnn/generate_nn.hxx" -#include "rnn/gru_node.hxx" -#include "rnn/lstm_node.hxx" -#include "rnn/mgu_node.hxx" + #include "rnn/rnn.hxx" -#include "rnn/rnn_genome.hxx" #include "rnn/rnn_node.hxx" +#include "rnn/lstm_node.hxx" +#include "rnn/gru_node.hxx" +#include "rnn/delta_node.hxx" #include "rnn/ugrnn_node.hxx" -#include "speciation_strategy.hxx" +#include "rnn/mgu_node.hxx" + +#include "common/files.hxx" +#include "common/log.hxx" + EXAMM::~EXAMM() { delete weight_rules; @@ -48,16 +52,24 @@ EXAMM::~EXAMM() { } EXAMM::EXAMM( - int32_t _island_size, int32_t _number_islands, int32_t _max_genomes, SpeciationStrategy* _speciation_strategy, - WeightRules* _weight_rules, GenomeProperty* _genome_property, string _output_directory -) - : island_size(_island_size), - number_islands(_number_islands), - max_genomes(_max_genomes), - speciation_strategy(_speciation_strategy), - weight_rules(_weight_rules), - genome_property(_genome_property), - output_directory(_output_directory) { + int32_t _island_size, + int32_t _number_islands, + int32_t _max_genomes, + //SHO SY + double _learning_rate, + SpeciationStrategy *_speciation_strategy, + WeightRules *_weight_rules, + GenomeProperty *_genome_property, + string _output_directory) : + island_size(_island_size), + number_islands(_number_islands), + max_genomes(_max_genomes), + learning_rate(_learning_rate), + speciation_strategy(_speciation_strategy), + weight_rules(_weight_rules), + genome_property(_genome_property), + output_directory(_output_directory) { + total_bp_epochs = 0; edge_innovation_count = 0; node_innovation_count = 0; @@ -71,9 +83,10 @@ EXAMM::EXAMM( check_weight_initialize_validity(); set_evolution_hyper_parameters(); initialize_seed_genome(); - // make sure we don't duplicate node or edge innovation numbers + //make sure we don't duplicate node or edge innovation numbers - function mutate_function = [=](int32_t max_mutations, RNN_Genome* genome) { + function mutate_function = + [=](int32_t max_mutations, RNN_Genome *genome) { this->mutate(max_mutations, genome); }; @@ -82,6 +95,18 @@ EXAMM::EXAMM( speciation_strategy->initialize_population(mutate_function); generate_log(); startClock = std::chrono::system_clock::now(); + + //SHO SY + initial_learning_rate_min = 0.001; + initial_learning_rate_max = 0.10; + learning_rate_min = 0.00001; + learning_rate_max = 0.3; + //learning_rate = 0.001; + rng_lr = uniform_real_distribution(0.0001, 0.03); + rng_ilr = uniform_real_distribution(0.001, 0.05); + //learning_rate = rng_lr(generator); + //initial_learning_rate = rng_ilr(generator); + genomes = vector< vector >(number_islands); } void EXAMM::print() { @@ -95,28 +120,39 @@ void EXAMM::generate_log() { Log::info("Generating fitness log\n"); mkpath(output_directory.c_str(), 0777); log_file = new ofstream(output_directory + "/" + "fitness_log.csv"); - (*log_file) << "Inserted Genomes, Total BP Epochs, Time, Best Val. MAE, Best Val. MSE, Enabled Nodes, Enabled " - "Edges, Enabled Rec. Edges"; + (*log_file) << "Inserted Genomes, Total BP Epochs, Time, Best Val. MAE, Best Val. MSE, Enabled Nodes, Enabled Edges, Enabled Rec. Edges"; (*log_file) << speciation_strategy->get_strategy_information_headers(); (*log_file) << endl; if (generate_op_log) { op_log_file = new ofstream(output_directory + "/op_log.csv"); op_log_ordering = { - "genomes", "crossover", "island_crossover", "clone", "add_edge", "add_recurrent_edge", - "enable_edge", "disable_edge", "enable_node", "disable_node", + "genomes", + "crossover", + "island_crossover", + "clone", + "add_edge", + "add_recurrent_edge", + "enable_edge", + "disable_edge", + "enable_node", + "disable_node", }; // To get data about these ops without respect to node type, // you'll have to calculate the sum, e.g. sum split_node(x) for all node types x // to get information about split_node as a whole. - vector ops_with_node_type = {"add_node", "split_node", "merge_node", "split_edge"}; - for (int32_t i = 0; i < (int32_t) ops_with_node_type.size(); i++) { + vector ops_with_node_type = { + "add_node", + "split_node", + "merge_node", + "split_edge" + }; + for (int32_t i = 0; i < (int32_t)ops_with_node_type.size(); i++) { string op = ops_with_node_type[i]; - for (int32_t j = 0; j < (int32_t) possible_node_types.size(); j++) { + for (int32_t j = 0; j < (int32_t)possible_node_types.size(); j++) op_log_ordering.push_back(op + "(" + NODE_TYPES[possible_node_types[j]] + ")"); - } } - for (int32_t i = 0; i < (int32_t) op_log_ordering.size(); i++) { + for (int32_t i = 0; i < (int32_t)op_log_ordering.size(); i++) { string op = op_log_ordering[i]; (*op_log_file) << op; (*op_log_file) << " Generated, "; @@ -133,9 +169,9 @@ void EXAMM::generate_log() { } } -void EXAMM::update_op_log_statistics(RNN_Genome* genome, int32_t insert_position) { +void EXAMM::update_op_log_statistics(RNN_Genome *genome, int32_t insert_position) { // Name of the operator - const map* generated_by_map = genome->get_generated_by_map(); + const map *generated_by_map = genome->get_generated_by_map(); for (auto it = generated_by_map->begin(); it != generated_by_map->end(); it++) { string generated_by = it->first; if (generated_counts.count(generated_by) > 0) { @@ -147,13 +183,13 @@ void EXAMM::update_op_log_statistics(RNN_Genome* genome, int32_t insert_position inserted_counts["genomes"] += 1; inserted_counts[generated_by] += 1; } - } + } } } void EXAMM::update_log() { if (log_file != NULL) { - // make sure the log file is still good + //make sure the log file is still good if (!log_file->good()) { log_file->close(); delete log_file; @@ -176,23 +212,28 @@ void EXAMM::update_log() { exit(1); } } - for (int32_t i = 0; i < (int32_t) op_log_ordering.size(); i++) { + for (int32_t i = 0; i < (int32_t)op_log_ordering.size(); i++) { string op = op_log_ordering[i]; - (*op_log_file) << generated_counts[op] << ", " << inserted_counts[op] << ", "; + (*op_log_file) << generated_counts[op] << ", " << inserted_counts[op] << ", "; } (*op_log_file) << endl; } - RNN_Genome* best_genome = get_best_genome(); + RNN_Genome *best_genome = get_best_genome(); if (best_genome == NULL) { best_genome = speciation_strategy->get_global_best_genome(); } std::chrono::time_point currentClock = std::chrono::system_clock::now(); long milliseconds = std::chrono::duration_cast(currentClock - startClock).count(); - (*log_file) << speciation_strategy->get_evaluated_genomes() << "," << total_bp_epochs << "," << milliseconds - << "," << best_genome->best_validation_mae << "," << best_genome->best_validation_mse << "," - << best_genome->get_enabled_node_count() << "," << best_genome->get_enabled_edge_count() << "," - << best_genome->get_enabled_recurrent_edge_count() - << speciation_strategy->get_strategy_information_values() << endl; + (*log_file) << speciation_strategy->get_evaluated_genomes() + << "," << total_bp_epochs + << "," << milliseconds + << "," << best_genome->best_validation_mae + << "," << best_genome->best_validation_mse + << "," << best_genome->get_enabled_node_count() + << "," << best_genome->get_enabled_edge_count() + << "," << best_genome->get_enabled_recurrent_edge_count() + << speciation_strategy->get_strategy_information_values() + << endl; } } @@ -205,7 +246,7 @@ void EXAMM::update_log() { void EXAMM::set_possible_node_types(vector possible_node_type_strings) { possible_node_types.clear(); - for (int32_t i = 0; i < (int32_t) possible_node_type_strings.size(); i++) { + for (int32_t i = 0; i < (int32_t)possible_node_type_strings.size(); i++) { string node_type_s = possible_node_type_strings[i]; bool found = false; @@ -244,7 +285,7 @@ RNN_Genome* EXAMM::get_worst_genome() { return speciation_strategy->get_worst_genome(); } -// this will insert a COPY, original needs to be deleted +//this will insert a COPY, original needs to be deleted bool EXAMM::insert_genome(RNN_Genome* genome) { total_bp_epochs += genome->get_bp_iterations(); if (!genome->sanity_check()) { @@ -252,10 +293,10 @@ bool EXAMM::insert_genome(RNN_Genome* genome) { exit(1); } - // updates EXAMM's mapping of which genomes have been generated by what + //updates EXAMM's mapping of which genomes have been generated by what genome->update_generation_map(generated_from_map); int32_t insert_position = speciation_strategy->insert_genome(genome); - // write this genome to disk if it was a new best found genome + //write this genome to disk if it was a new best found genome if (insert_position == 0) { // genome->normalize_type = normalize_type; genome->write_graphviz(output_directory + "/rnn_genome_" + to_string(genome->get_generation_id()) + ".gv"); @@ -267,26 +308,144 @@ bool EXAMM::insert_genome(RNN_Genome* genome) { return insert_position >= 0; } -RNN_Genome* EXAMM::generate_genome() { - if (speciation_strategy->get_evaluated_genomes() > max_genomes) { - return NULL; +//SHO SY +void EXAMM::generate_initial_hyperparameters(double &learning_rate) +{ + learning_rate = (rng_0_1(generator) * (initial_learning_rate_max - initial_learning_rate_min)) + initial_learning_rate_min; +} + +void EXAMM::generate_simplex_hyperparameters(double &learning_rate) +{ + double best_learning_rate; + double avg_learning_rate; + + // minstd_rand0 generator; + // uniform_real_distribution rng_0_1; + + // uint16_t seed = std::chrono::system_clock::now().time_since_epoch().count(); + // generator = minstd_rand0(seed); + // rng_0_1 = uniform_real_distribution(0.0, 1.0); + + avg_learning_rate = 0; + + + double best_fitness = EXAMM_MAX_DOUBLE; + //TODO maybe change simplex count + int simplex_count = 5; + + + for(uint32_t i=0; iget_islands_size()); + int32_t x_rnd = rng_0_1(generator) * speciation_strategy->get_islands_size(); + Log::error("\n SY: x_rnd = %d",x_rnd); + Log::error("\n SY: Island size 2: %d",speciation_strategy->get_island_at_index(x_rnd)->size()); + + if(speciation_strategy->get_island_at_index(x_rnd)->size() > 0) { + int32_t y_rnd = rng_0_1(generator) * speciation_strategy->get_island_at_index(x_rnd)->size(); + Log::error("\n SY: y_rnd = %d", y_rnd); + Log::error("\n SY: During current genome"); + + + RNN_Genome *current_genome = speciation_strategy->get_island_at_index(x_rnd)->get_genome_at(y_rnd); + Log::error("\n SY: After current genome"); + Log::error("\n Best Fitness Before: %lf",best_fitness); + + if( i == 0 || current_genome->get_best_validation_mse() < best_fitness) + { + + best_fitness = current_genome->get_best_validation_mse(); + Log::error("\n Best Fitness after: %lf",best_fitness); + Log::error("\n SY: Inside if statement after rnn genome"); + //best_learning_rate = current_genome->get_initial_learning_rate(); + best_learning_rate = current_genome->get_initial_learning_rate(); + + Log::error("\n SY: Best learning rate: %lf",best_learning_rate); + // best_learning_rate_delta = current_genome->get_best_learning_rate_delta(); + // best_dropout_probability = current_genome->get_best_dropout_probability(); + } + Log::error("\n SY: Before Average learning rate"); + //avg_learning_rate += current_genome->get_initial_learning_rate(); + avg_learning_rate += current_genome->get_initial_learning_rate(); + Log::error("\n SY: Avg Learning Rate: %lf",avg_learning_rate); + // avg_learning_rate_delta += current_genome->get_initial_learning_rate_delta(); + // avg_dropout_probability += current_genome->get_initial_dropout_probability(); + Log::error("\n SY: After Average learning rate"); + + } + } + Log::error("\n SY: avg before division: %lf",avg_learning_rate); + avg_learning_rate = avg_learning_rate / simplex_count; + Log::error("\n SY: avg after division: %lf",avg_learning_rate); + // avg_learning_rate_delta /= simplex_count; + // avg_dropout_probability /= simplex_count; + + double scale = (rng_0_1(generator) * 2.0) - 0.5; + Log::error("\n SY: avg_learning_rate after adding avg and mul: %lf",avg_learning_rate); + Log::error("\n SY: best_learning_rate after adding avg and mul: %lf",best_learning_rate); + Log::error("\n SY: scale after adding avg and mul: %lf",scale); + learning_rate = avg_learning_rate + ((best_learning_rate - avg_learning_rate) * scale); + + Log::error("\n SY: learning rate after adding avg and mul: %lf",learning_rate); + + // learning_rate_delta = avg_learning_rate_delta + ((best_learning_rate_delta - avg_learning_rate_delta) * scale); + // dropout_probability = avg_dropout_probability + ((best_dropout_probability - avg_dropout_probability) * scale); + + if (learning_rate < learning_rate_min) learning_rate = learning_rate_min; + if (learning_rate > learning_rate_max) learning_rate = learning_rate_max; + Log::error("\n SY: learning rate finally : %lf",learning_rate); + // if (learning_rate_delta < learning_rate_delta_min) learning_rate_delta = learning_rate_delta_min; + // if (learning_rate_delta > learning_rate_delta_max) learning_rate_delta = learning_rate_delta_max; + // if (dropout_probability < dropout_probability_min) dropout_probability = dropout_probability_min; + // if (dropout_probability > dropout_probability_max) dropout_probability = dropout_probability_max; - function mutate_function = [=](int32_t max_mutations, RNN_Genome* genome) { - this->mutate(max_mutations, genome); - }; +} - function crossover_function = [=](RNN_Genome* parent1, RNN_Genome* parent2) { - return this->crossover(parent1, parent2); - }; +RNN_Genome* EXAMM::generate_genome() { + if (speciation_strategy->get_evaluated_genomes() > max_genomes) return NULL; - RNN_Genome* genome = speciation_strategy->generate_genome(rng_0_1, generator, mutate_function, crossover_function); + function mutate_function = + [=](int32_t max_mutations, RNN_Genome *genome) { + this->mutate(max_mutations, genome); + }; + + function crossover_function = + [=](RNN_Genome *parent1, RNN_Genome *parent2) { + return this->crossover(parent1, parent2); + }; + + RNN_Genome *genome = speciation_strategy->generate_genome(rng_0_1, generator, mutate_function, crossover_function); + + //SHO SY + if(speciation_strategy->islands_full() != true) { + Log::error("SY: Island Not Full"); + genome->set_learning_rate(learning_rate); + Log::error("SY:Island not full learning_rate %lf",genome->get_learning_rate()); + } + else { + // Log::error("\n SY: initialising hyperparameters"); + generate_initial_hyperparameters(learning_rate); + // Log::error("\n SY: simplex hyperparameters"); + generate_simplex_hyperparameters(learning_rate); + // Log::error("\n SY: learning rate before updating genome: %lf",learning_rate); + //genome->learning_rate = learning_rate; + genome->set_learning_rate(learning_rate); + Log::error("\n SY: learning rate after updating genome if island full: %lf",genome->get_learning_rate()); + } + + Log::error("SY: Island is Full"); + Log::error("SY:Island is full learning_rate %lf",genome->get_learning_rate()); genome_property->set_genome_properties(genome); + genome -> set_learning_rate(learning_rate); // if (!epigenetic_weights) genome->initialize_randomly(); - // this is just a sanity check, can most likely comment out (checking to see - // if all the paramemters are sane) + //this is just a sanity check, can most likely comment out (checking to see + //if all the paramemters are sane) Log::debug("getting mu/sigma after random initialization of copy!\n"); double _mu, _sigma; genome->get_mu_sigma(genome->best_parameters, _mu, _sigma); @@ -298,21 +457,20 @@ int32_t EXAMM::get_random_node_type() { return possible_node_types[rng_0_1(generator) * possible_node_types.size()]; } -void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { - double total = clone_rate + add_edge_rate + add_recurrent_edge_rate + enable_edge_rate + disable_edge_rate - + split_edge_rate + add_node_rate + enable_node_rate + disable_node_rate + split_node_rate - + merge_node_rate; + +void EXAMM::mutate(int32_t max_mutations, RNN_Genome *g) { + double total = clone_rate + add_edge_rate + add_recurrent_edge_rate + enable_edge_rate + disable_edge_rate + split_edge_rate + add_node_rate + enable_node_rate + disable_node_rate + split_node_rate + merge_node_rate; bool modified = false; double mu, sigma; - // g->write_graphviz("rnn_genome_premutate_" + to_string(g->get_generation_id()) + ".gv"); + //g->write_graphviz("rnn_genome_premutate_" + to_string(g->get_generation_id()) + ".gv"); g->get_mu_sigma(g->best_parameters, mu, sigma); g->clear_generated_by(); - // the the weights in the genome to it's best parameters - // for epigenetic iniitalization + //the the weights in the genome to it's best parameters + //for epigenetic iniitalization if (g->best_parameters.size() == 0) { g->set_weights(g->initial_parameters); g->get_mu_sigma(g->initial_parameters, mu, sigma); @@ -328,15 +486,13 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { modified = false; number_mutations++; } - if (number_mutations >= max_mutations) { - break; - } + if (number_mutations >= max_mutations) break; g->assign_reachability(); double rng = rng_0_1(generator) * total; int32_t new_node_type = get_random_node_type(); string node_type_str = NODE_TYPES[new_node_type]; - Log::debug("rng: %lf, total: %lf, new node type: %d (%s)\n", rng, total, new_node_type, node_type_str.c_str()); + Log::debug( "rng: %lf, total: %lf, new node type: %d (%s)\n", rng, total, new_node_type, node_type_str.c_str()); if (rng < clone_rate) { Log::debug("\tcloned\n"); @@ -348,9 +504,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { if (rng < add_edge_rate) { modified = g->add_edge(mu, sigma, edge_innovation_count); Log::debug("\tadding edge, modified: %d\n", modified); - if (modified) { - g->set_generated_by("add_edge"); - } + if (modified) g->set_generated_by("add_edge"); continue; } rng -= add_edge_rate; @@ -359,9 +513,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { uniform_int_distribution dist = genome_property->get_recurrent_depth_dist(); modified = g->add_recurrent_edge(mu, sigma, dist, edge_innovation_count); Log::debug("\tadding recurrent edge, modified: %d\n", modified); - if (modified) { - g->set_generated_by("add_recurrent_edge"); - } + if (modified) g->set_generated_by("add_recurrent_edge"); continue; } rng -= add_recurrent_edge_rate; @@ -369,9 +521,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { if (rng < enable_edge_rate) { modified = g->enable_edge(); Log::debug("\tenabling edge, modified: %d\n", modified); - if (modified) { - g->set_generated_by("enable_edge"); - } + if (modified) g->set_generated_by("enable_edge"); continue; } rng -= enable_edge_rate; @@ -379,9 +529,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { if (rng < disable_edge_rate) { modified = g->disable_edge(); Log::debug("\tdisabling edge, modified: %d\n", modified); - if (modified) { - g->set_generated_by("disable_edge"); - } + if (modified) g->set_generated_by("disable_edge"); continue; } rng -= disable_edge_rate; @@ -390,9 +538,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { uniform_int_distribution dist = genome_property->get_recurrent_depth_dist(); modified = g->split_edge(mu, sigma, new_node_type, dist, edge_innovation_count, node_innovation_count); Log::debug("\tsplitting edge, modified: %d\n", modified); - if (modified) { - g->set_generated_by("split_edge(" + node_type_str + ")"); - } + if (modified) g->set_generated_by("split_edge(" + node_type_str + ")"); continue; } rng -= split_edge_rate; @@ -401,9 +547,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { uniform_int_distribution dist = genome_property->get_recurrent_depth_dist(); modified = g->add_node(mu, sigma, new_node_type, dist, edge_innovation_count, node_innovation_count); Log::debug("\tadding node, modified: %d\n", modified); - if (modified) { - g->set_generated_by("add_node(" + node_type_str + ")"); - } + if (modified) g->set_generated_by("add_node(" + node_type_str + ")"); continue; } rng -= add_node_rate; @@ -411,9 +555,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { if (rng < enable_node_rate) { modified = g->enable_node(); Log::debug("\tenabling node, modified: %d\n", modified); - if (modified) { - g->set_generated_by("enable_node"); - } + if (modified) g->set_generated_by("enable_node"); continue; } rng -= enable_node_rate; @@ -421,9 +563,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { if (rng < disable_node_rate) { modified = g->disable_node(); Log::debug("\tdisabling node, modified: %d\n", modified); - if (modified) { - g->set_generated_by("disable_node"); - } + if (modified) g->set_generated_by("disable_node"); continue; } rng -= disable_node_rate; @@ -432,9 +572,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { uniform_int_distribution dist = genome_property->get_recurrent_depth_dist(); modified = g->split_node(mu, sigma, new_node_type, dist, edge_innovation_count, node_innovation_count); Log::debug("\tsplitting node, modified: %d\n", modified); - if (modified) { - g->set_generated_by("split_node(" + node_type_str + ")"); - } + if (modified) g->set_generated_by("split_node(" + node_type_str + ")"); continue; } rng -= split_node_rate; @@ -443,17 +581,15 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { uniform_int_distribution dist = genome_property->get_recurrent_depth_dist(); modified = g->merge_node(mu, sigma, new_node_type, dist, edge_innovation_count, node_innovation_count); Log::debug("\tmerging node, modified: %d\n", modified); - if (modified) { - g->set_generated_by("merge_node(" + node_type_str + ")"); - } + if (modified) g->set_generated_by("merge_node(" + node_type_str + ")"); continue; } rng -= merge_node_rate; } - // get the new set of parameters (as new paramters may have been - // added duriung mutation) and set them to the initial parameters - // for epigenetic_initialization + //get the new set of parameters (as new paramters may have been + //added duriung mutation) and set them to the initial parameters + //for epigenetic_initialization vector new_parameters; @@ -466,7 +602,7 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { g->assign_reachability(); - // reset the genomes statistics (as these carry over on copy) + //reset the genomes statistics (as these carry over on copy) g->best_validation_mse = EXAMM_MAX_DOUBLE; g->best_validation_mae = EXAMM_MAX_DOUBLE; @@ -478,37 +614,25 @@ void EXAMM::mutate(int32_t max_mutations, RNN_Genome* g) { g->best_parameters.clear(); } -void EXAMM::attempt_node_insert( - vector& child_nodes, const RNN_Node_Interface* node, const vector& new_weights -) { - for (int32_t i = 0; i < (int32_t) child_nodes.size(); i++) { - if (child_nodes[i]->get_innovation_number() == node->get_innovation_number()) { - return; - } + +void EXAMM::attempt_node_insert(vector &child_nodes, const RNN_Node_Interface *node, const vector &new_weights) { + for (int32_t i = 0; i < (int32_t)child_nodes.size(); i++) { + if (child_nodes[i]->get_innovation_number() == node->get_innovation_number()) return; } - RNN_Node_Interface* node_copy = node->copy(); + RNN_Node_Interface *node_copy = node->copy(); node_copy->set_weights(new_weights); - child_nodes.insert( - upper_bound(child_nodes.begin(), child_nodes.end(), node_copy, sort_RNN_Nodes_by_depth()), node_copy - ); + child_nodes.insert( upper_bound(child_nodes.begin(), child_nodes.end(), node_copy, sort_RNN_Nodes_by_depth()), node_copy); } -void EXAMM::attempt_edge_insert( - vector& child_edges, vector& child_nodes, RNN_Edge* edge, RNN_Edge* second_edge, - bool set_enabled -) { - for (int32_t i = 0; i < (int32_t) child_edges.size(); i++) { +void EXAMM::attempt_edge_insert(vector &child_edges, vector &child_nodes, RNN_Edge *edge, RNN_Edge *second_edge, bool set_enabled) { + for (int32_t i = 0; i < (int32_t)child_edges.size(); i++) { if (child_edges[i]->get_innovation_number() == edge->get_innovation_number()) { - Log::fatal( - "ERROR in crossover! trying to push an edge with innovation_number: %d and it already exists in the " - "vector!\n", - edge->get_innovation_number() - ); + Log::fatal("ERROR in crossover! trying to push an edge with innovation_number: %d and it already exists in the vector!\n", edge->get_innovation_number()); Log::fatal("vector innovation numbers: "); - for (int32_t i = 0; i < (int32_t) child_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)child_edges.size(); i++) { Log::fatal("\t%d", child_edges[i]->get_innovation_number()); } @@ -517,11 +641,9 @@ void EXAMM::attempt_edge_insert( return; } else if (child_edges[i]->get_input_innovation_number() == edge->get_input_innovation_number() && - child_edges[i]->get_output_innovation_number() == edge->get_output_innovation_number()) { - Log::debug( - "Not inserting edge in crossover operation as there was already an edge with the same input and output " - "innovation numbers!\n" - ); + child_edges[i]->get_output_innovation_number() == edge->get_output_innovation_number()) { + + Log::debug("Not inserting edge in crossover operation as there was already an edge with the same input and output innovation numbers!\n"); return; } } @@ -532,10 +654,7 @@ void EXAMM::attempt_edge_insert( double crossover_value = rng_crossover_weight(generator); new_weight = crossover_value * -(second_edge->weight - edge->weight) + edge->weight; - Log::trace( - "EDGE WEIGHT CROSSOVER :: better: %lf, worse: %lf, crossover_value: %lf, new_weight: %lf\n", edge->weight, - second_edge->weight, crossover_value, new_weight - ); + Log::trace("EDGE WEIGHT CROSSOVER :: better: %lf, worse: %lf, crossover_value: %lf, new_weight: %lf\n", edge->weight, second_edge->weight, crossover_value, new_weight); vector input_weights1, input_weights2, output_weights1, output_weights2; edge->get_input_node()->get_weights(input_weights1); @@ -547,15 +666,15 @@ void EXAMM::attempt_edge_insert( new_input_weights.resize(input_weights1.size()); new_output_weights.resize(output_weights1.size()); - // can check to see if input weights lengths are same - // can check to see if output weights lengths are same + //can check to see if input weights lengths are same + //can check to see if output weights lengths are same - for (int32_t i = 0; i < (int32_t) new_input_weights.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_input_weights.size(); i++) { new_input_weights[i] = crossover_value * -(input_weights2[i] - input_weights1[i]) + input_weights1[i]; Log::trace("\tnew input weights[%d]: %lf\n", i, new_input_weights[i]); } - for (int32_t i = 0; i < (int32_t) new_output_weights.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_output_weights.size(); i++) { new_output_weights[i] = crossover_value * -(output_weights2[i] - output_weights1[i]) + output_weights1[i]; Log::trace("\tnew output weights[%d]: %lf\n", i, new_output_weights[i]); } @@ -569,30 +688,21 @@ void EXAMM::attempt_edge_insert( attempt_node_insert(child_nodes, edge->get_input_node(), new_input_weights); attempt_node_insert(child_nodes, edge->get_output_node(), new_output_weights); - RNN_Edge* edge_copy = edge->copy(child_nodes); + RNN_Edge *edge_copy = edge->copy(child_nodes); edge_copy->enabled = set_enabled; edge_copy->weight = new_weight; - // edges have already been copied - child_edges.insert( - upper_bound(child_edges.begin(), child_edges.end(), edge_copy, sort_RNN_Edges_by_depth()), edge_copy - ); + //edges have already been copied + child_edges.insert( upper_bound(child_edges.begin(), child_edges.end(), edge_copy, sort_RNN_Edges_by_depth()), edge_copy); } -void EXAMM::attempt_recurrent_edge_insert( - vector& child_recurrent_edges, vector& child_nodes, - RNN_Recurrent_Edge* recurrent_edge, RNN_Recurrent_Edge* second_edge, bool set_enabled -) { - for (int32_t i = 0; i < (int32_t) child_recurrent_edges.size(); i++) { +void EXAMM::attempt_recurrent_edge_insert(vector &child_recurrent_edges, vector &child_nodes, RNN_Recurrent_Edge *recurrent_edge, RNN_Recurrent_Edge *second_edge, bool set_enabled) { + for (int32_t i = 0; i < (int32_t)child_recurrent_edges.size(); i++) { if (child_recurrent_edges[i]->get_innovation_number() == recurrent_edge->get_innovation_number()) { - Log::fatal( - "ERROR in crossover! trying to push an recurrent_edge with innovation_number: %d and it already " - "exists in the vector!\n", - recurrent_edge->get_innovation_number() - ); + Log::fatal("ERROR in crossover! trying to push an recurrent_edge with innovation_number: %d and it already exists in the vector!\n", recurrent_edge->get_innovation_number()); Log::fatal("vector innovation numbers:\n"); - for (int32_t i = 0; i < (int32_t) child_recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)child_recurrent_edges.size(); i++) { Log::fatal("\t %d", child_recurrent_edges[i]->get_innovation_number()); } @@ -600,28 +710,22 @@ void EXAMM::attempt_recurrent_edge_insert( exit(1); return; - } else if (child_recurrent_edges[i]->get_input_innovation_number() == - recurrent_edge->get_input_innovation_number() && - child_recurrent_edges[i]->get_output_innovation_number() == - recurrent_edge->get_output_innovation_number()) { - Log::debug( - "Not inserting recurrent_edge in crossover operation as there was already an recurrent_edge with the " - "same input and output innovation numbers!\n" - ); + } else if (child_recurrent_edges[i]->get_input_innovation_number() == recurrent_edge->get_input_innovation_number() && + child_recurrent_edges[i]->get_output_innovation_number() == recurrent_edge->get_output_innovation_number()) { + + Log::debug("Not inserting recurrent_edge in crossover operation as there was already an recurrent_edge with the same input and output innovation numbers!\n"); return; } } + vector new_input_weights, new_output_weights; double new_weight = 0.0; if (second_edge != NULL) { double crossover_value = rng_crossover_weight(generator); new_weight = crossover_value * -(second_edge->weight - recurrent_edge->weight) + recurrent_edge->weight; - Log::debug( - "RECURRENT EDGE WEIGHT CROSSOVER :: better: %lf, worse: %lf, crossover_value: %lf, new_weight: %lf\n", - recurrent_edge->weight, second_edge->weight, crossover_value, new_weight - ); + Log::debug("RECURRENT EDGE WEIGHT CROSSOVER :: better: %lf, worse: %lf, crossover_value: %lf, new_weight: %lf\n", recurrent_edge->weight, second_edge->weight, crossover_value, new_weight); vector input_weights1, input_weights2, output_weights1, output_weights2; recurrent_edge->get_input_node()->get_weights(input_weights1); @@ -633,12 +737,12 @@ void EXAMM::attempt_recurrent_edge_insert( new_input_weights.resize(input_weights1.size()); new_output_weights.resize(output_weights1.size()); - for (int32_t i = 0; i < (int32_t) new_input_weights.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_input_weights.size(); i++) { new_input_weights[i] = crossover_value * -(input_weights2[i] - input_weights1[i]) + input_weights1[i]; Log::trace("\tnew input weights[%d]: %lf\n", i, new_input_weights[i]); } - for (int32_t i = 0; i < (int32_t) new_output_weights.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_output_weights.size(); i++) { new_output_weights[i] = crossover_value * -(output_weights2[i] - output_weights1[i]) + output_weights1[i]; Log::trace("\tnew output weights[%d]: %lf\n", i, new_output_weights[i]); } @@ -652,40 +756,28 @@ void EXAMM::attempt_recurrent_edge_insert( attempt_node_insert(child_nodes, recurrent_edge->get_input_node(), new_input_weights); attempt_node_insert(child_nodes, recurrent_edge->get_output_node(), new_output_weights); - RNN_Recurrent_Edge* recurrent_edge_copy = recurrent_edge->copy(child_nodes); + RNN_Recurrent_Edge *recurrent_edge_copy = recurrent_edge->copy(child_nodes); recurrent_edge_copy->enabled = set_enabled; recurrent_edge_copy->weight = new_weight; - // recurrent_edges have already been copied - child_recurrent_edges.insert( - upper_bound( - child_recurrent_edges.begin(), child_recurrent_edges.end(), recurrent_edge_copy, - sort_RNN_Recurrent_Edges_by_depth() - ), - recurrent_edge_copy - ); + + //recurrent_edges have already been copied + child_recurrent_edges.insert( upper_bound(child_recurrent_edges.begin(), child_recurrent_edges.end(), recurrent_edge_copy, sort_RNN_Recurrent_Edges_by_depth()), recurrent_edge_copy); } -RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { + +RNN_Genome* EXAMM::crossover(RNN_Genome *p1, RNN_Genome *p2) { Log::debug("generating new genome by crossover!\n"); Log::debug("p1->island: %d, p2->island: %d\n", p1->get_group_id(), p2->get_group_id()); Log::debug("p1->number_inputs: %d, p2->number_inputs: %d\n", p1->get_number_inputs(), p2->get_number_inputs()); - for (int32_t i = 0; i < (int32_t) p1->nodes.size(); i++) { - Log::debug( - "p1 node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d, reachable: %d, enabled: %d\n", i, - p1->nodes[i]->get_innovation_number(), p1->nodes[i]->get_depth(), p1->nodes[i]->get_layer_type(), - p1->nodes[i]->get_node_type(), p1->nodes[i]->is_reachable(), p1->nodes[i]->is_enabled() - ); + for (int32_t i = 0; i < (int32_t)p1->nodes.size(); i++) { + Log::debug("p1 node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d, reachable: %d, enabled: %d\n", i, p1->nodes[i]->get_innovation_number(), p1->nodes[i]->get_depth(), p1->nodes[i]->get_layer_type(), p1->nodes[i]->get_node_type(), p1->nodes[i]->is_reachable(), p1->nodes[i]->is_enabled()); } - for (int32_t i = 0; i < (int32_t) p2->nodes.size(); i++) { - Log::debug( - "p2 node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d, reachable: %d, enabled: %d\n", i, - p2->nodes[i]->get_innovation_number(), p2->nodes[i]->get_depth(), p2->nodes[i]->get_layer_type(), - p2->nodes[i]->get_node_type(), p2->nodes[i]->is_reachable(), p2->nodes[i]->is_enabled() - ); + for (int32_t i = 0; i < (int32_t)p2->nodes.size(); i++) { + Log::debug("p2 node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d, reachable: %d, enabled: %d\n", i, p2->nodes[i]->get_innovation_number(), p2->nodes[i]->get_depth(), p2->nodes[i]->get_layer_type(), p2->nodes[i]->get_node_type(), p2->nodes[i]->is_reachable(), p2->nodes[i]->is_enabled()); } double _mu, _sigma; @@ -707,29 +799,29 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { p2->get_mu_sigma(p2->best_parameters, _mu, _sigma); } - // nodes are copied in the attempt_node_insert_function - vector child_nodes; - vector child_edges; - vector child_recurrent_edges; + //nodes are copied in the attempt_node_insert_function + vector< RNN_Node_Interface* > child_nodes; + vector< RNN_Edge* > child_edges; + vector< RNN_Recurrent_Edge* > child_recurrent_edges; - // edges are not sorted in order of innovation number, they need to be - vector p1_edges = p1->edges; - vector p2_edges = p2->edges; + //edges are not sorted in order of innovation number, they need to be + vector< RNN_Edge* > p1_edges = p1->edges; + vector< RNN_Edge* > p2_edges = p2->edges; sort(p1_edges.begin(), p1_edges.end(), sort_RNN_Edges_by_innovation()); sort(p2_edges.begin(), p2_edges.end(), sort_RNN_Edges_by_innovation()); Log::debug("\tp1 innovation numbers AFTER SORT:\n"); - for (int32_t i = 0; i < (int32_t) p1_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)p1_edges.size(); i++) { Log::trace("\t\t%d\n", p1_edges[i]->innovation_number); } Log::debug("\tp2 innovation numbers AFTER SORT:\n"); - for (int32_t i = 0; i < (int32_t) p2_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)p2_edges.size(); i++) { Log::debug("\t\t%d\n", p2_edges[i]->innovation_number); } - vector p1_recurrent_edges = p1->recurrent_edges; - vector p2_recurrent_edges = p2->recurrent_edges; + vector< RNN_Recurrent_Edge* > p1_recurrent_edges = p1->recurrent_edges; + vector< RNN_Recurrent_Edge* > p2_recurrent_edges = p2->recurrent_edges; sort(p1_recurrent_edges.begin(), p1_recurrent_edges.end(), sort_RNN_Recurrent_Edges_by_innovation()); sort(p2_recurrent_edges.begin(), p2_recurrent_edges.end(), sort_RNN_Recurrent_Edges_by_innovation()); @@ -737,7 +829,7 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { int32_t p1_position = 0; int32_t p2_position = 0; - while (p1_position < (int32_t) p1_edges.size() && p2_position < (int32_t) p2_edges.size()) { + while (p1_position < (int32_t)p1_edges.size() && p2_position < (int32_t)p2_edges.size()) { RNN_Edge* p1_edge = p1_edges[p1_position]; RNN_Edge* p2_edge = p2_edges[p2_position]; @@ -751,22 +843,16 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { p2_position++; } else if (p1_innovation < p2_innovation) { bool set_enabled = rng_0_1(generator) < more_fit_crossover_rate; - if (p1_edge->is_reachable()) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p1_edge->is_reachable()) set_enabled = true; + else set_enabled = false; attempt_edge_insert(child_edges, child_nodes, p1_edge, NULL, set_enabled); p1_position++; } else { bool set_enabled = rng_0_1(generator) < less_fit_crossover_rate; - if (p2_edge->is_reachable() && set_enabled) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p2_edge->is_reachable() && set_enabled) set_enabled = true; + else set_enabled = false; attempt_edge_insert(child_edges, child_nodes, p2_edge, NULL, set_enabled); @@ -774,41 +860,35 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { } } - while (p1_position < (int32_t) p1_edges.size()) { + while (p1_position < (int32_t)p1_edges.size()) { RNN_Edge* p1_edge = p1_edges[p1_position]; bool set_enabled = rng_0_1(generator) < more_fit_crossover_rate; - if (p1_edge->is_reachable()) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p1_edge->is_reachable()) set_enabled = true; + else set_enabled = false; attempt_edge_insert(child_edges, child_nodes, p1_edge, NULL, set_enabled); p1_position++; } - while (p2_position < (int32_t) p2_edges.size()) { + while (p2_position < (int32_t)p2_edges.size()) { RNN_Edge* p2_edge = p2_edges[p2_position]; bool set_enabled = rng_0_1(generator) < less_fit_crossover_rate; - if (p2_edge->is_reachable() && set_enabled) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p2_edge->is_reachable() && set_enabled) set_enabled = true; + else set_enabled = false; attempt_edge_insert(child_edges, child_nodes, p2_edge, NULL, set_enabled); p2_position++; } - // do the same for recurrent_edges + //do the same for recurrent_edges p1_position = 0; p2_position = 0; - while (p1_position < (int32_t) p1_recurrent_edges.size() && p2_position < (int32_t) p2_recurrent_edges.size()) { + while (p1_position < (int32_t)p1_recurrent_edges.size() && p2_position < (int32_t)p2_recurrent_edges.size()) { RNN_Recurrent_Edge* p1_recurrent_edge = p1_recurrent_edges[p1_position]; RNN_Recurrent_Edge* p2_recurrent_edge = p2_recurrent_edges[p2_position]; @@ -816,31 +896,23 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { int32_t p2_innovation = p2_recurrent_edge->innovation_number; if (p1_innovation == p2_innovation) { - // do weight crossover - attempt_recurrent_edge_insert( - child_recurrent_edges, child_nodes, p1_recurrent_edge, p2_recurrent_edge, true - ); + //do weight crossover + attempt_recurrent_edge_insert(child_recurrent_edges, child_nodes, p1_recurrent_edge, p2_recurrent_edge, true); p1_position++; p2_position++; } else if (p1_innovation < p2_innovation) { bool set_enabled = rng_0_1(generator) < more_fit_crossover_rate; - if (p1_recurrent_edge->is_reachable()) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p1_recurrent_edge->is_reachable()) set_enabled = true; + else set_enabled = false; attempt_recurrent_edge_insert(child_recurrent_edges, child_nodes, p1_recurrent_edge, NULL, set_enabled); p1_position++; } else { bool set_enabled = rng_0_1(generator) < less_fit_crossover_rate; - if (p2_recurrent_edge->is_reachable() && set_enabled) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p2_recurrent_edge->is_reachable() && set_enabled) set_enabled = true; + else set_enabled = false; attempt_recurrent_edge_insert(child_recurrent_edges, child_nodes, p2_recurrent_edge, NULL, set_enabled); @@ -848,30 +920,24 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { } } - while (p1_position < (int32_t) p1_recurrent_edges.size()) { + while (p1_position < (int32_t)p1_recurrent_edges.size()) { RNN_Recurrent_Edge* p1_recurrent_edge = p1_recurrent_edges[p1_position]; bool set_enabled = rng_0_1(generator) < more_fit_crossover_rate; - if (p1_recurrent_edge->is_reachable()) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p1_recurrent_edge->is_reachable()) set_enabled = true; + else set_enabled = false; attempt_recurrent_edge_insert(child_recurrent_edges, child_nodes, p1_recurrent_edge, NULL, set_enabled); p1_position++; } - while (p2_position < (int32_t) p2_recurrent_edges.size()) { + while (p2_position < (int32_t)p2_recurrent_edges.size()) { RNN_Recurrent_Edge* p2_recurrent_edge = p2_recurrent_edges[p2_position]; bool set_enabled = rng_0_1(generator) < less_fit_crossover_rate; - if (p2_recurrent_edge->is_reachable() && set_enabled) { - set_enabled = true; - } else { - set_enabled = false; - } + if (p2_recurrent_edge->is_reachable() && set_enabled) set_enabled = true; + else set_enabled = false; attempt_recurrent_edge_insert(child_recurrent_edges, child_nodes, p2_recurrent_edge, NULL, set_enabled); @@ -882,11 +948,12 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { sort(child_edges.begin(), child_edges.end(), sort_RNN_Edges_by_depth()); sort(child_recurrent_edges.begin(), child_recurrent_edges.end(), sort_RNN_Recurrent_Edges_by_depth()); - RNN_Genome* child = new RNN_Genome(child_nodes, child_edges, child_recurrent_edges, weight_rules); + RNN_Genome *child = new RNN_Genome(child_nodes, child_edges, child_recurrent_edges, weight_rules); genome_property->set_genome_properties(child); // child->set_parameter_names(input_parameter_names, output_parameter_names); // child->set_normalize_bounds(normalize_type, normalize_mins, normalize_maxs, normalize_avgs, normalize_std_devs); + if (p1->get_group_id() == p2->get_group_id()) { child->set_generated_by("crossover"); } else { @@ -897,15 +964,11 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { vector new_parameters; - // if weight_inheritance is same, all the weights of the child genome would be initialized as weight_initialize - // method + // if weight_inheritance is same, all the weights of the child genome would be initialized as weight_initialize method WeightType weight_initialize = weight_rules->get_weight_initialize_method(); WeightType weight_inheritance = weight_rules->get_weight_inheritance_method(); if (weight_inheritance == weight_initialize) { - Log::debug( - "weight inheritance at crossover method is %s, setting weights to %s randomly \n", - WEIGHT_TYPES_STRING[weight_inheritance].c_str(), WEIGHT_TYPES_STRING[weight_inheritance].c_str() - ); + Log::debug("weight inheritance at crossover method is %s, setting weights to %s randomly \n", WEIGHT_TYPES_STRING[weight_inheritance].c_str(), WEIGHT_TYPES_STRING[weight_inheritance].c_str()); child->initialize_randomly(); } @@ -915,13 +978,13 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { child->assign_reachability(); - // reset the genomes statistics (as these carry over on copy) + //reset the genomes statistics (as these carry over on copy) child->best_validation_mse = EXAMM_MAX_DOUBLE; child->best_validation_mae = EXAMM_MAX_DOUBLE; - // get the new set of parameters (as new paramters may have been - // added duriung mutatino) and set them to the initial parameters - // for epigenetic_initialization + //get the new set of parameters (as new paramters may have been + //added duriung mutatino) and set them to the initial parameters + //for epigenetic_initialization child->get_weights(new_parameters); child->initial_parameters = new_parameters; @@ -933,6 +996,7 @@ RNN_Genome* EXAMM::crossover(RNN_Genome* p1, RNN_Genome* p2) { return child; } + // uniform_int_distribution EXAMM::get_recurrent_depth_dist() { // return uniform_int_distribution(this->min_recurrent_depth, this->max_recurrent_depth); // } @@ -959,26 +1023,21 @@ void EXAMM::check_weight_initialize_validity() { exit(1); } if (weight_inheritance != weight_initialize && weight_inheritance != WeightType::LAMARCKIAN) { - Log::fatal( - "Weight initialize is %s, weight inheritance is %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), - WEIGHT_TYPES_STRING[weight_inheritance].c_str() - ); + Log::fatal("Weight initialize is %s, weight inheritance is %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[weight_inheritance].c_str()); exit(1); } if (mutated_component_weight != weight_initialize && mutated_component_weight != WeightType::LAMARCKIAN) { - Log::fatal( - "Weight initialize is %s, new component weight is %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), - WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::fatal("Weight initialize is %s, new component weight is %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); exit(1); } + } void EXAMM::initialize_seed_genome() { - RNN_Genome* seed_genome = speciation_strategy->get_seed_genome(); + RNN_Genome *seed_genome = speciation_strategy->get_seed_genome(); edge_innovation_count = seed_genome->get_max_edge_innovation_count() + 1; node_innovation_count = seed_genome->get_max_node_innovation_count() + 1; - + seed_genome->set_generated_by("initial"); seed_genome->best_validation_mse = EXAMM_MAX_DOUBLE; seed_genome->best_validation_mse = EXAMM_MAX_DOUBLE; @@ -1001,7 +1060,7 @@ void EXAMM::set_evolution_hyper_parameters() { if (node_ops) { add_node_rate = 1.0; enable_node_rate = 1.0; - // disable_node_rate = 3.0; + //disable_node_rate = 3.0; disable_node_rate = 1.0; split_node_rate = 1.0; merge_node_rate = 1.0; diff --git a/examm/examm.hxx b/examm/examm.hxx index 5ccb545e..0fcc1615 100644 --- a/examm/examm.hxx +++ b/examm/examm.hxx @@ -17,113 +17,127 @@ using std::to_string; #include using std::vector; -#include "rnn/genome_property.hxx" #include "rnn/rnn_genome.hxx" #include "speciation_strategy.hxx" -#include "time_series/time_series.hxx" #include "weights/weight_rules.hxx" +#include "time_series/time_series.hxx" +#include "rnn/genome_property.hxx" class EXAMM { - private: - int32_t island_size; - int32_t number_islands; + private: + int32_t island_size; + int32_t number_islands; + + int32_t max_genomes; + int32_t total_bp_epochs; + SpeciationStrategy *speciation_strategy; + WeightRules *weight_rules; + GenomeProperty *genome_property; + + + int32_t edge_innovation_count; + int32_t node_innovation_count; + + map inserted_from_map; + map generated_from_map; + + //SHO SY + double learning_rate; + double initial_learning_rate; + double initial_learning_rate_min; + double initial_learning_rate_max; + double learning_rate_min; + double learning_rate_max; + vector< vector > genomes; + uniform_real_distribution rng_lr; + uniform_real_distribution rng_ilr; - int32_t max_genomes; - int32_t total_bp_epochs; - SpeciationStrategy* speciation_strategy; - WeightRules* weight_rules; - GenomeProperty* genome_property; + bool generate_op_log; - int32_t edge_innovation_count; - int32_t node_innovation_count; + minstd_rand0 generator; + uniform_real_distribution rng_0_1; + uniform_real_distribution rng_crossover_weight; - map inserted_from_map; - map generated_from_map; + double more_fit_crossover_rate; + double less_fit_crossover_rate; - bool generate_op_log; + double clone_rate; - minstd_rand0 generator; - uniform_real_distribution rng_0_1; - uniform_real_distribution rng_crossover_weight; + double add_edge_rate; + double add_recurrent_edge_rate; + double enable_edge_rate; + double disable_edge_rate; + double split_edge_rate; - double more_fit_crossover_rate; - double less_fit_crossover_rate; + double add_node_rate; + double enable_node_rate; + double disable_node_rate; + double split_node_rate; + double merge_node_rate; - double clone_rate; + vector possible_node_types; - double add_edge_rate; - double add_recurrent_edge_rate; - double enable_edge_rate; - double disable_edge_rate; - double split_edge_rate; + vector op_log_ordering; + map inserted_counts; + map generated_counts; - double add_node_rate; - double enable_node_rate; - double disable_node_rate; - double split_node_rate; - double merge_node_rate; + string output_directory; + ofstream *log_file; + ofstream *op_log_file; - vector possible_node_types; + std::chrono::time_point startClock; - vector op_log_ordering; - map inserted_counts; - map generated_counts; + string genome_file_name; - string output_directory; - ofstream* log_file; - ofstream* op_log_file; + public: + EXAMM( int32_t _island_size, + int32_t _number_islands, + int32_t _max_genomes, + double _learning_rate, + SpeciationStrategy *_speciation_strategy, + WeightRules *_weight_rules, + GenomeProperty *_genome_property, + string _output_directory); - std::chrono::time_point startClock; + ~EXAMM(); - string genome_file_name; + void print(); + void update_log(); - public: - EXAMM( - int32_t _island_size, int32_t _number_islands, int32_t _max_genomes, SpeciationStrategy* _speciation_strategy, - WeightRules* _weight_rules, GenomeProperty* _genome_property, string _output_directory - ); + void set_possible_node_types(vector possible_node_type_strings); - ~EXAMM(); + uniform_int_distribution get_recurrent_depth_dist(); - void print(); - void update_log(); + int32_t get_random_node_type(); - void set_possible_node_types(vector possible_node_type_strings); + RNN_Genome* generate_genome(); + bool insert_genome(RNN_Genome* genome); - uniform_int_distribution get_recurrent_depth_dist(); + void mutate(int32_t max_mutations, RNN_Genome *p1); - int32_t get_random_node_type(); + void attempt_node_insert(vector &child_nodes, const RNN_Node_Interface *node, const vector &new_weights); + void attempt_edge_insert(vector &child_edges, vector &child_nodes, RNN_Edge *edge, RNN_Edge *second_edge, bool set_enabled); + void attempt_recurrent_edge_insert(vector &child_recurrent_edges, vector &child_nodes, RNN_Recurrent_Edge *recurrent_edge, RNN_Recurrent_Edge *second_edge, bool set_enabled); + RNN_Genome* crossover(RNN_Genome *p1, RNN_Genome *p2); - RNN_Genome* generate_genome(); - bool insert_genome(RNN_Genome* genome); + double get_best_fitness(); + double get_worst_fitness(); + RNN_Genome* get_best_genome(); + RNN_Genome* get_worst_genome(); - void mutate(int32_t max_mutations, RNN_Genome* p1); + //SHO SY + void generate_initial_hyperparameters(double &learning_rate); - void attempt_node_insert( - vector& child_nodes, const RNN_Node_Interface* node, const vector& new_weights - ); - void attempt_edge_insert( - vector& child_edges, vector& child_nodes, RNN_Edge* edge, RNN_Edge* second_edge, - bool set_enabled - ); - void attempt_recurrent_edge_insert( - vector& child_recurrent_edges, vector& child_nodes, - RNN_Recurrent_Edge* recurrent_edge, RNN_Recurrent_Edge* second_edge, bool set_enabled - ); - RNN_Genome* crossover(RNN_Genome* p1, RNN_Genome* p2); + void generate_simplex_hyperparameters(double &learning_rate); - double get_best_fitness(); - double get_worst_fitness(); - RNN_Genome* get_best_genome(); - RNN_Genome* get_worst_genome(); + string get_output_directory() const; - string get_output_directory() const; + void check_weight_initialize_validity(); + void generate_log(); + void set_evolution_hyper_parameters(); + void initialize_seed_genome(); + void update_op_log_statistics(RNN_Genome *genome, int32_t insert_position); - void check_weight_initialize_validity(); - void generate_log(); - void set_evolution_hyper_parameters(); - void initialize_seed_genome(); - void update_op_log_statistics(RNN_Genome* genome, int32_t insert_position); }; #endif diff --git a/examm/island.cxx b/examm/island.cxx index cfa169ba..1ec43102 100644 --- a/examm/island.cxx +++ b/examm/island.cxx @@ -1,6 +1,6 @@ #include -using std::lower_bound; using std::sort; +using std::lower_bound; using std::upper_bound; #include @@ -17,73 +17,56 @@ using std::to_string; #include using std::unordered_map; -#include -using std::vector; - -#include "common/log.hxx" #include "island.hxx" #include "rnn/rnn_genome.hxx" -Island::Island(int32_t _id, int32_t _max_size) - : id(_id), max_size(_max_size), status(Island::INITIALIZING), erase_again(0), erased(false) { +#include "common/log.hxx" + +Island::Island(int32_t _id, int32_t _max_size) : id(_id), max_size(_max_size), status(Island::INITIALIZING), erase_again(0), erased(false) { +} + +Island::Island(int32_t _id, vector _genomes) : id(_id), max_size((int32_t)_genomes.size()), genomes(_genomes), status(Island::FILLED), erase_again(0), erased(false) { } -Island::Island(int32_t _id, vector _genomes) - : id(_id), - max_size((int32_t) _genomes.size()), - genomes(_genomes), - status(Island::FILLED), - erase_again(0), - erased(false) { +//SHO SY +RNN_Genome* Island::get_genome_at(int32_t _index) { + if (genomes.size() == 0) return NULL; + else return genomes[_index]; } RNN_Genome* Island::get_best_genome() { - if (genomes.size() == 0) { - return NULL; - } else { - return genomes[0]; - } + if (genomes.size() == 0) return NULL; + else return genomes[0]; } RNN_Genome* Island::get_worst_genome() { - if (genomes.size() == 0) { - return NULL; - } else { - return genomes.back(); - } + if (genomes.size() == 0) return NULL; + else return genomes.back(); } double Island::get_best_fitness() { - RNN_Genome* best_genome = get_best_genome(); - if (best_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return best_genome->get_fitness(); - } + RNN_Genome *best_genome = get_best_genome(); + if (best_genome == NULL) return EXAMM_MAX_DOUBLE; + else return best_genome->get_fitness(); } double Island::get_worst_fitness() { - RNN_Genome* worst_genome = get_worst_genome(); - if (worst_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return worst_genome->get_fitness(); - } + RNN_Genome *worst_genome = get_worst_genome(); + if (worst_genome == NULL) return EXAMM_MAX_DOUBLE; + else return worst_genome->get_fitness(); } int32_t Island::get_max_size() { - return (int32_t) max_size; + return (int32_t)max_size; } int32_t Island::size() { - return (int32_t) genomes.size(); + return (int32_t)genomes.size(); } bool Island::is_full() { - bool filled = (int32_t) genomes.size() >= max_size; - if (filled) { - status = Island::FILLED; - } + bool filled = (int32_t)genomes.size() >= max_size; + if (filled) status = Island::FILLED; return filled; } @@ -95,23 +78,19 @@ bool Island::is_repopulating() { return status == Island::REPOPULATING; } -void Island::copy_random_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome -) { + + +void Island::copy_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome) { int32_t genome_position = size() * rng_0_1(generator); *genome = genomes[genome_position]->copy(); } -void Island::copy_two_random_genomes( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome1, RNN_Genome** genome2 -) { +void Island::copy_two_random_genomes(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome1, RNN_Genome **genome2) { int32_t p1 = size() * rng_0_1(generator); int32_t p2 = (size() - 1) * rng_0_1(generator); - if (p2 >= p1) { - p2++; - } + if (p2 >= p1) p2++; - // swap the gnomes so that the first parent is the more fit parent + //swap the gnomes so that the first parent is the more fit parent if (p1 > p2) { int32_t tmp = p1; p1 = p2; @@ -123,21 +102,18 @@ void Island::copy_two_random_genomes( } void Island::do_population_check(int32_t line, int32_t initial_size) { - if (status == Island::FILLED && (int32_t) genomes.size() < max_size) { - Log::error( - "ERROR: do_population_check had issue on island.cxx line %d, status was FILLED and genomes.size() was: %d, " - "size at beginning of insert was: %d\n", - line, genomes.size(), initial_size - ); + if (status == Island::FILLED && (int32_t)genomes.size() < max_size) { + Log::error("ERROR: do_population_check had issue on island.cxx line %d, status was FILLED and genomes.size() was: %d, size at beginning of insert was: %d\n", line, genomes.size(), initial_size); status = Island::INITIALIZING; } } -// returns -1 for not inserted, otherwise the index it was inserted at -// inserts a copy of the genome, caller of the function will need to delete their -// pointer -int32_t Island::insert_genome(RNN_Genome* genome) { - int32_t initial_size = (int32_t) genomes.size(); + +//returns -1 for not inserted, otherwise the index it was inserted at +//inserts a copy of the genome, caller of the function will need to delete their +//pointer +int32_t Island::insert_genome(RNN_Genome *genome) { + int32_t initial_size = (int32_t)genomes.size(); if (genome->get_generation_id() <= erased_generation_id) { Log::trace("genome already erased, not inserting"); do_population_check(__LINE__, initial_size); @@ -147,124 +123,92 @@ int32_t Island::insert_genome(RNN_Genome* genome) { double new_fitness = genome->get_fitness(); Log::debug("inserting genome with fitness: %s to island %d\n", parse_fitness(genome->get_fitness()).c_str(), id); - // discard the genome if the island is full and it's fitness is worse than the worst in thte population + //discard the genome if the island is full and it's fitness is worse than the worst in thte population if (is_full() && new_fitness > get_worst_fitness()) { - Log::debug( - "ignoring genome, fitness: %lf > worst for island[%d] fitness: %lf\n", new_fitness, id, - genomes.back()->get_fitness() - ); + Log::debug("ignoring genome, fitness: %lf > worst for island[%d] fitness: %lf\n", new_fitness, id, genomes.back()->get_fitness()); do_population_check(__LINE__, initial_size); return false; } - // check and see if the structural hash of the genome is in the - // set of hashes for this population + //check and see if the structural hash of the genome is in the + //set of hashes for this population string structural_hash = genome->get_structural_hash(); if (structure_map.count(structural_hash) > 0) { - vector& potential_matches = structure_map.find(structural_hash)->second; - Log::debug( - "potential duplicate for hash '%s', had %d potential matches.\n", structural_hash.c_str(), - potential_matches.size() - ); - - for (auto potential_match = potential_matches.begin(); potential_match != potential_matches.end();) { - Log::debug( - "on potential match %d of %d\n", potential_match - potential_matches.begin(), potential_matches.size() - ); + vector &potential_matches = structure_map.find(structural_hash)->second; + Log::debug("potential duplicate for hash '%s', had %d potential matches.\n", structural_hash.c_str(), potential_matches.size()); + + for (auto potential_match = potential_matches.begin(); potential_match != potential_matches.end(); ) { + Log::debug("on potential match %d of %d\n", potential_match - potential_matches.begin(), potential_matches.size()); if ((*potential_match)->equals(genome)) { if ((*potential_match)->get_fitness() > new_fitness) { - Log::debug( - "REPLACING DUPLICATE GENOME, fitness of genome in search: %s, new fitness: %s\n", - parse_fitness((*potential_match)->get_fitness()).c_str(), - parse_fitness(genome->get_fitness()).c_str() - ); - // we have an exact match for this genome in the island and its fitness is worse - // than the genome we're trying to remove, so remove the duplicate it from the genomes - // as well from the potential matches vector - - auto duplicate_genome_iterator = - lower_bound(genomes.begin(), genomes.end(), *potential_match, sort_genomes_by_fitness()); + Log::debug("REPLACING DUPLICATE GENOME, fitness of genome in search: %s, new fitness: %s\n", parse_fitness((*potential_match)->get_fitness()).c_str(), parse_fitness(genome->get_fitness()).c_str()); + //we have an exact match for this genome in the island and its fitness is worse + //than the genome we're trying to remove, so remove the duplicate it from the genomes + //as well from the potential matches vector + + auto duplicate_genome_iterator = lower_bound(genomes.begin(), genomes.end(), *potential_match, sort_genomes_by_fitness()); bool found = false; for (; duplicate_genome_iterator != genomes.end(); duplicate_genome_iterator++) { - Log::debug( - "duplicate_genome_iterator: %p, (*potential_match): %p\n", (*duplicate_genome_iterator), - (*potential_match) - ); + Log::debug("duplicate_genome_iterator: %p, (*potential_match): %p\n", (*duplicate_genome_iterator), (*potential_match)); if ((*duplicate_genome_iterator) == (*potential_match)) { found = true; break; } } if (!found) { - Log::fatal( - "ERROR: could not find duplicate genome even though its structural hash was in the island, " - "this should never happen!\n" - ); + Log::fatal("ERROR: could not find duplicate genome even though its structural hash was in the island, this should never happen!\n"); exit(1); } - Log::debug( - "potential_match->get_fitness(): %lf, duplicate_genome_iterator->get_fitness(): %lf, " - "new_fitness: %lf\n", - (*potential_match)->get_fitness(), (*duplicate_genome_iterator)->get_fitness(), new_fitness - ); + Log::debug("potential_match->get_fitness(): %lf, duplicate_genome_iterator->get_fitness(): %lf, new_fitness: %lf\n", (*potential_match)->get_fitness(), (*duplicate_genome_iterator)->get_fitness(), new_fitness); int32_t duplicate_genome_index = duplicate_genome_iterator - genomes.begin(); Log::debug("duplicate_genome_index: %d\n", duplicate_genome_index); - // int32_t test_index = contains(genome); - // Log::info("test_index: %d\n", test_index); - RNN_Genome* duplicate = genomes[duplicate_genome_index]; - // Log::info("duplicate.equals(potential_match)? %d\n", duplicate->equals(*potential_match)); + //int32_t test_index = contains(genome); + //Log::info("test_index: %d\n", test_index); + RNN_Genome *duplicate = genomes[duplicate_genome_index]; + //Log::info("duplicate.equals(potential_match)? %d\n", duplicate->equals(*potential_match)); genomes.erase(genomes.begin() + duplicate_genome_index); Log::debug("potential_matches.size() before erase: %d\n", potential_matches.size()); - // erase the potential match from the structure map as well - // returns an iterator to next element after the deleted one so - // we don't need to increment it + //erase the potential match from the structure map as well + //returns an iterator to next element after the deleted one so + //we don't need to increment it potential_match = potential_matches.erase(potential_match); delete duplicate; Log::debug("potential_matches.size() after erase: %d\n", potential_matches.size()); - Log::debug( - "structure_map[%s].size() after erase: %d\n", structural_hash.c_str(), - structure_map[structural_hash].size() - ); + Log::debug("structure_map[%s].size() after erase: %d\n", structural_hash.c_str(), structure_map[structural_hash].size()); if (potential_matches.size() == 0) { - Log::debug( - "deleting the potential_matches vector for hash '%s' because it was empty.\n", - structural_hash.c_str() - ); + Log::debug("deleting the potential_matches vector for hash '%s' because it was empty.\n", structural_hash.c_str()); structure_map.erase(structural_hash); - break; // break because this vector is now empty and deleted + break; //break because this vector is now empty and deleted } } else { - Log::info( - "Island %d: island already contains a duplicate genome with a better fitness! not inserting.\n", - id - ); + Log::info("Island %d: island already contains a duplicate genome with a better fitness! not inserting.\n", id); do_population_check(__LINE__, initial_size); return -1; } } else { - // increment potential match because we didn't delete an entry (or return from the method) + //increment potential match because we didn't delete an entry (or return from the method) potential_match++; } } } - // inorder insert the new individual - RNN_Genome* copy = genome->copy(); - vector best = copy->get_best_parameters(); - if (best.size() != 0) { + //inorder insert the new individual + RNN_Genome *copy = genome->copy(); + vector best = copy -> get_best_parameters(); + if(best.size() != 0){ copy->set_weights(best); } - copy->set_generation_id(genome->get_generation_id()); + copy -> set_generation_id (genome -> get_generation_id()); Log::debug("created copy to insert to island: %d\n", copy->get_group_id()); auto index_iterator = upper_bound(genomes.begin(), genomes.end(), copy, sort_genomes_by_fitness()); int32_t insert_index = index_iterator - genomes.begin(); Log::debug("inserting genome at index: %d\n", insert_index); if (insert_index >= max_size) { - // if we're going to insert this at the back of the population - // its just going to get removed anyways, so we can delete - // it and report it was not inserted. + //if we're going to insert this at the back of the population + //its just going to get removed anyways, so we can delete + //it and report it was not inserted. Log::debug("not inserting genome because it is worse than the worst fitness\n"); delete copy; do_population_check(__LINE__, initial_size); @@ -272,70 +216,62 @@ int32_t Island::insert_genome(RNN_Genome* genome) { } genomes.insert(index_iterator, copy); - // calculate the index the genome was inseretd at from the iterator + //calculate the index the genome was inseretd at from the iterator structural_hash = copy->get_structural_hash(); - // add the genome to the vector for this structural hash + //add the genome to the vector for this structural hash structure_map[structural_hash].push_back(copy); Log::debug("adding to structure_map[%s] : %p\n", structural_hash.c_str(), ©); if (insert_index == 0) { - // this was a new best genome for this island + //this was a new best genome for this island Log::info("Island %d: new best fitness found!\n", id); if (genome->get_fitness() != EXAMM_MAX_DOUBLE) { - // need to set the weights for non-initial genomes so we - // can generate a proper graphviz file + //need to set the weights for non-initial genomes so we + //can generate a proper graphviz file vector best_parameters = genome->get_best_parameters(); genome->set_weights(best_parameters); } } - if ((int32_t) genomes.size() >= max_size) { - // the island is filled + + if ((int32_t)genomes.size() >= max_size) { + //the island is filled status = Island::FILLED; } Log::info("Island %d: genomes.size(): %d, max_size: %d, status: %d\n", id, genomes.size(), max_size, status); - if ((int32_t) genomes.size() > max_size) { - // island was full before insert so now we need to - // delete the worst genome in the island. + if ((int32_t)genomes.size() > max_size) { + //island was full before insert so now we need to + //delete the worst genome in the island. Log::debug("deleting worst genome\n"); - RNN_Genome* worst = genomes.back(); + RNN_Genome *worst = genomes.back(); genomes.pop_back(); structural_hash = worst->get_structural_hash(); - vector& potential_matches = structure_map.find(structural_hash)->second; + vector &potential_matches = structure_map.find(structural_hash)->second; bool found = false; - for (auto potential_match = potential_matches.begin(); potential_match != potential_matches.end();) { - // make sure the addresses of the pointers are the same - Log::debug( - "checking to remove worst from structure_map - &worst: %p, &(*potential_match): %p\n", worst, - (*potential_match) - ); + for (auto potential_match = potential_matches.begin(); potential_match != potential_matches.end(); ) { + //make sure the addresses of the pointers are the same + Log::debug("checking to remove worst from structure_map - &worst: %p, &(*potential_match): %p\n", worst, (*potential_match)); if ((*potential_match) == worst) { found = true; Log::debug("potential_matches.size() before erase: %d\n", potential_matches.size()); - // erase the potential match from the structure map as well + //erase the potential match from the structure map as well potential_match = potential_matches.erase(potential_match); Log::debug("potential_matches.size() after erase: %d\n", potential_matches.size()); - Log::debug( - "structure_map[%s].size() after erase: %d\n", structural_hash.c_str(), - structure_map[structural_hash].size() - ); + Log::debug("structure_map[%s].size() after erase: %d\n", structural_hash.c_str(), structure_map[structural_hash].size()); - // clean up the structure_map if no genomes in the population have this hash + //clean up the structure_map if no genomes in the population have this hash if (potential_matches.size() == 0) { - Log::debug( - "deleting the potential_matches vector for hash '%s' because it was empty.\n", - structural_hash.c_str() - ); + Log::debug("deleting the potential_matches vector for hash '%s' because it was empty.\n", structural_hash.c_str()); structure_map.erase(structural_hash); break; } @@ -345,10 +281,7 @@ int32_t Island::insert_genome(RNN_Genome* genome) { } if (!found) { - Log::debug( - "could not erase from structure_map[%s], genome not found! This should never happen.\n", - structural_hash.c_str() - ); + Log::debug("could not erase from structure_map[%s], genome not found! This should never happen.\n", structural_hash.c_str()); exit(1); } @@ -356,10 +289,10 @@ int32_t Island::insert_genome(RNN_Genome* genome) { } if (insert_index >= max_size) { - // technically we shouldn't get here but it might happen - // if the genome's fitness == the worst fitness in the - // island. So in this case it was not inserted to the - // island and return -1 + //technically we shouldn't get here but it might happen + //if the genome's fitness == the worst fitness in the + //island. So in this case it was not inserted to the + //island and return -1 do_population_check(__LINE__, initial_size); return -1; } else { @@ -370,9 +303,10 @@ int32_t Island::insert_genome(RNN_Genome* genome) { void Island::print(string indent) { if (Log::at_level(Log::TRACE)) { + Log::trace("%s\t%s\n", indent.c_str(), RNN_Genome::print_statistics_header().c_str()); - for (int32_t i = 0; i < (int32_t) genomes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genomes.size(); i++) { Log::trace("%s\t%s\n", indent.c_str(), genomes[i]->print_statistics().c_str()); } } @@ -380,7 +314,7 @@ void Island::print(string indent) { void Island::erase_island() { erased_generation_id = latest_generation_id; - for (int32_t i = 0; i < (int32_t) genomes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genomes.size(); i++) { delete genomes[i]; } genomes.clear(); @@ -408,8 +342,7 @@ int32_t Island::get_status() { } void Island::set_status(int32_t status_to_set) { - if (status_to_set == Island::INITIALIZING || status_to_set == Island::FILLED - || status_to_set == Island::REPOPULATING) { + if (status_to_set == Island::INITIALIZING || status_to_set == Island::FILLED || status_to_set == Island::REPOPULATING) { status = status_to_set; } else { Log::error("Island::set_status: Wrong island status to set! %d\n", status_to_set); @@ -421,11 +354,11 @@ bool Island::been_erased() { return erased; } -vector Island::get_genomes() { +vector Island::get_genomes() { return genomes; } -void Island::set_latest_generation_id(int32_t _latest_generation_id) { +void Island::set_latest_generation_id(int32_t _latest_generation_id){ latest_generation_id = _latest_generation_id; } @@ -437,27 +370,19 @@ void Island::set_erase_again_num() { erase_again--; } -void Island::fill_with_mutated_genomes( - RNN_Genome* seed_genome, int32_t num_mutations, bool tl_epigenetic_weights, - function& mutate -) { +void Island::fill_with_mutated_genomes(RNN_Genome *seed_genome, int32_t num_mutations, bool tl_epigenetic_weights, function &mutate) { Log::info("Island %d: Filling island with mutated seed genomes\n", id); for (int32_t i = 0; i < max_size; i++) { - RNN_Genome* new_genome = seed_genome->copy(); + RNN_Genome *new_genome = seed_genome->copy(); mutate(num_mutations, seed_genome); new_genome->set_generation_id(0); - if (tl_epigenetic_weights) { - new_genome->initialize_randomly(); - } + if (tl_epigenetic_weights) new_genome->initialize_randomly(); genomes.push_back(new_genome); } if (is_full()) { Log::info("island %d: is filled with mutated genome\n", id); } else { - Log::fatal( - "island (max capacity %d) is still not full after filled with mutated genomes, current island size is %d\n", - max_size, genomes.size() - ); + Log::fatal("island (max capacity %d) is still not full after filled with mutated genomes, current island size is %d\n", max_size, genomes.size()); exit(1); } -} +} \ No newline at end of file diff --git a/examm/island.hxx b/examm/island.hxx index b0b8b78a..c02ef6bb 100644 --- a/examm/island.hxx +++ b/examm/island.hxx @@ -18,194 +18,201 @@ using std::string; #include using std::unordered_map; + #include "rnn/rnn_genome.hxx" + class Island { - private: - int32_t id; /**< An integer ID for this island. */ - int32_t max_size; /**< The maximum number of genomes in the island. */ - int32_t erased_generation_id = - -1; /**< The latest generation id of an erased island, erased_generation_id = largest_generation_id when this - island is erased, to prevent deleted genomes get inserted back */ - int32_t latest_generation_id; /**< The latest generation id of genome being generated, including the ones doing - backprop by workers */ - - /** - * The genomes on this island, stored in sorted order best (front) to worst (back). - */ - vector genomes; - - unordered_map> structure_map; - int32_t - status; /**> The status of this island (either Island:INITIALIZING, Island::FILLED or Island::REPOPULATING */ - - int32_t erase_again; /**< a flag to track if this islands has been erased */ - bool erased; /**< a flag to track if this islands has been erased */ - - public: - const static int32_t INITIALIZING = 0; /**< status flag for if the island is initializing. */ - const static int32_t FILLED = 1; /**< status flag for if the island is filled. */ - const static int32_t REPOPULATING = 2; /**< status flag for if the island is repopulating. */ - - /** - * Initializes an island with a given max size. - * - * \param max_size is the maximum number of genomes in the island. - */ - Island(int32_t id, int32_t max_size); - - /** - * Initializes an island filled the supplied genomes. The size of the island will be the size - * of the supplied genome vector. The island status is set to filled. - */ - Island(int32_t id, vector genomes); - - /** - * Returns the fitness of the best genome in the island - * - * \return the best fitness of the island - */ - double get_best_fitness(); - - /** - * Returns the fitness of the worst genome in the island - * - * \return the worst fitness of the island - */ - double get_worst_fitness(); - - /** - * Returns the best genomme in the island. - * - * \return the best genome in the island - */ - RNN_Genome* get_best_genome(); - - /** - * Returns the worst genomme in the island. - * - * \return the worst genome in the island - */ - RNN_Genome* get_worst_genome(); - - /** - * Returns the maximum number of genomes the island can hold - * - * \return the maximum number of genomes this island can have - */ - int32_t get_max_size(); - - /** - * Returns the size of the island - * - * \return the number of genomes in this island. - */ - int32_t size(); - - /** - * Returns true if the island has Island::max_size genomes. - * - * \return true if the number of genomes in the island is >= size (although - * it should never be > size). - */ - bool is_full(); - - /** - * Returns true if the island is initializing, i.e., it's size is <= max_size - * and it hasn't been cleared out for repopulating. - * - * \return true if island is initializing. - */ - bool is_initializing(); - - /** - * Returns true if the island is repopulating, i.e., it's size is <= max_size - * and it has been full before but cleared out for repopulation. - * - * \return true if island is repopulating. - */ - bool is_repopulating(); - - /** - * Selects a genome from the island at random and returns a copy of it. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param genome will be the copied genome, an - * addresss to a pointer needs to be passed. - */ - void copy_random_genome(uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome); - - /** - * Selects two different genomes from the island at random and returns copies of them. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param genome1 will be the first copied genome, - * an addresss to a pointer needs to be passed. \param genome2 will be the second copied genome, an addresss to a - * pointer needs to be passed. - */ - void copy_two_random_genomes( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome1, RNN_Genome** genome2 - ); - - void do_population_check(int32_t line, int32_t initial_size); - - /** - * Inserts a genome into the island. - * - * Genomes are inserted in best to worst order genomes[0] will have - * the best fitness and genomes[size - 1] will have the worst. - * - * \param genome is the genome to be inserted. - * \return -1 if not inserted, otherwise the index it was inserted at - */ - int32_t insert_genome(RNN_Genome* genome); - - /** - * Prints out the state of this island. - * - * \param indent is how much to indent what is printed out - */ - void print(string indent = ""); - - /** - * erases the entire island and set the erased_generation_id. - */ - void erase_island(); - - void erase_structure_map(); - - /** - * returns the get_erased_generation_id. - */ - int32_t get_erased_generation_id(); - - /** - * \return the status of the island - */ - int32_t get_status(); - - /** - * after erasing the island, sets the island status to repopulating. - */ - void set_status(int32_t status_to_set); - - /** - * return if this island has been erased before. - */ - bool been_erased(); - - vector get_genomes(); - - void set_latest_generation_id(int32_t _latest_generation_id); - - int32_t get_erase_again_num(); - - void set_erase_again_num(); - - void fill_with_mutated_genomes( - RNN_Genome* seed_genome, int32_t num_mutations, bool tl_epigenetic_weights, - function& mutate - ); + private: + int32_t id; /**< An integer ID for this island. */ + int32_t max_size; /**< The maximum number of genomes in the island. */ + int32_t erased_generation_id = -1; /**< The latest generation id of an erased island, erased_generation_id = largest_generation_id when this island is erased, + to prevent deleted genomes get inserted back */ + int32_t latest_generation_id; /**< The latest generation id of genome being generated, including the ones doing backprop by workers */ + + /** + * The genomes on this island, stored in sorted order best (front) to worst (back). + */ + vector genomes; + + unordered_map> structure_map; + int32_t status; /**> The status of this island (either Island:INITIALIZING, Island::FILLED or Island::REPOPULATING */ + + int32_t erase_again; /**< a flag to track if this islands has been erased */ + bool erased; /**< a flag to track if this islands has been erased */ + + public: + const static int32_t INITIALIZING = 0; /**< status flag for if the island is initializing. */ + const static int32_t FILLED = 1; /**< status flag for if the island is filled. */ + const static int32_t REPOPULATING = 2; /**< status flag for if the island is repopulating. */ + + /** + * Initializes an island with a given max size. + * + * \param max_size is the maximum number of genomes in the island. + */ + Island(int32_t id, int32_t max_size); + + /** + * Initializes an island filled the supplied genomes. The size of the island will be the size + * of the supplied genome vector. The island status is set to filled. + */ + Island(int32_t id, vector genomes); + + /** + * Returns the fitness of the best genome in the island + * + * \return the best fitness of the island + */ + double get_best_fitness(); + + /** + * Returns the fitness of the worst genome in the island + * + * \return the worst fitness of the island + */ + double get_worst_fitness(); + + /** + * Returns the best genomme in the island. + * + * \return the best genome in the island + */ + RNN_Genome *get_best_genome(); + + /** + * Returns the worst genomme in the island. + * + * \return the worst genome in the island + */ + RNN_Genome *get_worst_genome(); + + //SHO SY + /** + * Returns the genome at a given index in the island. + * + * \param _index is the index of required genome in the island + * \return genome at a given index in the island + */ + RNN_Genome *get_genome_at(int32_t _index); + + /** + * Returns the maximum number of genomes the island can hold + * + * \return the maximum number of genomes this island can have + */ + int32_t get_max_size(); + + + + + /** + * Returns the size of the island + * + * \return the number of genomes in this island. + */ + int32_t size(); + + /** + * Returns true if the island has Island::max_size genomes. + * + * \return true if the number of genomes in the island is >= size (although + * it should never be > size). + */ + bool is_full(); + + /** + * Returns true if the island is initializing, i.e., it's size is <= max_size + * and it hasn't been cleared out for repopulating. + * + * \return true if island is initializing. + */ + bool is_initializing(); + + /** + * Returns true if the island is repopulating, i.e., it's size is <= max_size + * and it has been full before but cleared out for repopulation. + * + * \return true if island is repopulating. + */ + bool is_repopulating(); + + /** + * Selects a genome from the island at random and returns a copy of it. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param genome will be the copied genome, an addresss to a pointer needs to be passed. + */ + void copy_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome); + + /** + * Selects two different genomes from the island at random and returns copies of them. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param genome1 will be the first copied genome, an addresss to a pointer needs to be passed. + * \param genome2 will be the second copied genome, an addresss to a pointer needs to be passed. + */ + void copy_two_random_genomes(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome1, RNN_Genome **genome2); + + void do_population_check(int32_t line, int32_t initial_size); + + /** + * Inserts a genome into the island. + * + * Genomes are inserted in best to worst order genomes[0] will have + * the best fitness and genomes[size - 1] will have the worst. + * + * \param genome is the genome to be inserted. + * \return -1 if not inserted, otherwise the index it was inserted at + */ + int32_t insert_genome(RNN_Genome* genome); + + /** + * Prints out the state of this island. + * + * \param indent is how much to indent what is printed out + */ + void print(string indent = ""); + + /** + * erases the entire island and set the erased_generation_id. + */ + void erase_island(); + + void erase_structure_map(); + + /** + * returns the get_erased_generation_id. + */ + int32_t get_erased_generation_id(); + + /** + * \return the status of the island + */ + int32_t get_status(); + + + /** + * after erasing the island, sets the island status to repopulating. + */ + void set_status(int32_t status_to_set); + + /** + * return if this island has been erased before. + */ + bool been_erased(); + + vector get_genomes(); + + void set_latest_generation_id(int32_t _latest_generation_id); + + int32_t get_erase_again_num(); + + void set_erase_again_num(); + + void fill_with_mutated_genomes(RNN_Genome *seed_genome, int32_t num_mutations, bool tl_epigenetic_weights, function &mutate); }; #endif diff --git a/examm/island_speciation_strategy.cxx b/examm/island_speciation_strategy.cxx index 920eb203..835b28ec 100644 --- a/examm/island_speciation_strategy.cxx +++ b/examm/island_speciation_strategy.cxx @@ -3,7 +3,7 @@ using std::function; #include -// #include +//#include #include @@ -13,42 +13,46 @@ using std::uniform_real_distribution; #include using std::string; -#include "common/log.hxx" #include "examm.hxx" -#include "island_speciation_strategy.hxx" #include "rnn/rnn_genome.hxx" +#include "island_speciation_strategy.hxx" + +#include "common/log.hxx" /** * */ IslandSpeciationStrategy::IslandSpeciationStrategy( - int32_t _number_of_islands, int32_t _max_island_size, double _mutation_rate, double _intra_island_crossover_rate, - double _inter_island_crossover_rate, RNN_Genome* _seed_genome, string _island_ranking_method, - string _repopulation_method, int32_t _extinction_event_generation_number, int32_t _num_mutations, - int32_t _islands_to_exterminate, int32_t _max_genomes, bool _repeat_extinction, bool _start_filled, - bool _transfer_learning, string _transfer_learning_version, int32_t _seed_stirs, bool _tl_epigenetic_weights -) - : generation_island(0), - number_of_islands(_number_of_islands), - max_island_size(_max_island_size), - mutation_rate(_mutation_rate), - intra_island_crossover_rate(_intra_island_crossover_rate), - inter_island_crossover_rate(_inter_island_crossover_rate), - generated_genomes(0), - evaluated_genomes(0), - seed_genome(_seed_genome), - island_ranking_method(_island_ranking_method), - repopulation_method(_repopulation_method), - extinction_event_generation_number(_extinction_event_generation_number), - num_mutations(_num_mutations), - islands_to_exterminate(_islands_to_exterminate), - max_genomes(_max_genomes), - repeat_extinction(_repeat_extinction), - start_filled(_start_filled), - transfer_learning(_transfer_learning), - transfer_learning_version(_transfer_learning_version), - seed_stirs(_seed_stirs), - tl_epigenetic_weights(_tl_epigenetic_weights) { + int32_t _number_of_islands, int32_t _max_island_size, + double _mutation_rate, double _intra_island_crossover_rate, + double _inter_island_crossover_rate, RNN_Genome *_seed_genome, + string _island_ranking_method, string _repopulation_method, + int32_t _extinction_event_generation_number, int32_t _num_mutations, + int32_t _islands_to_exterminate, int32_t _max_genomes, + bool _repeat_extinction, bool _start_filled, + bool _transfer_learning, string _transfer_learning_version, int32_t _seed_stirs, bool _tl_epigenetic_weights) : + generation_island(0), + number_of_islands(_number_of_islands), + max_island_size(_max_island_size), + mutation_rate(_mutation_rate), + intra_island_crossover_rate(_intra_island_crossover_rate), + inter_island_crossover_rate(_inter_island_crossover_rate), + generated_genomes(0), + evaluated_genomes(0), + seed_genome(_seed_genome), + island_ranking_method(_island_ranking_method), + repopulation_method(_repopulation_method), + extinction_event_generation_number(_extinction_event_generation_number), + num_mutations(_num_mutations), + islands_to_exterminate(_islands_to_exterminate), + max_genomes(_max_genomes), + repeat_extinction(_repeat_extinction), + start_filled(_start_filled), + transfer_learning(_transfer_learning), + transfer_learning_version(_transfer_learning_version), + seed_stirs(_seed_stirs), + tl_epigenetic_weights(_tl_epigenetic_weights) { + double rate_sum = mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate; if (rate_sum != 1.0) { mutation_rate = mutation_rate / rate_sum; @@ -59,7 +63,7 @@ IslandSpeciationStrategy::IslandSpeciationStrategy( intra_island_crossover_rate += mutation_rate; inter_island_crossover_rate += intra_island_crossover_rate; - // set the generation id for the initial minimal genome + //set the generation id for the initial minimal genome seed_genome->set_generation_id(generated_genomes); global_best_genome = NULL; @@ -70,24 +74,23 @@ IslandSpeciationStrategy::IslandSpeciationStrategy( Log::info("Island Strategy: Extinction event generation number is %d\n", extinction_event_generation_number); Log::info("Island Strategy: Repopulation method is %s\n", repopulation_method.c_str()); Log::info("Island Strategy: Island ranking method is %s\n", island_ranking_method.c_str()); - Log::info("Island Strategy: Repeat extinction is set to %s\n", repeat_extinction ? "true" : "false"); + Log::info("Island Strategy: Repeat extinction is set to %s\n", repeat_extinction? "true":"false"); Log::info("Island Strategy: islands_to_exterminate is set to %d\n", islands_to_exterminate); } - Log::info("Island Strategy: Doing transfer learning: %s\n", transfer_learning ? "true" : "false"); + Log::info("Island Strategy: Doing transfer learning: %s\n", transfer_learning? "true":"false"); if (transfer_learning) { Log::info("Transfer learning version is %s\n", transfer_learning_version.c_str()); Log::info("Apply seed stirs: %d\n", seed_stirs); } + } -void IslandSpeciationStrategy::initialize_population(function& mutate) { +void IslandSpeciationStrategy::initialize_population(function &mutate) { for (int32_t i = 0; i < number_of_islands; i++) { - Island* new_island = new Island(i, max_island_size); - if (start_filled) { - new_island->fill_with_mutated_genomes(seed_genome, seed_stirs, tl_epigenetic_weights, mutate); - } + Island *new_island = new Island(i, max_island_size); + if (start_filled) new_island->fill_with_mutated_genomes(seed_genome, seed_stirs, tl_epigenetic_weights, mutate); islands.push_back(new_island); } } @@ -101,7 +104,7 @@ int32_t IslandSpeciationStrategy::get_evaluated_genomes() const { } RNN_Genome* IslandSpeciationStrategy::get_best_genome() { - // the global_best_genome is updated every time a genome is inserted + //the global_best_genome is updated every time a genome is inserted return global_best_genome; } @@ -109,7 +112,7 @@ RNN_Genome* IslandSpeciationStrategy::get_worst_genome() { int32_t worst_genome_island = -1; double worst_fitness = -EXAMM_MAX_DOUBLE; - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { if (islands[i]->size() > 0) { double island_worst_fitness = islands[i]->get_worst_fitness(); if (island_worst_fitness > worst_fitness) { @@ -126,47 +129,40 @@ RNN_Genome* IslandSpeciationStrategy::get_worst_genome() { } } + double IslandSpeciationStrategy::get_best_fitness() { - RNN_Genome* best_genome = get_best_genome(); - if (best_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return best_genome->get_fitness(); - } + RNN_Genome *best_genome = get_best_genome(); + if (best_genome == NULL) return EXAMM_MAX_DOUBLE; + else return best_genome->get_fitness(); } double IslandSpeciationStrategy::get_worst_fitness() { - RNN_Genome* worst_genome = get_worst_genome(); - if (worst_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return worst_genome->get_fitness(); - } + RNN_Genome *worst_genome = get_worst_genome(); + if (worst_genome == NULL) return EXAMM_MAX_DOUBLE; + else return worst_genome->get_fitness(); } bool IslandSpeciationStrategy::islands_full() const { - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { - if (!islands[i]->is_full()) { - return false; - } + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { + if (!islands[i]->is_full()) return false; } return true; } -// this will insert a COPY, original needs to be deleted -// returns 0 if a new global best, < 0 if not inserted, > 0 otherwise +//this will insert a COPY, original needs to be deleted +//returns 0 if a new global best, < 0 if not inserted, > 0 otherwise int32_t IslandSpeciationStrategy::insert_genome(RNN_Genome* genome) { Log::debug("inserting genome!\n"); repopulate(); bool new_global_best = false; if (global_best_genome == NULL) { - // this is the first insert of a genome so it's the global best by default + //this is the first insert of a genome so it's the global best by default global_best_genome = genome->copy(); new_global_best = true; } else if (global_best_genome->get_fitness() > genome->get_fitness()) { - // since we're re-setting this to a copy you need to delete it. + //since we're re-setting this to a copy you need to delete it. delete global_best_genome; global_best_genome = genome->copy(); new_global_best = true; @@ -177,30 +173,23 @@ int32_t IslandSpeciationStrategy::insert_genome(RNN_Genome* genome) { Log::info("Island %d: inserting genome\n", island); Log::debug("genome weight init type: %s\n", genome->weight_rules->get_weight_initialize_method_name().c_str()); Log::debug("genome weight inherit type: %s\n", genome->weight_rules->get_weight_inheritance_method_name().c_str()); - Log::debug( - "genome mutated component type: %s\n", genome->weight_rules->get_mutated_components_weight_method_name().c_str() - ); + Log::debug("genome mutated component type: %s\n", genome->weight_rules->get_mutated_components_weight_method_name().c_str()); int32_t insert_position = islands[island]->insert_genome(genome); if (insert_position == 0) { - if (new_global_best) { - return 0; - } else { - return 1; - } + if (new_global_best) return 0; + else return 1; } else { - return insert_position; // will be -1 if not inserted, or > 0 if not the global best + return insert_position; //will be -1 if not inserted, or > 0 if not the global best } } int32_t IslandSpeciationStrategy::get_worst_island_by_best_genome() { int32_t worst_island = -1; double worst_best_fitness = 0; - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { if (islands[i]->size() > 0) { - if (islands[i]->get_erase_again_num() > 0) { - continue; - } + if (islands[i]->get_erase_again_num() > 0) continue; double island_best_fitness = islands[i]->get_best_fitness(); if (island_best_fitness > worst_best_fitness) { worst_best_fitness = island_best_fitness; @@ -213,20 +202,18 @@ int32_t IslandSpeciationStrategy::get_worst_island_by_best_genome() { void IslandSpeciationStrategy::repopulate() { if (extinction_event_generation_number != 0) { - if (evaluated_genomes > 1 && evaluated_genomes % extinction_event_generation_number == 0 - && max_genomes - evaluated_genomes >= extinction_event_generation_number) { - if (island_ranking_method.compare("EraseWorst") == 0 || island_ranking_method.compare("") == 0) { + if(evaluated_genomes > 1 && evaluated_genomes % extinction_event_generation_number == 0 && max_genomes - evaluated_genomes >= extinction_event_generation_number) { + if (island_ranking_method.compare("EraseWorst") == 0 || island_ranking_method.compare("") == 0){ global_best_genome = get_best_genome()->copy(); vector rank = rank_islands(); - for (int32_t i = 0; i < islands_to_exterminate; i++) { - if (rank[i] >= 0) { - Log::info("found island: %d is the worst island \n", rank[0]); + for (int32_t i = 0; i < islands_to_exterminate; i++){ + if (rank[i] >= 0){ + Log::info("found island: %d is the worst island \n",rank[0]); islands[rank[i]]->erase_island(); islands[rank[i]]->erase_structure_map(); islands[rank[i]]->set_status(Island::REPOPULATING); - } else { - Log::error("Didn't find the worst island!"); } + else Log::error("Didn't find the worst island!"); // set this so the island would not be re-killed in 5 rounds if (!repeat_extinction) { set_erased_islands_status(); @@ -242,40 +229,38 @@ vector IslandSpeciationStrategy::rank_islands() { int32_t temp; double fitness_j1, fitness_j2; Log::info("ranking islands \n"); - Log::info("repeat extinction: %s \n", repeat_extinction ? "true" : "false"); - for (int32_t i = 0; i < number_of_islands; i++) { + Log::info("repeat extinction: %s \n", repeat_extinction? "true":"false"); + for (int32_t i = 0; i< number_of_islands; i++){ if (repeat_extinction) { island_rank.push_back(i); } else { - if (islands[i]->get_erase_again_num() == 0) { + if (islands[i] -> get_erase_again_num() == 0) { island_rank.push_back(i); } } } - for (int32_t i = 0; i < (int32_t) island_rank.size() - 1; i++) { - for (int32_t j = 0; j < (int32_t) island_rank.size() - i - 1; j++) { + for (int32_t i = 0; i < (int32_t)island_rank.size() - 1; i++) { + for (int32_t j = 0; j < (int32_t)island_rank.size() - i - 1; j++) { fitness_j1 = islands[island_rank[j]]->get_best_fitness(); - fitness_j2 = islands[island_rank[j + 1]]->get_best_fitness(); + fitness_j2 = islands[island_rank[j+1]]->get_best_fitness(); if (fitness_j1 < fitness_j2) { temp = island_rank[j]; - island_rank[j] = island_rank[j + 1]; - island_rank[j + 1] = temp; + island_rank[j] = island_rank[j+1]; + island_rank[j+1]= temp; } } } Log::debug("island rank: \n"); - for (int32_t i = 0; i < (int32_t) island_rank.size(); i++) { + for (int32_t i = 0; i< (int32_t)island_rank.size(); i++){ Log::debug("island: %d fitness %f \n", island_rank[i], islands[island_rank[i]]->get_best_fitness()); } return island_rank; } -RNN_Genome* IslandSpeciationStrategy::generate_for_initializing_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate -) { - Island* current_island = islands[generation_island]; - RNN_Genome* new_genome = NULL; +RNN_Genome* IslandSpeciationStrategy::generate_for_initializing_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate) { + Island *current_island = islands[generation_island]; + RNN_Genome *new_genome = NULL; if (current_island->size() == 0) { Log::info("Island %d: starting island with minimal genome\n", generation_island); new_genome = seed_genome->copy(); @@ -285,9 +270,7 @@ RNN_Genome* IslandSpeciationStrategy::generate_for_initializing_island( if (stir_seed_genome) { Log::info("Stir the seed genome with %d mutations\n", seed_stirs); mutate(seed_stirs, new_genome); - if (!tl_epigenetic_weights) { - new_genome->initialize_randomly(); - } + if (!tl_epigenetic_weights) new_genome->initialize_randomly(); } } else { Log::info("Island %d: island is initializing but not empty, mutating a random genome\n", generation_island); @@ -295,7 +278,7 @@ RNN_Genome* IslandSpeciationStrategy::generate_for_initializing_island( current_island->copy_random_genome(rng_0_1, generator, &new_genome); mutate(num_mutations, new_genome); if (new_genome->outputs_unreachable()) { - // no path from at least one input to the outputs + //no path from at least one input to the outputs delete new_genome; new_genome = NULL; } @@ -307,42 +290,30 @@ RNN_Genome* IslandSpeciationStrategy::generate_for_initializing_island( return new_genome; } -RNN_Genome* IslandSpeciationStrategy::generate_for_repopulating_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate, - function& crossover -) { +RNN_Genome* IslandSpeciationStrategy::generate_for_repopulating_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover) { Log::info("Island %d: island is repopulating \n", generation_island); // Island *current_island = islands[generation_island]; - RNN_Genome* new_genome = NULL; + RNN_Genome *new_genome = NULL; - if (repopulation_method.compare("randomParents") == 0 || repopulation_method.compare("randomparents") == 0) { + if (repopulation_method.compare("randomParents") == 0 || repopulation_method.compare("randomparents") == 0){ Log::info("Island %d: island is repopulating through random parents method!\n", generation_island); new_genome = parents_repopulation("randomParents", rng_0_1, generator, mutate, crossover); - } else if (repopulation_method.compare("bestParents") == 0 || repopulation_method.compare("bestparents") == 0) { + } else if (repopulation_method.compare("bestParents") == 0 || repopulation_method.compare("bestparents") == 0){ Log::info("Island %d: island is repopulating through best parents method!\n", generation_island); new_genome = parents_repopulation("bestParents", rng_0_1, generator, mutate, crossover); - } else if (repopulation_method.compare("bestGenome") == 0 || repopulation_method.compare("bestgenome") == 0) { + } else if (repopulation_method.compare("bestGenome") == 0 || repopulation_method.compare("bestgenome") == 0){ new_genome = get_global_best_genome()->copy(); mutate(num_mutations, new_genome); - } else if (repopulation_method.compare("bestIsland") == 0 || repopulation_method.compare("bestisland") == 0) { - // copy the best island to the worst at once - Log::info( - "Island %d: island is repopulating through bestIsland method! Coping the best island to the population " - "island\n", - generation_island - ); - Log::info( - "Island %d: island current size is: %d \n", generation_island, - islands[generation_island]->get_genomes().size() - ); + } else if (repopulation_method.compare("bestIsland") == 0 || repopulation_method.compare("bestisland") == 0){ + //copy the best island to the worst at once + Log::info("Island %d: island is repopulating through bestIsland method! Coping the best island to the population island\n", generation_island); + Log::info("Island %d: island current size is: %d \n", generation_island, islands[generation_island]->get_genomes().size()); int32_t best_island_id = get_best_genome()->get_group_id(); repopulate_by_copy_island(best_island_id, mutate); - if (new_genome == NULL) { - new_genome = generate_for_filled_island(rng_0_1, generator, mutate, crossover); - } + if (new_genome == NULL) new_genome = generate_for_filled_island(rng_0_1, generator, mutate, crossover); } else { Log::fatal("Wrong repopulation method: %s\n", repopulation_method.c_str()); exit(1); @@ -350,16 +321,14 @@ RNN_Genome* IslandSpeciationStrategy::generate_for_repopulating_island( return new_genome; } -RNN_Genome* IslandSpeciationStrategy::generate_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate, - function& crossover -) { + +RNN_Genome* IslandSpeciationStrategy::generate_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover) { Log::debug("getting island: %d\n", generation_island); - Island* current_island = islands[generation_island]; - RNN_Genome* new_genome = NULL; + Island *current_island = islands[generation_island]; + RNN_Genome *new_genome = NULL; if (current_island->is_initializing()) { - // islands could start with full of mutated seed genomes, it can be used with or without transfer learning + //islands could start with full of mutated seed genomes, it can be used with or without transfer learning new_genome = generate_for_initializing_island(rng_0_1, generator, mutate); } else if (current_island->is_full()) { new_genome = generate_for_filled_island(rng_0_1, generator, mutate, crossover); @@ -376,25 +345,20 @@ RNN_Genome* IslandSpeciationStrategy::generate_genome( new_genome->set_group_id(generation_island); if (current_island->is_initializing()) { - RNN_Genome* genome_copy = new_genome->copy(); + RNN_Genome *genome_copy = new_genome->copy(); Log::debug("inserting genome copy!\n"); insert_genome(genome_copy); } generation_island++; - if (generation_island >= (int32_t) islands.size()) { - generation_island = 0; - } + if (generation_island >= (int32_t)islands.size()) generation_island = 0; return new_genome; } -RNN_Genome* IslandSpeciationStrategy::generate_for_filled_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate, - function& crossover -) { - // if we haven't filled ALL of the island populations yet, only use mutation - // otherwise do mutation at %, crossover at %, and island crossover at % - Island* island = islands[generation_island]; +RNN_Genome* IslandSpeciationStrategy::generate_for_filled_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover){ + //if we haven't filled ALL of the island populations yet, only use mutation + //otherwise do mutation at %, crossover at %, and island crossover at % + Island *island = islands[generation_island]; RNN_Genome* genome; double r = rng_0_1(generator); if (!islands_full() || r < mutation_rate) { @@ -403,48 +367,47 @@ RNN_Genome* IslandSpeciationStrategy::generate_for_filled_island( mutate(num_mutations, genome); } else if (r < intra_island_crossover_rate || number_of_islands == 1) { - // intra-island crossover + //intra-island crossover Log::debug("performing intra-island crossover\n"); - // select two distinct parent genomes in the same island + //select two distinct parent genomes in the same island RNN_Genome *parent1 = NULL, *parent2 = NULL; island->copy_two_random_genomes(rng_0_1, generator, &parent1, &parent2); genome = crossover(parent1, parent2); delete parent1; delete parent2; } else { - // get a random genome from this island - RNN_Genome* parent1 = NULL; + //get a random genome from this island + RNN_Genome *parent1 = NULL; island->copy_random_genome(rng_0_1, generator, &parent1); - // select a different island randomly + //select a different island randomly int32_t other_island = rng_0_1(generator) * (number_of_islands - 1); - if (other_island >= generation_island) { - other_island++; - } - // get the best genome from the other island - RNN_Genome* parent2 = islands[other_island]->get_best_genome()->copy(); // new RNN GENOME - // swap so the first parent is the more fit parent + if (other_island >= generation_island) other_island++; + //get the best genome from the other island + RNN_Genome *parent2 = islands[other_island]->get_best_genome()->copy(); // new RNN GENOME + //swap so the first parent is the more fit parent if (parent1->get_fitness() > parent2->get_fitness()) { - RNN_Genome* tmp = parent1; + RNN_Genome *tmp = parent1; parent1 = parent2; parent2 = tmp; } - genome = crossover(parent1, parent2); // new RNN GENOME + genome = crossover(parent1, parent2); // new RNN GENOME delete parent1; delete parent2; } if (genome->outputs_unreachable()) { - // no path from at least one input to the outputs + //no path from at least one input to the outputs delete genome; genome = NULL; } return genome; } + void IslandSpeciationStrategy::print(string indent) const { Log::trace("%sIslands: \n", indent.c_str()); - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { Log::trace("%sIsland %d:\n", indent.c_str(), i); islands[i]->print(indent + "\t"); } @@ -455,7 +418,7 @@ void IslandSpeciationStrategy::print(string indent) const { */ string IslandSpeciationStrategy::get_strategy_information_headers() const { string info_header = ""; - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { info_header.append(","); info_header.append("Island_"); info_header.append(to_string(i)); @@ -472,8 +435,8 @@ string IslandSpeciationStrategy::get_strategy_information_headers() const { * Gets speciation strategy information values for logs */ string IslandSpeciationStrategy::get_strategy_information_values() const { - string info_value = ""; - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { + string info_value=""; + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { double best_fitness = islands[i]->get_best_fitness(); double worst_fitness = islands[i]->get_worst_fitness(); info_value.append(","); @@ -484,10 +447,7 @@ string IslandSpeciationStrategy::get_strategy_information_values() const { return info_value; } -RNN_Genome* IslandSpeciationStrategy::parents_repopulation( - string method, uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover -) { +RNN_Genome* IslandSpeciationStrategy::parents_repopulation(string method, uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover){ RNN_Genome* genome = NULL; Log::debug("generation island: %d \n", generation_island); @@ -503,8 +463,8 @@ RNN_Genome* IslandSpeciationStrategy::parents_repopulation( } while (parent_island2 == generation_island || parent_island2 == parent_island1); Log::debug("parent island 2: %d \n", parent_island2); - RNN_Genome* parent1 = NULL; - RNN_Genome* parent2 = NULL; + RNN_Genome *parent1 = NULL; + RNN_Genome *parent2 = NULL; while (parent1 == NULL) { if (method.compare("randomParents") == 0) { @@ -519,17 +479,14 @@ RNN_Genome* IslandSpeciationStrategy::parents_repopulation( islands[parent_island2]->copy_random_genome(rng_0_1, generator, &parent2); } else if (method.compare("bestParents") == 0) { parent2 = islands[parent_island2]->get_best_genome(); - } + } } - Log::debug( - "current island is %d, the parent1 island is %d, parent 2 island is %d\n", generation_island, parent_island1, - parent_island2 - ); + Log::debug("current island is %d, the parent1 island is %d, parent 2 island is %d\n", generation_island, parent_island1, parent_island2); - // swap so the first parent is the more fit parent + //swap so the first parent is the more fit parent if (parent1->get_fitness() > parent2->get_fitness()) { - RNN_Genome* tmp = parent1; + RNN_Genome *tmp = parent1; parent1 = parent2; parent2 = tmp; } @@ -538,20 +495,18 @@ RNN_Genome* IslandSpeciationStrategy::parents_repopulation( mutate(num_mutations, genome); if (genome->outputs_unreachable()) { - // no path from at least one input to the outputs - delete genome; + //no path from at least one input to the outputs + delete genome; genome = generate_genome(rng_0_1, generator, mutate, crossover); } return genome; } -void IslandSpeciationStrategy::repopulate_by_copy_island( - int32_t best_island_id, function& mutate -) { - vector best_island_genomes = islands[best_island_id]->get_genomes(); - for (int32_t i = 0; i < (int32_t) best_island_genomes.size(); i++) { +void IslandSpeciationStrategy::repopulate_by_copy_island(int32_t best_island_id, function &mutate){ + vectorbest_island_genomes = islands[best_island_id]->get_genomes(); + for (int32_t i = 0; i < (int32_t)best_island_genomes.size(); i++){ // copy the genome from the best island - RNN_Genome* copy = best_island_genomes[i]->copy(); + RNN_Genome *copy = best_island_genomes[i]->copy(); mutate(num_mutations, copy); generated_genomes++; @@ -567,14 +522,23 @@ RNN_Genome* IslandSpeciationStrategy::get_global_best_genome() { } void IslandSpeciationStrategy::set_erased_islands_status() { - for (int32_t i = 0; i < (int32_t) islands.size(); i++) { - if (islands[i]->get_erase_again_num() > 0) { - islands[i]->set_erase_again_num(); - Log::debug("Island %d can be removed in %d rounds.\n", i, islands[i]->get_erase_again_num()); + for (int32_t i = 0; i < (int32_t)islands.size(); i++) { + if (islands[i] -> get_erase_again_num() > 0) { + islands[i] -> set_erase_again_num(); + Log::debug("Island %d can be removed in %d rounds.\n", i, islands[i] -> get_erase_again_num()); } } } RNN_Genome* IslandSpeciationStrategy::get_seed_genome() { return seed_genome; +} + +//SHO SY +int32_t IslandSpeciationStrategy::get_islands_size() const { + return islands.size(); +} + +Island* IslandSpeciationStrategy::get_island_at_index(int32_t index) const { + return islands[index]; } \ No newline at end of file diff --git a/examm/island_speciation_strategy.hxx b/examm/island_speciation_strategy.hxx index 0eed891c..d15113fb 100644 --- a/examm/island_speciation_strategy.hxx +++ b/examm/island_speciation_strategy.hxx @@ -8,6 +8,7 @@ using std::function; using std::minstd_rand0; using std::uniform_real_distribution; + #include using std::string; @@ -16,221 +17,213 @@ using std::string; #include "speciation_strategy.hxx" class IslandSpeciationStrategy : public SpeciationStrategy { - private: - int32_t generation_island; /**< Used to track which island to generate the next genome from. */ - int32_t number_of_islands; /**< the number of islands to have. */ - int32_t max_island_size; /**< the maximum number of genomes in an island. */ - - double mutation_rate; /**< How frequently to do mutations. Note that mutation_rate + intra_island_crossover_rate + - inter_island_crossover_rate should equal 1, if not they will be scaled down such that they - do. */ - double intra_island_crossover_rate; /**< How frequently to do intra-island crossovers. Note that mutation_rate + - intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if - not they will be scaled down such that they do. */ - double inter_island_crossover_rate; /**< How frequently to do inter-island crossovers. Note that mutation_rate + - intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if - not they will be scaled down such that they do. */ - - int32_t generated_genomes; /**< How many genomes have been generated by this speciation strategy. */ - int32_t evaluated_genomes; /**< How many genomes have been inserted into this speciatoin strategy. */ - - RNN_Genome* seed_genome; /**< keep a reference to the seed genome so we can re-use it across islands and not - duplicate innovation numbers. */ - - string island_ranking_method; /**< The method used to find the worst island in population */ - - string repopulation_method; /**< The method used to repopulate the island after being erased */ - - int32_t extinction_event_generation_number; /**< When EXAMM reaches this generation id, an extinction event will be - triggered (i.e. islands will be killed and repopulated). */ - int32_t num_mutations; /**< When an island is erradicated, it is repopulated with copies of the best genome that - have this number of mutations applied to them. */ - int32_t islands_to_exterminate; /**< When an extinction event is triggered, this is the number of islands that will - be exterminated. */ - int32_t max_genomes; - - bool repeat_extinction; - bool start_filled; - - // bool seed_genome_was_minimal; /**< is true if we passed in a minimal genome (i.e., are not using transfer - // learning) */ - - // int32_t worst_island; - /** - * All the islands which contain the genomes for this speciation strategy. - */ - vector islands; - RNN_Genome* global_best_genome; - - // Transfer learning class properties: - - bool transfer_learning; - string transfer_learning_version; - int32_t seed_stirs; - bool tl_epigenetic_weights; - - public: - // static void register_command_line_arguments(); - // static IslandSpeciationStrategy* generate_from_command_line(); - - /** - * Creates a new IslandSpeciationStrategy. - * - * \param number_of_islands specifies how many islands it will us e - * \param max_island_size specifies the maximum number of gneomes in an island - */ - IslandSpeciationStrategy( - int32_t _number_of_islands, int32_t _max_island_size, double _mutation_rate, - double _intra_island_crossover_rate, double _inter_island_crossover_rate, RNN_Genome* _seed_genome, - string _island_ranking_method, string _repopulation_method, int32_t _extinction_event_generation_number, - int32_t _num_mutations, int32_t _islands_to_exterminate, int32_t _max_genomes, bool _repeat_extinction, - bool _start_filled, bool _transfer_learning, string _transfer_learning_version, int32_t _seed_stirs, - bool _tl_epigenetic_weights - ); - - // /** - // * Transfer learning constructor. - // * \param Modification function to be applied to every copy of the seed_genome - // */ - // IslandSpeciationStrategy(int32_t _number_of_islands, int32_t _max_island_size, - // double _mutation_rate, double _intra_island_crossover_rate, - // double _inter_island_crossover_rate, RNN_Genome *_seed_genome, - // string _island_ranking_method, string _repopulation_method, - // int32_t _extinction_event_generation_number, int32_t _num_mutations, - // int32_t _islands_to_exterminate, bool seed_genome_was_minimal, function &modify); - - /** - * \return the number of generated genomes. - */ - int32_t get_generated_genomes() const; - - /** - * \return the number of inserted genomes. - */ - int32_t get_evaluated_genomes() const; - - /** - * Gets the fitness of the best genome of all the islands - * \return the best fitness over all islands - */ - double get_best_fitness(); - - /** - * Gets the fitness of the worst genome of all the islands - * \return the worst fitness over all islands - */ - double get_worst_fitness(); - - /** - * Gets the best genome of all the islands - * \return the best genome of all islands or NULL if no genomes have yet been inserted - */ - RNN_Genome* get_best_genome(); - - /** - * Gets the the worst genome of all the islands - * \return the worst genome of all islands or NULL if no genomes have yet been inserted - */ - RNN_Genome* get_worst_genome(); - - /** - * \return true if all the islands are full - */ - bool islands_full() const; - - /** - * Inserts a copy of the genome into one of the islands handled by this - * strategy, determined by the RNN_Genome::get_group_id() method. - * - * The caller of this method will need to free the memory of the genome passed - * into this method. - * - * \param genome is the genome to insert. - * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome - * for all the islands, or > 0 otherwise. - */ - int32_t insert_genome(RNN_Genome* genome); - - /** - * find the worst island in the population, the worst island's best genome is the worst among all the islands - * - * \return the worst island id - */ - int32_t get_worst_island_by_best_genome(); - - /** - * rank the islands by their best fitness, the fitness of ranked islands are in descending order - * - * \return island rank from worst to the best - */ - vector rank_islands(); - - /** - * Generates a new genome. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param mutate is the a function which performs a - * mutation on a genome \param crossover is the function which performs crossover between two genomes - * - * \return the newly generated genome. - */ - RNN_Genome* generate_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - - RNN_Genome* generate_for_filled_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - RNN_Genome* generate_for_initializing_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate - ); - RNN_Genome* generate_for_repopulating_island( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - /** - * Prints out all the island's populations - * - * \param indent is how much to indent what is printed out - */ - void print(string indent = "") const; - - /** - * Gets speciation strategy information headers for logs - */ - string get_strategy_information_headers() const; - - /** - * Gets speciation strategy information values for logs - */ - string get_strategy_information_values() const; - - /** - * Island repopulation through two random parents from two seperate islands, - * parents can be random genomes or best genome from the island - */ - RNN_Genome* parents_repopulation( - string method, uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - - /** - * fill a island with the best island. - * \param best_island is the island id of the best island - * \param fill_island is the island is of the island to be filled - */ - void repopulate_by_copy_island(int32_t best_island, function& mutate); - - RNN_Genome* get_global_best_genome(); - RNN_Genome* get_seed_genome(); - - void set_erased_islands_status(); - void initialize_population(function& mutate); - void repopulate(); + private: + int32_t generation_island; /**< Used to track which island to generate the next genome from. */ + int32_t number_of_islands; /**< the number of islands to have. */ + int32_t max_island_size; /**< the maximum number of genomes in an island. */ + + double mutation_rate; /**< How frequently to do mutations. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + double intra_island_crossover_rate; /**< How frequently to do intra-island crossovers. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + double inter_island_crossover_rate; /**< How frequently to do inter-island crossovers. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + + int32_t generated_genomes; /**< How many genomes have been generated by this speciation strategy. */ + int32_t evaluated_genomes; /**< How many genomes have been inserted into this speciatoin strategy. */ + + RNN_Genome *seed_genome; /**< keep a reference to the seed genome so we can re-use it across islands and not duplicate innovation numbers. */ + + string island_ranking_method; /**< The method used to find the worst island in population */ + + string repopulation_method; /**< The method used to repopulate the island after being erased */ + + int32_t extinction_event_generation_number; /**< When EXAMM reaches this generation id, an extinction event will be triggered (i.e. islands will be killed and repopulated). */ + int32_t num_mutations; /**< When an island is erradicated, it is repopulated with copies of the best genome that have this number of mutations applied to them. */ + int32_t islands_to_exterminate; /**< When an extinction event is triggered, this is the number of islands that will be exterminated. */ + int32_t max_genomes; + + bool repeat_extinction; + bool start_filled; + + // bool seed_genome_was_minimal; /**< is true if we passed in a minimal genome (i.e., are not using transfer learning) */ + + // int32_t worst_island; + /** + * All the islands which contain the genomes for this speciation strategy. + */ + vector islands; + RNN_Genome* global_best_genome; + + // Transfer learning class properties: + + bool transfer_learning; + string transfer_learning_version; + int32_t seed_stirs; + bool tl_epigenetic_weights; + + + public: + //static void register_command_line_arguments(); + //static IslandSpeciationStrategy* generate_from_command_line(); + + /** + * Creates a new IslandSpeciationStrategy. + * + * \param number_of_islands specifies how many islands it will us e + * \param max_island_size specifies the maximum number of gneomes in an island + */ + IslandSpeciationStrategy(int32_t _number_of_islands, int32_t _max_island_size, + double _mutation_rate, double _intra_island_crossover_rate, + double _inter_island_crossover_rate, RNN_Genome *_seed_genome, + string _island_ranking_method, string _repopulation_method, + int32_t _extinction_event_generation_number, int32_t _num_mutations, + int32_t _islands_to_exterminate, int32_t _max_genomes, + bool _repeat_extinction, bool _start_filled, + bool _transfer_learning, string _transfer_learning_version, int32_t _seed_stirs, + bool _tl_epigenetic_weights); + + // /** + // * Transfer learning constructor. + // * \param Modification function to be applied to every copy of the seed_genome + // */ + // IslandSpeciationStrategy(int32_t _number_of_islands, int32_t _max_island_size, + // double _mutation_rate, double _intra_island_crossover_rate, + // double _inter_island_crossover_rate, RNN_Genome *_seed_genome, + // string _island_ranking_method, string _repopulation_method, + // int32_t _extinction_event_generation_number, int32_t _num_mutations, + // int32_t _islands_to_exterminate, bool seed_genome_was_minimal, function &modify); + + /** + * \return the number of generated genomes. + */ + int32_t get_generated_genomes() const; + + /** + * \return the number of inserted genomes. + */ + int32_t get_evaluated_genomes() const; + + /** + * Gets the fitness of the best genome of all the islands + * \return the best fitness over all islands + */ + double get_best_fitness(); + + /** + * Gets the fitness of the worst genome of all the islands + * \return the worst fitness over all islands + */ + double get_worst_fitness(); + + /** + * Gets the best genome of all the islands + * \return the best genome of all islands or NULL if no genomes have yet been inserted + */ + RNN_Genome* get_best_genome(); + + /** + * Gets the the worst genome of all the islands + * \return the worst genome of all islands or NULL if no genomes have yet been inserted + */ + RNN_Genome* get_worst_genome(); + + /** + * \return true if all the islands are full + */ + bool islands_full() const; + + /** + * Inserts a copy of the genome into one of the islands handled by this + * strategy, determined by the RNN_Genome::get_group_id() method. + * + * The caller of this method will need to free the memory of the genome passed + * into this method. + * + * \param genome is the genome to insert. + * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome + * for all the islands, or > 0 otherwise. + */ + int32_t insert_genome(RNN_Genome* genome); + + /** + * find the worst island in the population, the worst island's best genome is the worst among all the islands + * + * \return the worst island id + */ + int32_t get_worst_island_by_best_genome(); + + /** + * rank the islands by their best fitness, the fitness of ranked islands are in descending order + * + * \return island rank from worst to the best + */ + vector rank_islands(); + + /** + * Generates a new genome. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param mutate is the a function which performs a mutation on a genome + * \param crossover is the function which performs crossover between two genomes + * + * \return the newly generated genome. + */ + RNN_Genome* generate_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + + RNN_Genome* generate_for_filled_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + RNN_Genome* generate_for_initializing_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate); + RNN_Genome* generate_for_repopulating_island(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + /** + * Prints out all the island's populations + * + * \param indent is how much to indent what is printed out + */ + void print(string indent = "") const; + + /** + * Gets speciation strategy information headers for logs + */ + string get_strategy_information_headers() const; + + /** + * Gets speciation strategy information values for logs + */ + string get_strategy_information_values() const; + + /** + * Island repopulation through two random parents from two seperate islands, + * parents can be random genomes or best genome from the island + */ + RNN_Genome* parents_repopulation(string method,uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + + /** + * fill a island with the best island. + * \param best_island is the island id of the best island + * \param fill_island is the island is of the island to be filled + */ + void repopulate_by_copy_island(int32_t best_island, function &mutate); + + RNN_Genome* get_global_best_genome(); + RNN_Genome* get_seed_genome(); + + void set_erased_islands_status(); + void initialize_population(function &mutate); + void repopulate(); + + //SHO SY + /** + * Get the number of islands + * + * \return the number of island + */ + int32_t get_islands_size() const; + + /** + * Get the island at a given index + * \param index index of required island + * \return the island at given index + */ + Island* get_island_at_index(int32_t index) const; }; + #endif diff --git a/examm/neat_speciation_strategy.cxx b/examm/neat_speciation_strategy.cxx index 8d5f18ac..84f516e9 100644 --- a/examm/neat_speciation_strategy.cxx +++ b/examm/neat_speciation_strategy.cxx @@ -3,7 +3,7 @@ using std::function; #include -// #include +//#include #include @@ -15,33 +15,35 @@ using std::string; #include -#include "common/log.hxx" #include "examm.hxx" -#include "neat_speciation_strategy.hxx" #include "rnn/rnn_genome.hxx" +#include "neat_speciation_strategy.hxx" + +#include "common/log.hxx" /** * */ NeatSpeciationStrategy::NeatSpeciationStrategy( - double _mutation_rate, double _intra_island_crossover_rate, double _inter_island_crossover_rate, - RNN_Genome* _seed_genome, double _species_threshold, double _fitness_threshold, double _neat_c1, double _neat_c2, - double _neat_c3 -) - : generation_species(0), - species_count(0), - population_not_improving_count(0), - species_threshold(_species_threshold), - fitness_threshold(_fitness_threshold), - neat_c1(_neat_c1), - neat_c2(_neat_c2), - neat_c3(_neat_c3), - mutation_rate(_mutation_rate), - intra_island_crossover_rate(_intra_island_crossover_rate), - inter_island_crossover_rate(_inter_island_crossover_rate), - generated_genomes(0), - evaluated_genomes(0), - seed_genome(_seed_genome) { + double _mutation_rate, double _intra_island_crossover_rate, + double _inter_island_crossover_rate, RNN_Genome *_seed_genome, + double _species_threshold, double _fitness_threshold, + double _neat_c1, double _neat_c2, double _neat_c3) : + generation_species(0), + species_count(0), + population_not_improving_count(0), + species_threshold(_species_threshold), + fitness_threshold(_fitness_threshold), + neat_c1(_neat_c1), + neat_c2(_neat_c2), + neat_c3(_neat_c3), + mutation_rate(_mutation_rate), + intra_island_crossover_rate(_intra_island_crossover_rate), + inter_island_crossover_rate(_inter_island_crossover_rate), + generated_genomes(0), + evaluated_genomes(0), + seed_genome(_seed_genome) { + double rate_sum = mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate; if (rate_sum != 1.0) { mutation_rate = mutation_rate / rate_sum; @@ -54,16 +56,18 @@ NeatSpeciationStrategy::NeatSpeciationStrategy( Log::info("Neat speciation strategy, the species threshold is %f. \n", species_threshold); - // set the generation id for the initial minimal genome + //set the generation id for the initial minimal genome generated_genomes++; seed_genome->set_generation_id(generated_genomes); // set the fitst species with minimal genome Neat_Species.push_back(new Species(species_count)); - Log::info("initialized the first species, current neat species size: %d \n", Neat_Species.size()); + Log::info("initialized the first species, current neat species size: %d \n", Neat_Species.size() ); species_count++; insert_genome(seed_genome); global_best_genome = NULL; + + } int32_t NeatSpeciationStrategy::get_generated_genomes() const { @@ -78,7 +82,7 @@ RNN_Genome* NeatSpeciationStrategy::get_best_genome() { int32_t best_genome_species = -1; double best_fitness = EXAMM_MAX_DOUBLE; - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { if (Neat_Species[i]->size() > 0) { double island_best_fitness = Neat_Species[i]->get_best_fitness(); if (island_best_fitness <= best_fitness) { @@ -88,9 +92,8 @@ RNN_Genome* NeatSpeciationStrategy::get_best_genome() { } } - if (best_genome_species < 0) { - return NULL; - } else { + if (best_genome_species < 0) return NULL; + else { return Neat_Species[best_genome_species]->get_best_genome(); } } @@ -99,7 +102,7 @@ RNN_Genome* NeatSpeciationStrategy::get_worst_genome() { int32_t worst_genome_species = -1; double worst_fitness = -EXAMM_MAX_DOUBLE; - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { if (Neat_Species[i]->size() > 0) { double island_worst_fitness = Neat_Species[i]->get_worst_fitness(); if (island_worst_fitness > worst_fitness) { @@ -116,37 +119,34 @@ RNN_Genome* NeatSpeciationStrategy::get_worst_genome() { } } + double NeatSpeciationStrategy::get_best_fitness() { - RNN_Genome* best_genome = get_best_genome(); - if (best_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return best_genome->get_fitness(); - } + RNN_Genome *best_genome = get_best_genome(); + if (best_genome == NULL) return EXAMM_MAX_DOUBLE; + else return best_genome->get_fitness(); } double NeatSpeciationStrategy::get_worst_fitness() { - RNN_Genome* worst_genome = get_worst_genome(); - if (worst_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return worst_genome->get_fitness(); - } + RNN_Genome *worst_genome = get_worst_genome(); + if (worst_genome == NULL) return EXAMM_MAX_DOUBLE; + else return worst_genome->get_fitness(); } -// this will insert a COPY, original needs to be deleted -// returns 0 if a new global best, < 0 if not inserted, > 0 otherwise + +//this will insert a COPY, original needs to be deleted +//returns 0 if a new global best, < 0 if not inserted, > 0 otherwise int32_t NeatSpeciationStrategy::insert_genome(RNN_Genome* genome) { bool inserted = false; bool erased_population = check_population(); if (!erased_population) { - check_species(); - } else { + check_species(); + } + else { population_not_improving_count = 0; } vector best = genome->get_best_parameters(); - if (best.size() != 0) { + if(best.size() != 0){ genome->set_weights(best); } @@ -163,7 +163,7 @@ int32_t NeatSpeciationStrategy::insert_genome(RNN_Genome* genome) { if (!inserted) { vector species_list = get_random_species_list(); - for (int32_t i = 0; i < (int32_t) species_list.size(); i++) { + for (int32_t i = 0; i < (int32_t)species_list.size(); i++){ Species* random_species = Neat_Species[species_list[i]]; if (random_species == NULL || random_species->size() == 0) { Log::error("random_species is empty\n"); @@ -176,7 +176,7 @@ int32_t NeatSpeciationStrategy::insert_genome(RNN_Genome* genome) { break; } - if (genome_representation == NULL) { + if (genome_representation == NULL){ Log::fatal("the latest genome is null, this should never happen!\n"); } double distance = get_distance(genome_representation, genome); @@ -196,10 +196,8 @@ int32_t NeatSpeciationStrategy::insert_genome(RNN_Genome* genome) { Species* new_species = new Species(species_count); species_count++; Neat_Species.push_back(new_species); - if (species_count != (int32_t) Neat_Species.size()) { - Log::error( - "this should never happen, the species count is not the same as the number of species we have! \n" - ); + if (species_count != (int32_t)Neat_Species.size()){ + Log::error("this should never happen, the species count is not the same as the number of species we have! \n"); Log::error("num of species: %d, and species count is %d \n", Neat_Species.size(), species_count); } insert_position = new_species->insert_genome(genome); @@ -207,46 +205,39 @@ int32_t NeatSpeciationStrategy::insert_genome(RNN_Genome* genome) { } if (insert_position == 0) { - // check and see if the inserted genome has the same fitness as the best fitness - // of all islands + //check and see if the inserted genome has the same fitness as the best fitness + //of all islands double best_fitness = get_best_fitness(); if (genome->get_fitness() == best_fitness) { population_not_improving_count = 0; return 0; - } else { - population_not_improving_count++; + } + else { + population_not_improving_count ++; return 1; - } // was the best for the island but not the global best + } //was the best for the island but not the global best } else { - population_not_improving_count++; - return insert_position; // will be -1 if not inserted, or > 0 if not the global best + population_not_improving_count ++; + return insert_position; //will be -1 if not inserted, or > 0 if not the global best } } -RNN_Genome* NeatSpeciationStrategy::generate_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate, - function& crossover -) { - // generate the genome from the next island in a round - // robin fashion. - RNN_Genome* genome = NULL; - if (generation_species >= (int32_t) Neat_Species.size()) { - generation_species = 0; - } + +RNN_Genome* NeatSpeciationStrategy::generate_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover) { + //generate the genome from the next island in a round + //robin fashion. + RNN_Genome *genome = NULL; + if (generation_species >= (int32_t)Neat_Species.size()) generation_species = 0; Log::debug("getting species: %d\n", generation_species); - Species* currentSpecies = Neat_Species[generation_species]; + Species *currentSpecies = Neat_Species[generation_species]; - function distance_function = [=](RNN_Genome* g1, RNN_Genome* g2) { + function distance_function = + [=](RNN_Genome *g1, RNN_Genome *g2) { return this->get_distance(g1, g2); }; - Log::info( - "generating new genome for species[%d], species_size: %d, mutation_rate: %lf, intra_island_crossover_rate: " - "%lf, inter_island_crossover_rate: %lf\n", - generation_species, currentSpecies->size(), mutation_rate, intra_island_crossover_rate, - inter_island_crossover_rate - ); + Log::info("generating new genome for species[%d], species_size: %d, mutation_rate: %lf, intra_island_crossover_rate: %lf, inter_island_crossover_rate: %lf\n", generation_species, currentSpecies->size(), mutation_rate, intra_island_crossover_rate, inter_island_crossover_rate); if (currentSpecies->size() <= 2) { Log::info("current species has less than 2 genomes, doing mutation!\n"); @@ -257,7 +248,7 @@ RNN_Genome* NeatSpeciationStrategy::generate_genome( mutate(1 /*max_mutations*/, genome); if (genome->outputs_unreachable()) { - // no path from at least one input to the outputs + //no path from at least one input to the outputs delete genome; genome = NULL; } @@ -268,17 +259,15 @@ RNN_Genome* NeatSpeciationStrategy::generate_genome( genome->set_group_id(generation_species); generation_species++; - if (generation_species >= (signed) Neat_Species.size()) { - generation_species = 0; - } + if (generation_species >= (signed) Neat_Species.size()) generation_species = 0; return genome; } } else { - // first eliminate genomes who have low fitness sharing in this species - if (currentSpecies->size() > 10) { - currentSpecies->fitness_sharing_remove(fitness_threshold, distance_function); - } - // generate a genome via crossover or mutation + //first eliminate genomes who have low fitness sharing in this species + if (currentSpecies->size() > 10){ + currentSpecies->fitness_sharing_remove(fitness_threshold, distance_function); + } + //generate a genome via crossover or mutation Log::info("current species size %d, doing mutaion or crossover\n", currentSpecies->size()); Log::info("generating genome with id: %d \n", generated_genomes); while (genome == NULL) { @@ -286,47 +275,44 @@ RNN_Genome* NeatSpeciationStrategy::generate_genome( } } if (genome != NULL) { - // set th generation id and increment generated genomes + //set th generation id and increment generated genomes generated_genomes++; genome->set_generation_id(generated_genomes); genome->set_group_id(generation_species); - // set the island for the genome and increment to the next island + //set the island for the genome and increment to the next island generation_species++; // Neat_Species[generation_species]->set_latest_generation_id(generated_genomes); } else { Log::fatal("ERROR: genome was NULL at the end of generate genome!\n"); - Log::fatal("This should never happen.\n"); + Log::fatal( "This should never happen.\n"); exit(1); } return genome; } -RNN_Genome* NeatSpeciationStrategy::generate_for_species( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, function& mutate, - function& crossover -) { - // if we haven't filled ALL of the island populations yet, only use mutation - // otherwise do mutation at %, crossover at %, and island crossover at % - Species* currentSpecies = Neat_Species[generation_species]; +RNN_Genome* NeatSpeciationStrategy::generate_for_species(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover) { + //if we haven't filled ALL of the island populations yet, only use mutation + //otherwise do mutation at %, crossover at %, and island crossover at % + Species *currentSpecies = Neat_Species[generation_species]; RNN_Genome* genome; double r = rng_0_1(generator); - if (r < mutation_rate) { + if ( r < mutation_rate) { Log::info("performing mutation\n"); currentSpecies->copy_random_genome(rng_0_1, generator, &genome); - // TODO: make max_mutations an IslandSpeciationStrategy option + //TODO: make max_mutations an IslandSpeciationStrategy option mutate(1 /*max_mutations*/, genome); } else if (r < intra_island_crossover_rate || Neat_Species.size() == 1) { - // intra-island crossover + //intra-island crossover Log::info("performing intra-island crossover\n"); - // select two distinct parent genomes in the same island + //select two distinct parent genomes in the same island RNN_Genome *parent1 = NULL, *parent2 = NULL; currentSpecies->copy_two_random_genomes(rng_0_1, generator, &parent1, &parent2); @@ -334,36 +320,34 @@ RNN_Genome* NeatSpeciationStrategy::generate_for_species( delete parent1; delete parent2; } else { - // inter-island crossover - // Log::info("performing inter-island crossover\n"); + //inter-island crossover + // Log::info("performing inter-island crossover\n"); - // get a random genome from this island - RNN_Genome* parent1 = NULL; + //get a random genome from this island + RNN_Genome *parent1 = NULL; currentSpecies->copy_random_genome(rng_0_1, generator, &parent1); - // select a different island randomly + //select a different island randomly int32_t other_island = rng_0_1(generator) * (Neat_Species.size() - 1); - if (other_island >= generation_species) { - other_island++; - } + if (other_island >= generation_species) other_island++; - // get the best genome from the other island - RNN_Genome* parent2 = Neat_Species[other_island]->get_best_genome()->copy(); // new RNN GENOME + //get the best genome from the other island + RNN_Genome *parent2 = Neat_Species[other_island]->get_best_genome()->copy(); // new RNN GENOME - // swap so the first parent is the more fit parent + //swap so the first parent is the more fit parent if (parent1->get_fitness() > parent2->get_fitness()) { - RNN_Genome* tmp = parent1; + RNN_Genome *tmp = parent1; parent1 = parent2; parent2 = tmp; } - genome = crossover(parent1, parent2); // new RNN GENOME + genome = crossover(parent1, parent2); // new RNN GENOME delete parent1; delete parent2; } if (genome->outputs_unreachable()) { - // no path from at least one input to the outputs + //no path from at least one input to the outputs delete genome; genome = NULL; } @@ -372,7 +356,7 @@ RNN_Genome* NeatSpeciationStrategy::generate_for_species( void NeatSpeciationStrategy::print(string indent) const { Log::info("%NEAT Species: \n", indent.c_str()); - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { Log::info("%sSpecies %d:\n", indent.c_str(), i); Neat_Species[i]->print(indent + "\t"); } @@ -382,8 +366,8 @@ void NeatSpeciationStrategy::print(string indent) const { * Gets speciation strategy information headers for logs */ string NeatSpeciationStrategy::get_strategy_information_headers() const { - string info_header = ""; - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + string info_header=""; + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { info_header.append(","); info_header.append("Species_"); info_header.append(to_string(i)); @@ -400,8 +384,8 @@ string NeatSpeciationStrategy::get_strategy_information_headers() const { * Gets speciation strategy information values for logs */ string NeatSpeciationStrategy::get_strategy_information_values() const { - string info_value = ""; - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + string info_value=""; + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { double best_fitness = Neat_Species[i]->get_best_fitness(); // double worst_fitness = Neat_Species[i]->get_worst_fitness(); info_value.append(","); @@ -418,7 +402,7 @@ RNN_Genome* NeatSpeciationStrategy::get_global_best_genome() { vector NeatSpeciationStrategy::get_random_species_list() { vector species_list; - for (int32_t i = 0; i < (int32_t) Neat_Species.size(); i++) { + for (int32_t i = 0; i < (int32_t)Neat_Species.size(); i++) { species_list.push_back(i); } @@ -431,6 +415,7 @@ vector NeatSpeciationStrategy::get_random_species_list() { } double NeatSpeciationStrategy::get_distance(RNN_Genome* g1, RNN_Genome* g2) { + double distance; int32_t E; int32_t D; @@ -438,11 +423,11 @@ double NeatSpeciationStrategy::get_distance(RNN_Genome* g1, RNN_Genome* g2) { // d = c1*E/N + c2*D/N + c3*w vector innovation1 = g1->get_innovation_list(); vector innovation2 = g2->get_innovation_list(); - double weight1 = g1->get_avg_edge_weight(); - double weight2 = g2->get_avg_edge_weight(); + double weight1 = g1-> get_avg_edge_weight(); + double weight2 = g2-> get_avg_edge_weight(); double w = abs(weight1 - weight2); Log::debug("weight difference: %f \n", w); - if (innovation1.size() >= innovation2.size()) { + if (innovation1.size() >= innovation2.size()){ N = innovation1.size(); } else { @@ -459,26 +444,21 @@ double NeatSpeciationStrategy::get_distance(RNN_Genome* g1, RNN_Genome* g2) { std::vector setunion; std::vector intersec; - std::set_union( - innovation1.begin(), innovation1.end(), innovation2.begin(), innovation2.end(), - std::inserter(setunion, setunion.begin()) - ); - std::set_intersection( - innovation1.begin(), innovation1.end(), innovation2.begin(), innovation2.end(), - std::inserter(intersec, intersec.begin()) - ); + std::set_union(innovation1.begin(), innovation1.end(), innovation2.begin(), innovation2.end(), std::inserter(setunion, setunion.begin())); + std::set_intersection(innovation1.begin(), innovation1.end(), innovation2.begin(), innovation2.end(), std::inserter(intersec, intersec.begin())); D = setunion.size() - intersec.size() - E; - distance = neat_c1 * E / N + neat_c2 * D / N + neat_c3 * w; + distance = neat_c1 * E / N + neat_c2 * D / N + neat_c3 * w ; Log::debug("distance is %f \n", distance); return distance; + } -// v1.max > v2.max +//v1.max > v2.max int32_t NeatSpeciationStrategy::get_exceed_number(vector v1, vector v2) { int32_t exceed = 0; - for (auto it = v1.rbegin(); it != v1.rend(); ++it) { - if (*it > v2.back()) { + for (auto it = v1.rbegin(); it != v1.rend(); ++it) { + if(*it > v2.back()){ exceed++; } else { break; @@ -488,21 +468,22 @@ int32_t NeatSpeciationStrategy::get_exceed_number(vector v1, vectorget_best_fitness(); - fitness_j2 = Neat_Species[j + 1]->get_best_fitness(); + fitness_j2 = Neat_Species[j+1]->get_best_fitness(); if (fitness_j1 < fitness_j2) { temp = Neat_Species[j]; - Neat_Species[j] = Neat_Species[j + 1]; - Neat_Species[j + 1] = temp; + Neat_Species[j] = Neat_Species[j+1]; + Neat_Species[j+1]= temp; } } } - for (int32_t i = 0; i < (int32_t) Neat_Species.size() - 1; i++) { + for (int32_t i = 0; i < (int32_t)Neat_Species.size() -1; i++) { Log::error("Neat specis rank: %f \n", Neat_Species[i]->get_best_fitness()); } } @@ -516,38 +497,35 @@ bool NeatSpeciationStrategy::check_population() { Log::error("the population fitness has not been improved for 3000 genomes, start to erasing \n"); rank_species(); - Neat_Species.erase(Neat_Species.begin(), Neat_Species.end() - 2); + Neat_Species.erase(Neat_Species.begin(), Neat_Species.end()-2); if (Neat_Species.size() != 2) { - Log::error( - "It should never happen, the population has %d number of species instead of 2! \n", Neat_Species.size() - ); + Log::error("It should never happen, the population has %d number of species instead of 2! \n", Neat_Species.size()); } - for (int32_t i = 0; i < 2; i++) { - Log::error("species %d size %d\n", i, Neat_Species[i]->size()); - Log::error("species %d fitness %f\n", i, Neat_Species[i]->get_best_fitness()); + for (int32_t i = 0; i < 2; i++){ + Log::error("species %d size %d\n",i, Neat_Species[i]->size() ); + Log::error("species %d fitness %f\n",i, Neat_Species[i]->get_best_fitness() ); Neat_Species[i]->set_species_not_improving_count(0); } Log::error("erase finished!\n"); - Log::error("current number of species: %d \n", Neat_Species.size()); + Log::error ("current number of species: %d \n", Neat_Species.size()); erased = true; } return erased; } void NeatSpeciationStrategy::check_species() { + Log::info("checking speies \n"); auto it = Neat_Species.begin(); while (it != Neat_Species.end()) { if (Neat_Species[it - Neat_Species.begin()]->get_species_not_improving_count() >= 2250) { - Log::error( - "Species at position %d hasn't been improving for 2250 genomes, erasing it \n", - it - Neat_Species.begin() - ); - Log::error("current number of species: %d \n", Neat_Species.size()); + Log::error("Species at position %d hasn't been improving for 2250 genomes, erasing it \n", it - Neat_Species.begin() ); + Log::error ("current number of species: %d \n", Neat_Species.size()); // Neat_Species[Neat_Species.begin() - it]->erase_species(); it = Neat_Species.erase(it); - } else { + } + else { ++it; } } @@ -558,5 +536,19 @@ RNN_Genome* NeatSpeciationStrategy::get_seed_genome() { return seed_genome; } -void NeatSpeciationStrategy::initialize_population(function& mutate) { +void NeatSpeciationStrategy::initialize_population(function &mutate) { + } + +//SHO SY +int32_t NeatSpeciationStrategy::get_islands_size() const { + return 0; +} + +Island* NeatSpeciationStrategy::get_island_at_index(int32_t index) const { + return NULL; +} + +bool NeatSpeciationStrategy::islands_full() const { + return true; +} \ No newline at end of file diff --git a/examm/neat_speciation_strategy.hxx b/examm/neat_speciation_strategy.hxx index 3416de03..d2aaa1ca 100644 --- a/examm/neat_speciation_strategy.hxx +++ b/examm/neat_speciation_strategy.hxx @@ -11,142 +11,150 @@ using std::string; using std::minstd_rand0; using std::uniform_real_distribution; +#include "species.hxx" #include "rnn/rnn_genome.hxx" #include "speciation_strategy.hxx" -#include "species.hxx" class NeatSpeciationStrategy : public SpeciationStrategy { - private: - int32_t generation_species; /**< Used to track which island to generate the next genome from. */ - int32_t species_count; /** < Used to keep track of the number of species generated . */ - int32_t population_not_improving_count; - double species_threshold; - double fitness_threshold; - double neat_c1; - double neat_c2; - double neat_c3; - double mutation_rate; /**< How frequently to do mutations. Note that mutation_rate + intra_island_crossover_rate + - inter_island_crossover_rate should equal 1, if not they will be scaled down such that they - do. */ - double intra_island_crossover_rate; /**< How frequently to do intra-island crossovers. Note that mutation_rate + - intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if - not they will be scaled down such that they do. */ - double inter_island_crossover_rate; /**< How frequently to do inter-island crossovers. Note that mutation_rate + - intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if - not they will be scaled down such that they do. */ - - int32_t generated_genomes; /**< How many genomes have been generated by this speciation strategy. */ - int32_t evaluated_genomes; /**< How many genomes have been inserted into this speciatoin strategy. */ - - RNN_Genome* seed_genome; /**< keep a reference to a minimal genome so we can re-use it across islands and not - duplicate innovation numbers. */ - - vector Neat_Species; - RNN_Genome* global_best_genome; - - public: - NeatSpeciationStrategy( - double _mutation_rate, double _intra_island_crossover_rate, double _inter_island_crossover_rate, - RNN_Genome* _seed_genome, double _species_threshold, double _fitness_threshold, double _neat_c1, - double _neat_c2, double _neat_c3 - ); - /** - * \return the number of generated genomes. - */ - int32_t get_generated_genomes() const; - - /** - * \return the number of inserted genomes. - */ - int32_t get_evaluated_genomes() const; - - /** - * Gets the fitness of the best genome of all the islands - * \return the best fitness over all islands - */ - double get_best_fitness(); - - /** - * Gets the fitness of the worst genome of all the islands - * \return the worst fitness over all islands - */ - double get_worst_fitness(); - - /** - * Gets the best genome of all the islands - * \return the best genome of all islands - */ - RNN_Genome* get_best_genome(); - - /** - * Gets the the worst genome of all the islands - * \return the worst genome of all islands - */ - RNN_Genome* get_worst_genome(); - - /** - * Inserts a copy of the genome into this speciation strategy. - * - * The caller of this method will need to free the memory of the genome passed - * into this method. - * - * \param genome is the genome to insert. - * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome - * or > 0 otherwise. - */ - int32_t insert_genome(RNN_Genome* genome); - - /** - * Generates a new genome. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param mutate is the a function which performs a - * mutation on a genome \param crossover is the function which performs crossover between two genomes - * - * \return the newly generated genome. - */ - RNN_Genome* generate_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - - RNN_Genome* generate_for_species( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ); - - /** - * Prints out all the island's populations - * - * \param indent is how much to indent what is printed out - */ - void print(string indent = "") const; - - /** - * Gets speciation strategy information headers for logs - */ - string get_strategy_information_headers() const; - - /** - * Gets speciation strategy information values for logs - */ - string get_strategy_information_values() const; - - RNN_Genome* get_global_best_genome(); - - vector get_random_species_list(); - - double get_distance(RNN_Genome* g1, RNN_Genome* g2); - - int32_t get_exceed_number(vector v1, vector v2); - - void rank_species(); - - bool check_population(); - - void check_species(); - void initialize_population(function& mutate); - RNN_Genome* get_seed_genome(); + private: + int32_t generation_species; /**< Used to track which island to generate the next genome from. */ + int32_t species_count; /** < Used to keep track of the number of species generated . */ + int32_t population_not_improving_count; + double species_threshold; + double fitness_threshold; + double neat_c1; + double neat_c2; + double neat_c3; + double mutation_rate; /**< How frequently to do mutations. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + double intra_island_crossover_rate; /**< How frequently to do intra-island crossovers. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + double inter_island_crossover_rate; /**< How frequently to do inter-island crossovers. Note that mutation_rate + intra_island_crossover_rate + inter_island_crossover_rate should equal 1, if not they will be scaled down such that they do. */ + + int32_t generated_genomes; /**< How many genomes have been generated by this speciation strategy. */ + int32_t evaluated_genomes; /**< How many genomes have been inserted into this speciatoin strategy. */ + + RNN_Genome *seed_genome; /**< keep a reference to a minimal genome so we can re-use it across islands and not duplicate innovation numbers. */ + + vector Neat_Species; + RNN_Genome* global_best_genome; + public: + + NeatSpeciationStrategy( double _mutation_rate, double _intra_island_crossover_rate, + double _inter_island_crossover_rate, RNN_Genome *_seed_genome, + double _species_threshold, double _fitness_threshold, + double _neat_c1, double _neat_c2, double _neat_c3); + /** + * \return the number of generated genomes. + */ + int32_t get_generated_genomes() const; + + /** + * \return the number of inserted genomes. + */ + int32_t get_evaluated_genomes() const; + + /** + * Gets the fitness of the best genome of all the islands + * \return the best fitness over all islands + */ + double get_best_fitness(); + + /** + * Gets the fitness of the worst genome of all the islands + * \return the worst fitness over all islands + */ + double get_worst_fitness(); + + /** + * Gets the best genome of all the islands + * \return the best genome of all islands + */ + RNN_Genome* get_best_genome(); + + /** + * Gets the the worst genome of all the islands + * \return the worst genome of all islands + */ + RNN_Genome* get_worst_genome(); + + /** + * Inserts a copy of the genome into this speciation strategy. + * + * The caller of this method will need to free the memory of the genome passed + * into this method. + * + * \param genome is the genome to insert. + * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome + * or > 0 otherwise. + */ + int32_t insert_genome(RNN_Genome* genome); + + /** + * Generates a new genome. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param mutate is the a function which performs a mutation on a genome + * \param crossover is the function which performs crossover between two genomes + * + * \return the newly generated genome. + */ + RNN_Genome* generate_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + + RNN_Genome* generate_for_species(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover); + + /** + * Prints out all the island's populations + * + * \param indent is how much to indent what is printed out + */ + void print(string indent = "") const; + + /** + * Gets speciation strategy information headers for logs + */ + string get_strategy_information_headers() const; + + /** + * Gets speciation strategy information values for logs + */ + string get_strategy_information_values() const; + + RNN_Genome* get_global_best_genome(); + + vector get_random_species_list(); + + double get_distance(RNN_Genome* g1, RNN_Genome* g2); + + int32_t get_exceed_number(vector v1, vector v2); + + void rank_species(); + + bool check_population(); + + void check_species(); + void initialize_population(function &mutate); + RNN_Genome* get_seed_genome(); + + //SHO SY + /** + * \return true if all the islands are full + */ + bool islands_full() const; + + /** + * Get the number of islands + * + * \return the number of island + */ + int32_t get_islands_size() const; + + /** + * Get the island at a given index + * \param index index of required island + * \return the island at given index + */ + Island* get_island_at_index(int32_t index) const; + }; #endif diff --git a/examm/speciation_strategy.hxx b/examm/speciation_strategy.hxx index 9d790ab0..3838aa20 100644 --- a/examm/speciation_strategy.hxx +++ b/examm/speciation_strategy.hxx @@ -9,88 +9,95 @@ using std::string; using std::minstd_rand0; using std::uniform_real_distribution; +#include "island.hxx" + class SpeciationStrategy { - public: - /** - * \return the number of generated genomes. - */ - virtual int32_t get_generated_genomes() const = 0; - - /** - * \return the number of inserted genomes. - */ - virtual int32_t get_evaluated_genomes() const = 0; - - /** - * Gets the fitness of the best genome of all the islands - * \return the best fitness over all islands - */ - virtual double get_best_fitness() = 0; - - /** - * Gets the fitness of the worst genome of all the islands - * \return the worst fitness over all islands - */ - virtual double get_worst_fitness() = 0; - - /** - * Gets the best genome of all the islands - * \return the best genome of all islands - */ - virtual RNN_Genome* get_best_genome() = 0; - - /** - * Gets the the worst genome of all the islands - * \return the worst genome of all islands - */ - virtual RNN_Genome* get_worst_genome() = 0; - - /** - * Inserts a copy of the genome into this speciation strategy. - * - * The caller of this method will need to free the memory of the genome passed - * into this method. - * - * \param genome is the genome to insert. - * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome - * or > 0 otherwise. - */ - virtual int32_t insert_genome(RNN_Genome* genome) = 0; - - /** - * Generates a new genome. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param mutate is the a function which performs a - * mutation on a genome \param crossover is the function which performs crossover between two genomes - * - * \return the newly generated genome. - */ - virtual RNN_Genome* generate_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, - function& mutate, function& crossover - ) = 0; - - /** - * Prints out all the island's populations - * - * \param indent is how much to indent what is printed out - */ - virtual void print(string indent = "") const = 0; - - /** - * Gets speciation strategy information headers for logs - */ - virtual string get_strategy_information_headers() const = 0; - - /** - * Gets speciation strategy information values for logs - */ - virtual string get_strategy_information_values() const = 0; - - virtual RNN_Genome* get_global_best_genome() = 0; - virtual void initialize_population(function& mutate) = 0; - virtual RNN_Genome* get_seed_genome() = 0; + + public: + /** + * \return the number of generated genomes. + */ + virtual int32_t get_generated_genomes() const = 0; + + /** + * \return the number of inserted genomes. + */ + virtual int32_t get_evaluated_genomes() const = 0; + + /** + * Gets the fitness of the best genome of all the islands + * \return the best fitness over all islands + */ + virtual double get_best_fitness() = 0; + + /** + * Gets the fitness of the worst genome of all the islands + * \return the worst fitness over all islands + */ + virtual double get_worst_fitness() = 0; + + /** + * Gets the best genome of all the islands + * \return the best genome of all islands + */ + virtual RNN_Genome* get_best_genome() = 0; + + /** + * Gets the the worst genome of all the islands + * \return the worst genome of all islands + */ + virtual RNN_Genome* get_worst_genome() = 0; + + /** + * Inserts a copy of the genome into this speciation strategy. + * + * The caller of this method will need to free the memory of the genome passed + * into this method. + * + * \param genome is the genome to insert. + * \return a value < 0 if the genome was not inserted, 0 if it was a new best genome + * or > 0 otherwise. + */ + virtual int32_t insert_genome(RNN_Genome* genome) = 0; + + /** + * Generates a new genome. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param mutate is the a function which performs a mutation on a genome + * \param crossover is the function which performs crossover between two genomes + * + * \return the newly generated genome. + */ + virtual RNN_Genome* generate_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, function &mutate, function &crossover) = 0; + + + /** + * Prints out all the island's populations + * + * \param indent is how much to indent what is printed out + */ + virtual void print(string indent = "") const = 0; + + /** + * Gets speciation strategy information headers for logs + */ + virtual string get_strategy_information_headers() const = 0; + + /** + * Gets speciation strategy information values for logs + */ + virtual string get_strategy_information_values() const = 0; + + virtual RNN_Genome* get_global_best_genome() = 0; + virtual void initialize_population(function &mutate) = 0; + virtual RNN_Genome* get_seed_genome() = 0; + + //SHO SY + virtual bool islands_full() const = 0; + virtual int32_t get_islands_size() const = 0; + virtual Island* get_island_at_index(int32_t index) const = 0; }; #endif diff --git a/examm/species.cxx b/examm/species.cxx index 1e650ec7..57bcf33d 100644 --- a/examm/species.cxx +++ b/examm/species.cxx @@ -13,62 +13,50 @@ using std::uniform_real_distribution; using std::string; using std::to_string; -#include "common/log.hxx" -#include "rnn/rnn_genome.hxx" #include "species.hxx" -// Species(int32_t id, double fitness_th); +#include "rnn/rnn_genome.hxx" + +#include "common/log.hxx" + // Species(int32_t id, double fitness_th); Species::Species(int32_t _id) : id(_id), species_not_improving_count(0) { } RNN_Genome* Species::get_best_genome() { - if (genomes.size() == 0) { - return NULL; - } else { - return genomes[0]; - } + if (genomes.size() == 0) return NULL; + else return genomes[0]; } RNN_Genome* Species::get_worst_genome() { - if (genomes.size() == 0) { - return NULL; - } else { - return genomes.back(); - } + if (genomes.size() == 0) return NULL; + else return genomes.back(); } -RNN_Genome* Species::get_random_genome(uniform_real_distribution& rng_0_1, minstd_rand0& generator) { - if (genomes.size() == 0) { - return NULL; - } else { +RNN_Genome* Species::get_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator) { + if (genomes.size() == 0) return NULL; + else { int32_t genome_position = size() * rng_0_1(generator); return genomes[genome_position]; } } double Species::get_best_fitness() { - RNN_Genome* best_genome = get_best_genome(); - if (best_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return best_genome->get_fitness(); - } + RNN_Genome *best_genome = get_best_genome(); + if (best_genome == NULL) return EXAMM_MAX_DOUBLE; + else return best_genome->get_fitness(); } double Species::get_worst_fitness() { - RNN_Genome* worst_genome = get_worst_genome(); - if (worst_genome == NULL) { - return EXAMM_MAX_DOUBLE; - } else { - return worst_genome->get_fitness(); - } + RNN_Genome *worst_genome = get_worst_genome(); + if (worst_genome == NULL) return EXAMM_MAX_DOUBLE; + else return worst_genome->get_fitness(); } int32_t Species::size() { - return (int32_t) genomes.size(); + return (int32_t)genomes.size(); } int32_t Species::contains(RNN_Genome* genome) { - for (int32_t j = 0; j < (int32_t) genomes.size(); j++) { + for (int32_t j = 0; j < (int32_t)genomes.size(); j++) { if (genomes[j]->equals(genome)) { return j; } @@ -77,23 +65,18 @@ int32_t Species::contains(RNN_Genome* genome) { return -1; } -void Species::copy_random_genome( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome -) { - int32_t genome_position = size() * rng_0_1(generator); + +void Species::copy_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome) { + int32_t genome_position = size() * rng_0_1(generator); *genome = genomes[genome_position]->copy(); } -void Species::copy_two_random_genomes( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome1, RNN_Genome** genome2 -) { +void Species::copy_two_random_genomes(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome1, RNN_Genome **genome2) { int32_t p1 = size() * rng_0_1(generator); int32_t p2 = (size() - 1) * rng_0_1(generator); - if (p2 >= p1) { - p2++; - } + if (p2 >= p1) p2++; - // swap the gnomes so that the first parent is the more fit parent + //swap the gnomes so that the first parent is the more fit parent if (p1 > p2) { int32_t tmp = p1; p1 = p2; @@ -104,26 +87,25 @@ void Species::copy_two_random_genomes( *genome2 = genomes[p2]->copy(); } -// returns -1 for not inserted, otherwise the index it was inserted at -// inserts a copy of the genome, caller of the function will need to delete their -// pointer -int32_t Species::insert_genome(RNN_Genome* genome) { +//returns -1 for not inserted, otherwise the index it was inserted at +//inserts a copy of the genome, caller of the function will need to delete their +//pointer +int32_t Species::insert_genome(RNN_Genome *genome) { Log::info("inserting genome with fitness: %s to species %d\n", parse_fitness(genome->get_fitness()).c_str(), id); // inorder insert the new individual - RNN_Genome* copy = genome->copy(); + RNN_Genome *copy = genome->copy(); copy->set_generation_id(genome->get_generation_id()); copy->set_group_id(id); vector best = copy->get_best_parameters(); - if (best.size() != 0) { + if(best.size() != 0){ copy->set_weights(copy->get_best_parameters()); } vector copy_weights; copy->get_weights(copy_weights); - auto index_iterator = - genomes.insert(upper_bound(genomes.begin(), genomes.end(), copy, sort_genomes_by_fitness()), copy); - + auto index_iterator = genomes.insert( upper_bound(genomes.begin(), genomes.end(), copy, sort_genomes_by_fitness()), copy); + // calculate the index the genome was inseretd at from the iterator int32_t insert_index = index_iterator - genomes.begin(); @@ -137,11 +119,11 @@ int32_t Species::insert_genome(RNN_Genome* genome) { genome->set_weights(best_parameters); } species_not_improving_count = 0; - } else { - species_not_improving_count++; + } else { + species_not_improving_count ++; } - inserted_genome_id.push_back(copy->get_generation_id()); + inserted_genome_id.push_back( copy->get_generation_id()); Log::info("Inserted genome %d at index %d\n", genome->get_generation_id(), insert_index); return insert_index; @@ -149,25 +131,25 @@ int32_t Species::insert_genome(RNN_Genome* genome) { void Species::print(string indent) { Log::info("%s\t%s\n", indent.c_str(), RNN_Genome::print_statistics_header().c_str()); - for (int32_t i = 0; i < (int32_t) genomes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genomes.size(); i++) { Log::info("%s\t%s\n", indent.c_str(), genomes[i]->print_statistics().c_str()); } } -vector Species::get_genomes() { +vector Species::get_genomes() { return genomes; } RNN_Genome* Species::get_latested_genome() { RNN_Genome* latest = NULL; - for (auto it = inserted_genome_id.rbegin(); it != inserted_genome_id.rend(); ++it) { + for (auto it = inserted_genome_id.rbegin(); it != inserted_genome_id.rend(); ++it){ int32_t latest_id = *it; - for (int32_t i = 0; i < (int32_t) genomes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genomes.size(); i++) { if (genomes[i]->get_generation_id() == latest_id) { latest = genomes[i]; break; } - } + } if (latest) { break; } @@ -175,23 +157,23 @@ RNN_Genome* Species::get_latested_genome() { return latest; } -void Species::fitness_sharing_remove( - double fitness_threshold, function& get_distance -) { - int32_t N = (int32_t) genomes.size(); +void Species::fitness_sharing_remove(double fitness_threshold, function &get_distance) { + int32_t N = (int32_t)genomes.size(); double distance_sum[N]; double fitness_share[N]; double fitness_share_total = 0; double sum_square = 0; - double distance[N][N]; + double distance [N][N]; for (int32_t i = 0; i < N; i++) { distance_sum[i] = 0; for (int32_t j = 0; j < N; j++) { if (i < j) { distance[i][j] = get_distance(genomes[i], genomes[j]); - } else if (i > j) { - distance[i][j] = distance[j][i]; - } else { + } + else if (i > j) { + distance[i][j] = distance[j][i]; + } + else { distance[i][j] = 0; } if (distance[i][j] > fitness_threshold) { @@ -200,29 +182,31 @@ void Species::fitness_sharing_remove( distance_sum[i] += 1; } } - fitness_share[i] = (genomes[i]->get_fitness()) / distance_sum[i]; + fitness_share[i] = (genomes[i] -> get_fitness()) / distance_sum[i]; fitness_share_total += fitness_share[i]; sum_square += fitness_share[i] * fitness_share[i]; } double fitness_share_mean = fitness_share_total / N; - double fitness_share_std = sqrt(sum_square / (N - 1)); + double fitness_share_std = sqrt( sum_square / (N-1) ); double upper_cut_off = fitness_share_mean + fitness_share_std * 3; int32_t i = 0; auto it = genomes.begin(); - while (it != genomes.end()) { - if (fitness_share[i] > upper_cut_off) { - it = genomes.erase(it); - } else { - ++it; - } + while (it != genomes.end()) { + if (fitness_share[i] > upper_cut_off) { + it = genomes.erase(it); + } + else { + ++it; + } i++; - } + } + } void Species::erase_species() { genomes.clear(); - if (genomes.size() != 0) { + if(genomes.size() != 0){ Log::error("The worst island is not fully erased!\n"); } } diff --git a/examm/species.hxx b/examm/species.hxx index 607397cc..f4fb64df 100644 --- a/examm/species.hxx +++ b/examm/species.hxx @@ -19,128 +19,127 @@ using std::string; #include "rnn/rnn_genome.hxx" + class Species { - private: - int32_t id; /**< An integer ID for this species. */ - - // int32_t latest_inserted_generation_id; /**< The latest generation id of genome being generated, including the - // ones doing backprop by workers */ - - vector inserted_genome_id; - /** - * The genomes on this species, stored in sorted order best (front) to worst (back). - */ - vector genomes; - - int32_t species_not_improving_count; - - public: - /** - * Initializes a species. - */ - Species(int32_t id); - - /** - * Returns the fitness of the best genome in the island - * - * \return the best fitness of the island - */ - double get_best_fitness(); - - /** - * Returns the fitness of the worst genome in the island - * - * \return the worst fitness of the island - */ - double get_worst_fitness(); - - /** - * Returns the best genomme in the island. - * - * \return the best genome in the island - */ - RNN_Genome* get_best_genome(); - - /** - * Returns the worst genomme in the island. - * - * \return the worst genome in the island - */ - RNN_Genome* get_worst_genome(); - - /** - * Returns the best genomme in the island. - * - * \return the best genome in the island - */ - RNN_Genome* get_random_genome(uniform_real_distribution& rng_0_1, minstd_rand0& generator); - - /** - * Returns the size of the island - * - * \return the number of genomes in this island. - */ - int32_t size(); - - /** - * Checks to see if a genome already exists in the island, using - * the RNN_Genome::equals method (which checks to see if all edges - * and nodes are the same, but not necessarily weights). - * - * \return the index in the island of the duplicate genome, -1 otherwise. - */ - int32_t contains(RNN_Genome* genome); - - /** - * Selects a genome from the island at random and returns a copy of it. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param genome will be the copied genome, an - * addresss to a pointer needs to be passed. - */ - void copy_random_genome(uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome); - - /** - * Selects two different genomes from the island at random and returns copies of them. - * - * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 - * (non=inclusive). \param generator is the random number generator \param genome1 will be the first copied genome, - * an addresss to a pointer needs to be passed. \param genome2 will be the second copied genome, an addresss to a - * pointer needs to be passed. - */ - void copy_two_random_genomes( - uniform_real_distribution& rng_0_1, minstd_rand0& generator, RNN_Genome** genome1, RNN_Genome** genome2 - ); - - /** - * Inserts a genome into the island. - * - * Genomes are inserted in best to worst order genomes[0] will have - * the best fitness and genomes[size - 1] will have the worst. - * - * \param genome is the genome to be inserted. - * \return -1 if not inserted, otherwise the index it was inserted at - */ - int32_t insert_genome(RNN_Genome* genome); - - /** - * Prints out the state of this island. - * - * \param indent is how much to indent what is printed out - */ - void print(string indent = ""); - - vector get_genomes(); - - RNN_Genome* get_latested_genome(); - - void fitness_sharing_remove(double fitness_threshold, function& get_distance); - - void erase_species(); - - int32_t get_species_not_improving_count(); - - void set_species_not_improving_count(int32_t count); + private: + int32_t id; /**< An integer ID for this species. */ + + // int32_t latest_inserted_generation_id; /**< The latest generation id of genome being generated, including the ones doing backprop by workers */ + + vector inserted_genome_id; + /** + * The genomes on this species, stored in sorted order best (front) to worst (back). + */ + vector genomes; + + int32_t species_not_improving_count; + + public: + /** + * Initializes a species. + */ + Species(int32_t id); + + + /** + * Returns the fitness of the best genome in the island + * + * \return the best fitness of the island + */ + double get_best_fitness(); + + /** + * Returns the fitness of the worst genome in the island + * + * \return the worst fitness of the island + */ + double get_worst_fitness(); + + /** + * Returns the best genomme in the island. + * + * \return the best genome in the island + */ + RNN_Genome *get_best_genome(); + + /** + * Returns the worst genomme in the island. + * + * \return the worst genome in the island + */ + RNN_Genome *get_worst_genome(); + + /** + * Returns the best genomme in the island. + * + * \return the best genome in the island + */ + RNN_Genome *get_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator); + + /** + * Returns the size of the island + * + * \return the number of genomes in this island. + */ + int32_t size(); + + /** + * Checks to see if a genome already exists in the island, using + * the RNN_Genome::equals method (which checks to see if all edges + * and nodes are the same, but not necessarily weights). + * + * \return the index in the island of the duplicate genome, -1 otherwise. + */ + int32_t contains(RNN_Genome* genome); + + /** + * Selects a genome from the island at random and returns a copy of it. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param genome will be the copied genome, an addresss to a pointer needs to be passed. + */ + void copy_random_genome(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome); + + /** + * Selects two different genomes from the island at random and returns copies of them. + * + * \param rng_0_1 is the random number distribution that generates random numbers between 0 (inclusive) and 1 (non=inclusive). + * \param generator is the random number generator + * \param genome1 will be the first copied genome, an addresss to a pointer needs to be passed. + * \param genome2 will be the second copied genome, an addresss to a pointer needs to be passed. + */ + void copy_two_random_genomes(uniform_real_distribution &rng_0_1, minstd_rand0 &generator, RNN_Genome **genome1, RNN_Genome **genome2); + + /** + * Inserts a genome into the island. + * + * Genomes are inserted in best to worst order genomes[0] will have + * the best fitness and genomes[size - 1] will have the worst. + * + * \param genome is the genome to be inserted. + * \return -1 if not inserted, otherwise the index it was inserted at + */ + int32_t insert_genome(RNN_Genome* genome); + + /** + * Prints out the state of this island. + * + * \param indent is how much to indent what is printed out + */ + void print(string indent = ""); + + vector get_genomes(); + + RNN_Genome* get_latested_genome(); + + void fitness_sharing_remove(double fitness_threshold, function &get_distance); + + void erase_species(); + + int32_t get_species_not_improving_count(); + + void set_species_not_improving_count(int32_t count); }; #endif diff --git a/mpi/exact_mpi.cxx b/mpi/exact_mpi.cxx index 3c5e1005..77406386 100644 --- a/mpi/exact_mpi.cxx +++ b/mpi/exact_mpi.cxx @@ -1,8 +1,9 @@ #include + #include +using std::setw; using std::fixed; using std::setprecision; -using std::setw; #include using std::cerr; @@ -21,21 +22,24 @@ using std::thread; #include using std::vector; -#include "cnn/exact.hxx" +#include "mpi.h" + #include "common/arguments.hxx" + #include "image_tools/image_set.hxx" -#include "mpi.h" -#define WORK_REQUEST_TAG 1 +#include "cnn/exact.hxx" + +#define WORK_REQUEST_TAG 1 #define GENOME_LENGTH_TAG 2 -#define GENOME_TAG 3 -#define TERMINATE_TAG 4 +#define GENOME_TAG 3 +#define TERMINATE_TAG 4 mutex exact_mutex; vector arguments; -EXACT* exact; +EXACT *exact; bool finished = false; @@ -69,13 +73,13 @@ CNN_Genome* receive_genome_from(string name, int source) { genome_str[length] = '\0'; - // cout << "genome_str:" << endl << genome_str << endl; + //cout << "genome_str:" << endl << genome_str << endl; istringstream iss(genome_str); CNN_Genome* genome = new CNN_Genome(iss, false); - delete[] genome_str; + delete [] genome_str; return genome; } @@ -109,9 +113,7 @@ void receive_terminate_message(int source) { MPI_Recv(terminate_message, 1, MPI_INT, source, TERMINATE_TAG, MPI_COMM_WORLD, &status); } -void master( - const Images& training_images, const Images& validation_images, const Images& testing_images, int max_rank -) { +void master(const Images &training_images, const Images &validation_images, const Images &testing_images, int max_rank) { string name = "master"; cout << "MAX INT: " << numeric_limits::max() << endl; @@ -119,7 +121,7 @@ void master( int terminates_sent = 0; while (true) { - // wait for a incoming message + //wait for a incoming message MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); @@ -127,48 +129,46 @@ void master( int tag = status.MPI_TAG; cout << "[" << setw(10) << name << "] probe returned message from: " << source << " with tag: " << tag << endl; - // if the message is a work request, send a genome + + //if the message is a work request, send a genome if (tag == WORK_REQUEST_TAG) { receive_work_request(source); exact_mutex.lock(); - CNN_Genome* genome = exact->generate_individual(); + CNN_Genome *genome = exact->generate_individual(); exact_mutex.unlock(); - if (genome == NULL) { // search was completed if it returns NULL for an individual - // send terminate message + if (genome == NULL) { //search was completed if it returns NULL for an individual + //send terminate message cout << "[" << setw(10) << name << "] terminating worker: " << source << endl; send_terminate_message(source); terminates_sent++; - cout << "[" << setw(10) << name << "] sent: " << terminates_sent << " terminates of: " << (max_rank - 1) - << endl; - if (terminates_sent >= max_rank - 1) { - return; - } + cout << "[" << setw(10) << name << "] sent: " << terminates_sent << " terminates of: " << (max_rank - 1) << endl; + if (terminates_sent >= max_rank - 1) return; } else { ofstream outfile(exact->get_output_directory() + "/gen_" + to_string(genome->get_generation_id())); genome->write(outfile); outfile.close(); - // send genome + //send genome cout << "[" << setw(10) << name << "] sending genome to: " << source << endl; send_genome_to(name, source, genome); - // delete this genome as it will not be used again + //delete this genome as it will not be used again delete genome; } } else if (tag == GENOME_LENGTH_TAG) { cout << "[" << setw(10) << name << "] received genome from: " << source << endl; - CNN_Genome* genome = receive_genome_from(name, source); + CNN_Genome *genome = receive_genome_from(name, source); exact_mutex.lock(); exact->insert_genome(genome); exact_mutex.unlock(); - // this genome will be deleted if/when removed from population + //this genome will be deleted if/when removed from population } else { cerr << "[" << setw(10) << name << "] ERROR: received message with unknown tag: " << tag << endl; MPI_Abort(MPI_COMM_WORLD, 1); @@ -176,7 +176,7 @@ void master( } } -void worker(const Images& training_images, const Images& validation_images, const Images& testing_images, int rank) { +void worker(const Images &training_images, const Images &validation_images, const Images &testing_images, int rank) { string name = "worker_" + to_string(rank); while (true) { cout << "[" << setw(10) << name << "] sending work request!" << endl; @@ -261,16 +261,11 @@ int main(int argc, char** argv) { get_argument(arguments, "--images_resize", true, images_resize); Images training_images(training_filename, padding); - Images validation_images( - validation_filename, padding, training_images.get_average(), training_images.get_std_dev() - ); + Images validation_images(validation_filename, padding, training_images.get_average(), training_images.get_std_dev()); Images testing_images(testing_filename, padding, training_images.get_average(), training_images.get_std_dev()); if (rank == 0) { - exact = new EXACT( - training_images, validation_images, testing_images, padding, population_size, max_epochs, use_sfmp, - use_node_operations, max_genomes, output_directory, search_name, reset_edges - ); + exact = new EXACT(training_images, validation_images, testing_images, padding, population_size, max_epochs, use_sfmp, use_node_operations, max_genomes, output_directory, search_name, reset_edges); master(training_images, validation_images, testing_images, max_rank); } else { diff --git a/mpi/examm_mpi.cxx b/mpi/examm_mpi.cxx index 7886d91d..3fc66629 100644 --- a/mpi/examm_mpi.cxx +++ b/mpi/examm_mpi.cxx @@ -1,8 +1,9 @@ #include + #include +using std::setw; using std::fixed; using std::setprecision; -using std::setw; #include using std::mutex; @@ -16,33 +17,35 @@ using std::thread; #include using std::vector; +#include "mpi.h" + #include "common/log.hxx" #include "common/process_arguments.hxx" -#include "examm/examm.hxx" -#include "mpi.h" -#include "rnn/generate_nn.hxx" -#include "time_series/time_series.hxx" #include "weights/weight_rules.hxx" #include "weights/weight_update.hxx" +#include "rnn/generate_nn.hxx" +#include "examm/examm.hxx" -#define WORK_REQUEST_TAG 1 +#include "time_series/time_series.hxx" + +#define WORK_REQUEST_TAG 1 #define GENOME_LENGTH_TAG 2 -#define GENOME_TAG 3 -#define TERMINATE_TAG 4 +#define GENOME_TAG 3 +#define TERMINATE_TAG 4 mutex examm_mutex; vector arguments; -EXAMM* examm; -WeightUpdate* weight_update_method; +EXAMM *examm; +WeightUpdate *weight_update_method; bool finished = false; -vector > > training_inputs; -vector > > training_outputs; -vector > > validation_inputs; -vector > > validation_outputs; +vector< vector< vector > > training_inputs; +vector< vector< vector > > training_outputs; +vector< vector< vector > > validation_inputs; +vector< vector< vector > > validation_outputs; // bool random_sequence_length; // int32_t sequence_length_lower_bound = 30; @@ -80,12 +83,12 @@ RNN_Genome* receive_genome_from(int32_t source) { RNN_Genome* genome = new RNN_Genome(genome_str, length); - delete[] genome_str; + delete [] genome_str; return genome; } void send_genome_to(int32_t target, RNN_Genome* genome) { - char* byte_array; + char *byte_array; int32_t length; genome->write_to_array(&byte_array, length); @@ -115,13 +118,13 @@ void receive_terminate_message(int32_t source) { } void master(int32_t max_rank) { - // the "main" id will have already been set by the main function so we do not need to re-set it here + //the "main" id will have already been set by the main function so we do not need to re-set it here Log::debug("MAX int32_t: %d\n", numeric_limits::max()); int32_t terminates_sent = 0; while (true) { - // wait for a incoming message + //wait for a incoming message MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); @@ -129,51 +132,50 @@ void master(int32_t max_rank) { int32_t tag = status.MPI_TAG; Log::debug("probe returned message from: %d with tag: %d\n", source, tag); - // if the message is a work request, send a genome + + //if the message is a work request, send a genome if (tag == WORK_REQUEST_TAG) { receive_work_request(source); + // if (transfer_learning_version.compare("v3") == 0 || transfer_learning_version.compare("v1+v3") == 0) { // seed_stirs = 3; // } examm_mutex.lock(); - RNN_Genome* genome = examm->generate_genome(); + RNN_Genome *genome = examm->generate_genome(); examm_mutex.unlock(); - if (genome == NULL) { // search was completed if it returns NULL for an individual - // send terminate message + if (genome == NULL) { //search was completed if it returns NULL for an individual + //send terminate message Log::info("terminating worker: %d\n", source); send_terminate_message(source); terminates_sent++; Log::debug("sent: %d terminates of %d\n", terminates_sent, (max_rank - 1)); - if (terminates_sent >= max_rank - 1) { - return; - } + if (terminates_sent >= max_rank - 1) return; } else { - // genome->write_to_file( examm->get_output_directory() + "/before_send_gen_" + - // to_string(genome->get_generation_id()) ); + //genome->write_to_file( examm->get_output_directory() + "/before_send_gen_" + to_string(genome->get_generation_id()) ); - // send genome + //send genome Log::debug("sending genome to: %d\n", source); send_genome_to(source, genome); - // delete this genome as it will not be used again + //delete this genome as it will not be used again delete genome; } } else if (tag == GENOME_LENGTH_TAG) { Log::debug("received genome from: %d\n", source); - RNN_Genome* genome = receive_genome_from(source); + RNN_Genome *genome = receive_genome_from(source); examm_mutex.lock(); examm->insert_genome(genome); examm_mutex.unlock(); - // delete the genome as it won't be used again, a copy was inserted + //delete the genome as it won't be used again, a copy was inserted delete genome; - // this genome will be deleted if/when removed from population + //this genome will be deleted if/when removed from population } else { Log::fatal("ERROR: received message from %d with unknown tag: %d", source, tag); MPI_Abort(MPI_COMM_WORLD, 1); @@ -204,15 +206,13 @@ void worker(int32_t rank) { Log::debug("received genome!\n"); RNN_Genome* genome = receive_genome_from(0); - // have each worker write the backproagation to a separate log file + //have each worker write the backproagation to a separate log file string log_id = "genome_" + to_string(genome->get_generation_id()) + "_worker_" + to_string(rank); Log::set_id(log_id); - genome->backpropagate_stochastic( - training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method - ); + genome->backpropagate_stochastic(training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method); Log::release_id(log_id); - // go back to the worker's log for MPI communication + //go back to the worker's log for MPI communication Log::set_id("worker_" + to_string(rank)); send_genome_to(0, genome); @@ -224,7 +224,7 @@ void worker(int32_t rank) { } } - // release the log file for the worker communication + //release the log file for the worker communication Log::release_id("worker_" + to_string(rank)); } @@ -245,19 +245,17 @@ int main(int argc, char** argv) { Log::restrict_to_rank(0); std::cout << "initailized log!" << std::endl; - TimeSeriesSets* time_series_sets = NULL; + TimeSeriesSets *time_series_sets = NULL; time_series_sets = TimeSeriesSets::generate_from_arguments(arguments); - get_train_validation_data( - arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs - ); + get_train_validation_data(arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs); weight_update_method = new WeightUpdate(); weight_update_method->generate_from_arguments(arguments); - WeightRules* weight_rules = new WeightRules(); - weight_rules->initialize_from_args(arguments); + WeightRules *weight_rules = new WeightRules(); + weight_rules->generate_weight_initialize_from_arguments(arguments); - RNN_Genome* seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); + RNN_Genome *seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); Log::clear_rank_restriction(); diff --git a/mpi/examm_mpi_multi.cxx b/mpi/examm_mpi_multi.cxx index 7b64cf5e..1b9d7fb5 100644 --- a/mpi/examm_mpi_multi.cxx +++ b/mpi/examm_mpi_multi.cxx @@ -1,8 +1,9 @@ #include + #include +using std::setw; using std::fixed; using std::setprecision; -using std::setw; #include using std::mutex; @@ -16,33 +17,36 @@ using std::thread; #include using std::vector; + +#include "mpi.h" + #include "common/arguments.hxx" #include "common/files.hxx" #include "common/log.hxx" #include "common/process_arguments.hxx" +#include "weights/weight_update.hxx" + #include "examm/examm.hxx" -#include "mpi.h" #include "rnn/generate_nn.hxx" #include "time_series/time_series.hxx" -#include "weights/weight_update.hxx" -#define WORK_REQUEST_TAG 1 +#define WORK_REQUEST_TAG 1 #define GENOME_LENGTH_TAG 2 -#define GENOME_TAG 3 -#define TERMINATE_TAG 4 +#define GENOME_TAG 3 +#define TERMINATE_TAG 4 mutex examm_mutex; vector arguments; -EXAMM* examm; +EXAMM *examm; -WeightUpdate* weight_update_method; +WeightUpdate *weight_update_method; -vector > > training_inputs; -vector > > training_outputs; -vector > > validation_inputs; -vector > > validation_outputs; +vector< vector< vector > > training_inputs; +vector< vector< vector > > training_outputs; +vector< vector< vector > > validation_inputs; +vector< vector< vector > > validation_outputs; int32_t global_slice; int32_t global_repeat; @@ -79,12 +83,12 @@ RNN_Genome* receive_genome_from(int32_t source) { RNN_Genome* genome = new RNN_Genome(genome_str, length); - delete[] genome_str; + delete [] genome_str; return genome; } void send_genome_to(int32_t target, RNN_Genome* genome) { - char* byte_array; + char *byte_array; int32_t length; genome->write_to_array(&byte_array, length); @@ -117,7 +121,7 @@ void master(int32_t max_rank) { int32_t terminates_sent = 0; while (true) { - // wait for a incoming message + //wait for a incoming message MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); @@ -125,47 +129,44 @@ void master(int32_t max_rank) { int32_t tag = status.MPI_TAG; Log::debug("probe returned message from: %d with tag: %d\n", source, tag); - // if the message is a work request, send a genome + //if the message is a work request, send a genome if (tag == WORK_REQUEST_TAG) { receive_work_request(source); examm_mutex.lock(); - RNN_Genome* genome = examm->generate_genome(); + RNN_Genome *genome = examm->generate_genome(); examm_mutex.unlock(); - if (genome == NULL) { // search was completed if it returns NULL for an individual - // send terminate message + if (genome == NULL) { //search was completed if it returns NULL for an individual + //send terminate message Log::debug("terminating worker: %d\n", source); send_terminate_message(source); terminates_sent++; Log::debug("sent: %d terminates of %d\n", terminates_sent, (max_rank - 1)); - if (terminates_sent >= max_rank - 1) { - return; - } + if (terminates_sent >= max_rank - 1) return; } else { - // genome->write_to_file( examm->get_output_directory() + "/before_send_gen_" + - // to_string(genome->get_generation_id()) ); + //genome->write_to_file( examm->get_output_directory() + "/before_send_gen_" + to_string(genome->get_generation_id()) ); - // send genome + //send genome Log::debug("sending genome to: %d\n", source); send_genome_to(source, genome); - // delete this genome as it will not be used again + //delete this genome as it will not be used again delete genome; } } else if (tag == GENOME_LENGTH_TAG) { Log::debug("received genome from: %d\n", source); - RNN_Genome* genome = receive_genome_from(source); + RNN_Genome *genome = receive_genome_from(source); examm_mutex.lock(); examm->insert_genome(genome); examm_mutex.unlock(); delete genome; - // this genome will be deleted if/when removed from population + //this genome will be deleted if/when removed from population } else { Log::fatal("ERROR: received message from %d with unknown tag: %d\n", source, tag); MPI_Abort(MPI_COMM_WORLD, 1); @@ -174,8 +175,7 @@ void master(int32_t max_rank) { } void worker(int32_t rank) { - string worker_id = - "worker_slice_" + to_string(global_slice) + "_repeat_" + to_string(global_repeat) + "_" + to_string(rank); + string worker_id = "worker_slice_" + to_string(global_slice) + "_repeat_" + to_string(global_repeat) + "_" + to_string(rank); Log::set_id(worker_id); while (true) { @@ -198,15 +198,12 @@ void worker(int32_t rank) { Log::debug("received genome!\n"); RNN_Genome* genome = receive_genome_from(0); - string log_id = "slice_" + to_string(global_slice) + "_repeat_" + to_string(global_repeat) + "_genome_" - + to_string(genome->get_generation_id()) + "_worker_" + to_string(rank); + string log_id = "slice_" + to_string(global_slice) + "_repeat_" + to_string(global_repeat) + "_genome_" + to_string(genome->get_generation_id()) + "_worker_" + to_string(rank); Log::set_id(log_id); - genome->backpropagate_stochastic( - training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method - ); + genome->backpropagate_stochastic(training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method); Log::release_id(log_id); - // go back to the worker's log for MPI communication + //go back to the worker's log for MPI communication Log::set_id(worker_id); send_genome_to(0, genome); @@ -218,7 +215,7 @@ void worker(int32_t rank) { } } - // release the log file for the worker communication + //release the log file for the worker communication Log::release_id(worker_id); } @@ -238,26 +235,24 @@ int main(int argc, char** argv) { int32_t fold_size = 2; get_argument(arguments, "--fold_size", true, fold_size); - + string output_directory = ""; get_argument(arguments, "--output_directory", false, output_directory); int32_t repeats; get_argument(arguments, "--repeats", true, repeats); - TimeSeriesSets* time_series_sets = NULL; + TimeSeriesSets *time_series_sets = NULL; time_series_sets = TimeSeriesSets::generate_from_arguments(arguments); - get_train_validation_data( - arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs - ); + get_train_validation_data(arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs); weight_update_method = new WeightUpdate(); weight_update_method->generate_from_arguments(arguments); - WeightRules* weight_rules = new WeightRules(); - weight_rules->initialize_from_args(arguments); + WeightRules *weight_rules = new WeightRules(); + weight_rules->generate_weight_initialize_from_arguments(arguments); - RNN_Genome* seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); + RNN_Genome *seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); Log::clear_rank_restriction(); @@ -280,8 +275,8 @@ int main(int argc, char** argv) { time_series_sets->set_training_indexes(training_indexes); time_series_sets->set_test_indexes(test_indexes); - // time_series_sets->export_training_series(time_offset, training_inputs, training_outputs); - // time_series_sets->export_test_series(time_offset, validation_inputs, validation_outputs); + //time_series_sets->export_training_series(time_offset, training_inputs, training_outputs); + //time_series_sets->export_test_series(time_offset, validation_inputs, validation_outputs); string slice_output_directory = output_directory + "/slice_" + to_string(i); mkpath(slice_output_directory.c_str(), 0777); @@ -291,7 +286,7 @@ int main(int argc, char** argv) { string current_output_directory = slice_output_directory + "/repeat_" + to_string(k); mkpath(current_output_directory.c_str(), 0777); - // set to the master/workers can specify the right log id + //set to the master/workers can specify the right log id global_slice = i; global_repeat = k; @@ -306,11 +301,11 @@ int main(int argc, char** argv) { std::chrono::time_point end = std::chrono::system_clock::now(); long milliseconds = std::chrono::duration_cast(end - start).count(); - // examm->write_memory_log(current_output_directory + "/memory_fitness_log.csv"); + //examm->write_memory_log(current_output_directory + "/memory_fitness_log.csv"); slice_times_file << milliseconds << endl; - RNN_Genome* best_genome = examm->get_best_genome(); + RNN_Genome *best_genome = examm->get_best_genome(); string binary_file = slice_output_directory + "/repeat_best_" + to_string(k) + ".bin"; string graphviz_file = slice_output_directory + "/repeat_best_" + to_string(k) + ".gv"; @@ -327,10 +322,7 @@ int main(int argc, char** argv) { Log::set_id("main_" + to_string(rank)); MPI_Barrier(MPI_COMM_WORLD); - Log::debug( - "rank %d completed slice %d of %d repeat %d of %d\n", rank, i, time_series_sets->get_number_series(), k, - repeats - ); + Log::debug("rank %d completed slice %d of %d repeat %d of %d\n", rank, i, time_series_sets->get_number_series(), k, repeats); } slice_times_file.close(); diff --git a/mpi/process_sweep_results.cxx b/mpi/process_sweep_results.cxx index e1f538f2..e207e25d 100644 --- a/mpi/process_sweep_results.cxx +++ b/mpi/process_sweep_results.cxx @@ -3,6 +3,7 @@ using std::sort; #include #include + #include using std::setw; @@ -27,23 +28,26 @@ using std::map; using std::vector; #include "common/arguments.hxx" -#include "dirent.h" + #include "rnn/rnn_genome.hxx" + +#include "dirent.h" + #include "run_statistics.hxx" #include "tracker.hxx" + map>> genome_map; vector run_statistics; + bool extension_is(string name, string extension) { - if (name.size() < 4) { - return false; - } + if (name.size() < 4) return false; string ext = name.substr(name.length() - 4, 4); - // cout << "comparing '" << ext << "' to '" << extension << "'" << endl; + //cout << "comparing '" << ext << "' to '" << extension << "'" << endl; return ext.compare(extension) == 0; } @@ -52,17 +56,13 @@ string current_output; string current_run_type; void process_dir(string dir_name, int32_t depth) { - DIR* dir; - struct dirent* ent; + DIR *dir; + struct dirent *ent; if ((dir = opendir(dir_name.c_str())) != NULL) { /* print all the files and directories within directory */ while ((ent = readdir(dir)) != NULL) { - if (ent->d_name[0] == '.') { - continue; - } - if (strcmp(ent->d_name, "logs") == 0 && depth == 0) { - continue; - } + if (ent->d_name[0] == '.') continue; + if (strcmp(ent->d_name, "logs") == 0 && depth == 0) continue; if (depth == 0) { current_output = ent->d_name; @@ -79,12 +79,11 @@ void process_dir(string dir_name, int32_t depth) { } string sub_dir_name = dir_name + "/" + ent->d_name; - // cout << sub_dir_name << ", depth: " << depth << endl; + //cout << sub_dir_name << ", depth: " << depth << endl; if (depth == 3 && extension_is(sub_dir_name, ".bin")) { - cout << "\tprocessing genome binary '" << sub_dir_name << "' for '" << current_output << "'" - << " and " << current_run_type; - RNN_Genome* genome = new RNN_Genome(sub_dir_name); + cout << "\tprocessing genome binary '" << sub_dir_name << "' for '" << current_output << "'" << " and " << current_run_type; + RNN_Genome *genome = new RNN_Genome(sub_dir_name); cout << ", fitness: " << genome->get_fitness() << endl; genome_map[current_output][current_run_type].push_back(genome); @@ -96,10 +95,12 @@ void process_dir(string dir_name, int32_t depth) { } else { /* could not open directory */ - // cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; + //cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; } } + + int main(int argc, char** argv) { vector arguments = vector(argv, argv + argc); @@ -112,31 +113,35 @@ int main(int argc, char** argv) { output_types.push_back("rpm"); output_types.push_back("pitch"); - cout << "search_name,slice_name,best_mse,best_mae,n_edges,n_rec_edges,n_nodes,n_ff,n_lstm,n_ugrnn,n_delta,n_mgu,n_" - "gru" - << endl; - // iterate over the map of output names + cout << "search_name,slice_name,best_mse,best_mae,n_edges,n_rec_edges,n_nodes,n_ff,n_lstm,n_ugrnn,n_delta,n_mgu,n_gru" << endl; + + //iterate over the map of output names for (auto i = genome_map.begin(); i != genome_map.end(); i++) { string output_name = i->first; - // iterate over the map of run types + //iterate over the map of run types for (auto j = i->second.begin(); j != i->second.end(); j++) { string run_type = j->first; - RunStatistics* rs = new RunStatistics(output_name, run_type); + RunStatistics *rs = new RunStatistics(output_name, run_type); - // iterate over the vector of genomes + //iterate over the vector of genomes for (auto k = j->second.begin(); k != j->second.end(); k++) { - RNN_Genome* genome = *k; - - cout << i->first << "," << j->first << "," << genome->get_best_validation_mse() << "," - << genome->get_best_validation_mae() << "," << genome->get_enabled_edge_count() << "," - << genome->get_enabled_recurrent_edge_count() << "," << genome->get_enabled_node_count() << "," - << genome->get_enabled_node_count(SIMPLE_NODE) << "," << genome->get_enabled_node_count(LSTM_NODE) - << "," << genome->get_enabled_node_count(UGRNN_NODE) << "," - << genome->get_enabled_node_count(DELTA_NODE) << "," << genome->get_enabled_node_count(MGU_NODE) - << "," << genome->get_enabled_node_count(GRU_NODE) << endl; + RNN_Genome *genome = *k; + + cout << i->first << "," << j->first << "," + << genome->get_best_validation_mse() << "," + << genome->get_best_validation_mae() << "," + << genome->get_enabled_edge_count() << "," + << genome->get_enabled_recurrent_edge_count() << "," + << genome->get_enabled_node_count() << "," + << genome->get_enabled_node_count(SIMPLE_NODE) << "," + << genome->get_enabled_node_count(LSTM_NODE) << "," + << genome->get_enabled_node_count(UGRNN_NODE) << "," + << genome->get_enabled_node_count(DELTA_NODE) << "," + << genome->get_enabled_node_count(MGU_NODE) << "," + << genome->get_enabled_node_count(GRU_NODE) << endl; rs->mse.track(genome->get_best_validation_mse()); rs->mae.track(genome->get_best_validation_mae()); @@ -161,43 +166,31 @@ int main(int argc, char** argv) { cout << rs->to_string_correlate("mae", rs->mae) << endl; /* - cout << i->first << ",min," << mse.min() << "," << mae.min() << "," << edge.min() << "," << - rec_edge.min() << "," << node.min() << "," << ff.min() << "," << lstm.min() << "," << ugrnn.min() << "," - << delta.min() << "," << mgu.min() << "," << gru.min() << endl; cout << i->first << ",avg," << mse.avg() - << "," << mae.avg() << "," << edge.avg() << "," << rec_edge.avg() << "," << node.avg() << "," << ff.avg() - << "," << lstm.avg() << "," << ugrnn.avg() << "," << delta.avg() << "," << mgu.avg() << "," << gru.avg() - << endl; cout << i->first << ",max," << mse.max() << "," << mae.max() << "," << edge.max() << "," << - rec_edge.max() << "," << node.max() << "," << ff.max() << "," << lstm.max() << "," << ugrnn.max() << "," - << delta.max() << "," << mgu.max() << "," << gru.max() << endl; cout << i->first << ",stddev," << - mse.stddev() << "," << mae.stddev() << "," << edge.stddev() << "," << rec_edge.stddev() << "," << - node.stddev() << "," << ff.stddev() << "," << lstm.stddev() << "," << ugrnn.stddev() << "," << - delta.stddev() << "," << mgu.stddev() << "," << gru.stddev() << endl; cout << i->first << ",mse - correlation," << mse.correlate(mse) << "," << mae.correlate(mse) << "," << edge.correlate(mse) << "," << - rec_edge.correlate(mse) << "," << node.correlate(mse) << "," << ff.correlate(mse) << "," << - lstm.correlate(mse) << "," << ugrnn.correlate(mse) << "," << delta.correlate(mse) << "," << - mgu.correlate(mse) << "," << gru.correlate(mse) << endl; cout << i->first << ",mae correlation," << - mse.correlate(mae) << "," << mae.correlate(mae) << "," << edge.correlate(mae) << "," << - rec_edge.correlate(mae) << "," << node.correlate(mae) << "," << ff.correlate(mae) << "," << - lstm.correlate(mae) << "," << ugrnn.correlate(mae) << "," << delta.correlate(mae) << "," << - mgu.correlate(mae) << "," << gru.correlate(mae) << endl; + cout << i->first << ",min," << mse.min() << "," << mae.min() << "," << edge.min() << "," << rec_edge.min() << "," << node.min() << "," << ff.min() << "," << lstm.min() << "," << ugrnn.min() << "," << delta.min() << "," << mgu.min() << "," << gru.min() << endl; + cout << i->first << ",avg," << mse.avg() << "," << mae.avg() << "," << edge.avg() << "," << rec_edge.avg() << "," << node.avg() << "," << ff.avg() << "," << lstm.avg() << "," << ugrnn.avg() << "," << delta.avg() << "," << mgu.avg() << "," << gru.avg() << endl; + cout << i->first << ",max," << mse.max() << "," << mae.max() << "," << edge.max() << "," << rec_edge.max() << "," << node.max() << "," << ff.max() << "," << lstm.max() << "," << ugrnn.max() << "," << delta.max() << "," << mgu.max() << "," << gru.max() << endl; + cout << i->first << ",stddev," << mse.stddev() << "," << mae.stddev() << "," << edge.stddev() << "," << rec_edge.stddev() << "," << node.stddev() << "," << ff.stddev() << "," << lstm.stddev() << "," << ugrnn.stddev() << "," << delta.stddev() << "," << mgu.stddev() << "," << gru.stddev() << endl; + cout << i->first << ",mse correlation," << mse.correlate(mse) << "," << mae.correlate(mse) << "," << edge.correlate(mse) << "," << rec_edge.correlate(mse) << "," << node.correlate(mse) << "," << ff.correlate(mse) << "," << lstm.correlate(mse) << "," << ugrnn.correlate(mse) << "," << delta.correlate(mse) << "," << mgu.correlate(mse) << "," << gru.correlate(mse) << endl; + cout << i->first << ",mae correlation," << mse.correlate(mae) << "," << mae.correlate(mae) << "," << edge.correlate(mae) << "," << rec_edge.correlate(mae) << "," << node.correlate(mae) << "," << ff.correlate(mae) << "," << lstm.correlate(mae) << "," << ugrnn.correlate(mae) << "," << delta.correlate(mae) << "," << mgu.correlate(mae) << "," << gru.correlate(mae) << endl; */ cout << endl; cout << endl; + run_statistics.push_back(rs); + } } - // process the kfold sweep directories, these should start with "sweep" + + //process the kfold sweep directories, these should start with "sweep" DIR *dir, *subdir; - struct dirent* ent; + struct dirent *ent; if ((dir = opendir(path.c_str())) != NULL) { /* print all the files and directories within directory */ while ((ent = readdir(dir)) != NULL) { - if (ent->d_name[0] != 's') { - continue; - } + if (ent->d_name[0] != 's') continue; string sweep_directory = ent->d_name; cout << "processing sweep directory: " << ent->d_name << endl; @@ -205,6 +198,7 @@ int main(int argc, char** argv) { if ((subdir = opendir(sub_dir_name.c_str())) != NULL) { while ((ent = readdir(subdir)) != NULL) { if (strlen(ent->d_name) > 4 && extension_is(ent->d_name, ".csv")) { + Tracker mse; Tracker mae; @@ -214,25 +208,25 @@ int main(int argc, char** argv) { string line; while (getline(infile, line)) { - // cout << line << endl; + //cout << line << endl; stringstream ss(line); string s; getline(ss, s, ','); - // int32_t fold = stoi(s); + //int32_t fold = stoi(s); getline(ss, s, ','); - // int32_t repeat = stoi(s); + //int32_t repeat = stoi(s); getline(ss, s, ','); - // int32_t runtime = stoi(s); + //int32_t runtime = stoi(s); getline(ss, s, ','); - // double training_mse = stod(s); + //double training_mse = stod(s); getline(ss, s, ','); - // double training_mae = stod(s); + //double training_mae = stod(s); getline(ss, s, ','); double test_mse = stod(s); @@ -268,30 +262,35 @@ int main(int argc, char** argv) { cout << endl; cout << endl; - // run_statistics.push_back(new RunStatistics(sweep_directory + "_" + search_type, mse, mae)); + //run_statistics.push_back(new RunStatistics(sweep_directory + "_" + search_type, mse, mae)); } else { - // cout << "skipping: '" << ent->d_name << "'" << endl; + //cout << "skipping: '" << ent->d_name << "'" << endl; } + } } else { /* could not open directory */ - // cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; + //cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; } + } closedir(dir); } else { /* could not open directory */ - // cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; + //cerr << "ERROR: could not open the directory '" << dir_name << "'" << endl; } - for (int32_t i = 0; i < (int32_t) output_types.size(); i++) { + + + + for (int32_t i = 0; i < (int32_t)output_types.size(); i++) { cout << endl << endl; cout << run_statistics[0]->overview_header(); - for (int32_t j = 0; j < (int32_t) run_statistics.size(); j++) { + for (int32_t j = 0; j < (int32_t)run_statistics.size(); j++) { if (run_statistics[j]->output_name.compare(output_types[i]) == 0) { string run_type = run_statistics[j]->run_type; if (run_type.find("simple") == string::npos || run_type.find("all") != string::npos) { @@ -305,12 +304,12 @@ int main(int argc, char** argv) { cout << endl << endl << endl; - for (int32_t i = 0; i < (int32_t) output_types.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_types.size(); i++) { cout << endl << endl; cout << run_statistics[0]->overview_ff_header(); - for (int32_t j = 0; j < (int32_t) run_statistics.size(); j++) { + for (int32_t j = 0; j < (int32_t)run_statistics.size(); j++) { if (run_statistics[j]->output_name.compare(output_types[i]) == 0) { string run_type = run_statistics[j]->run_type; if (run_type.find("simple") != string::npos && run_type.find("all") == string::npos) { @@ -324,6 +323,8 @@ int main(int argc, char** argv) { cout << endl << endl << endl; + + cout << "\\begin{table}" << endl; cout << "\\begin{scriptsize}" << endl; cout << "\\centering" << endl; @@ -333,7 +334,7 @@ int main(int argc, char** argv) { cout << run_statistics[0]->correlate_header() << endl; cout << "\\hline" << endl; - for (int32_t i = 0; i < (int32_t) run_statistics.size(); i++) { + for (int32_t i = 0; i < (int32_t)run_statistics.size(); i++) { if (run_statistics[i]->run_type.find("all") != string::npos) { cout << run_statistics[i]->to_string_correlate("mse", run_statistics[i]->mse) << "\\\\" << endl; } @@ -341,9 +342,7 @@ int main(int argc, char** argv) { cout << "\\hline" << endl; cout << "\\end{tabular}" << endl; - cout << "\\caption{\\label{table:consolidated_rankings} Hidden node count correlations for EXAMM runs evolving all " - "memory neuron types.}" - << endl; + cout << "\\caption{\\label{table:consolidated_rankings} Hidden node count correlations for EXAMM runs evolving all memory neuron types.}" << endl; cout << "\\end{scriptsize}" << endl; cout << "\\end{table}" << endl; @@ -354,61 +353,57 @@ int main(int argc, char** argv) { cout << "\\hline" << endl; cout << " " - << "& \\multicolumn{4}{|c|}{FF}" - << "& \\multicolumn{4}{|c|}{LSTM}" - << "& \\multicolumn{4}{|c|}{UGRNN}" - << "& \\multicolumn{4}{|c|}{Delta}" - << "& \\multicolumn{4}{|c|}{MGU}" - << "& \\multicolumn{4}{|c|}{GRU}" - << "\\\\" << endl; + << "& \\multicolumn{4}{|c|}{FF}" + << "& \\multicolumn{4}{|c|}{LSTM}" + << "& \\multicolumn{4}{|c|}{UGRNN}" + << "& \\multicolumn{4}{|c|}{Delta}" + << "& \\multicolumn{4}{|c|}{MGU}" + << "& \\multicolumn{4}{|c|}{GRU}" + << "\\\\" << endl; cout << "\\hline" << endl; cout << "Run Type" - << " & Min & Avg & Max & Corr" - << " & Min & Avg & Max & Corr" - << " & Min & Avg & Max & Corr" - << " & Min & Avg & Max & Corr" - << " & Min & Avg & Max & Corr" - << " & Min & Avg & Max & Corr" - << "\\\\" << endl; + << " & Min & Avg & Max & Corr" + << " & Min & Avg & Max & Corr" + << " & Min & Avg & Max & Corr" + << " & Min & Avg & Max & Corr" + << " & Min & Avg & Max & Corr" + << " & Min & Avg & Max & Corr" + << "\\\\" << endl; cout << "\\hline" << endl; cout << "\\hline" << endl; - for (int32_t i = 0; i < (int32_t) run_statistics.size(); i++) { + for (int32_t i = 0; i < (int32_t)run_statistics.size(); i++) { if (run_statistics[i]->run_type.find("all") != string::npos) { - cout << run_statistics[i]->output_name << " & " << run_statistics[i]->ff.min() << " & " << setprecision(1) - << run_statistics[i]->ff.avg() << " & " << run_statistics[i]->ff.max() << "&" << setprecision(2) - << run_statistics[i]->ff.correlate(run_statistics[i]->mse) << " & " << run_statistics[i]->lstm.min() - << " & " << setprecision(1) << run_statistics[i]->lstm.avg() << " & " << run_statistics[i]->lstm.max() - << "&" << setprecision(2) << run_statistics[i]->lstm.correlate(run_statistics[i]->mse) << " & " - << run_statistics[i]->ugrnn.min() << " & " << setprecision(1) << run_statistics[i]->ugrnn.avg() - << " & " << run_statistics[i]->ugrnn.max() << "&" << setprecision(2) - << run_statistics[i]->ugrnn.correlate(run_statistics[i]->mse) << " & " - << run_statistics[i]->delta.min() << " & " << setprecision(1) << run_statistics[i]->delta.avg() - << " & " << run_statistics[i]->delta.max() << "&" << setprecision(2) - << run_statistics[i]->delta.correlate(run_statistics[i]->mse) << " & " << run_statistics[i]->mgu.min() - << " & " << setprecision(1) << run_statistics[i]->mgu.avg() << " & " << run_statistics[i]->mgu.max() - << "&" << setprecision(2) << run_statistics[i]->mgu.correlate(run_statistics[i]->mse) << " & " - << run_statistics[i]->gru.min() << " & " << setprecision(1) << run_statistics[i]->gru.avg() << " & " - << run_statistics[i]->gru.max() << "&" << setprecision(2) - << run_statistics[i]->gru.correlate(run_statistics[i]->mse) << "\\\\" << endl; + cout << run_statistics[i]->output_name + << " & " << run_statistics[i]->ff.min() << " & " << setprecision(1) << run_statistics[i]->ff.avg() << " & " << run_statistics[i]->ff.max() << "&" << setprecision(2) << run_statistics[i]->ff.correlate(run_statistics[i]->mse) + << " & " << run_statistics[i]->lstm.min() << " & " << setprecision(1) << run_statistics[i]->lstm.avg() << " & " << run_statistics[i]->lstm.max() << "&" << setprecision(2) << run_statistics[i]->lstm.correlate(run_statistics[i]->mse) + << " & " << run_statistics[i]->ugrnn.min() << " & " << setprecision(1) << run_statistics[i]->ugrnn.avg() << " & " << run_statistics[i]->ugrnn.max() << "&" << setprecision(2) << run_statistics[i]->ugrnn.correlate(run_statistics[i]->mse) + << " & " << run_statistics[i]->delta.min() << " & " << setprecision(1) << run_statistics[i]->delta.avg() << " & " << run_statistics[i]->delta.max() << "&" << setprecision(2) << run_statistics[i]->delta.correlate(run_statistics[i]->mse) + << " & " << run_statistics[i]->mgu.min() << " & " << setprecision(1) << run_statistics[i]->mgu.avg() << " & " << run_statistics[i]->mgu.max() << "&" << setprecision(2) << run_statistics[i]->mgu.correlate(run_statistics[i]->mse) + << " & " << run_statistics[i]->gru.min() << " & " << setprecision(1) << run_statistics[i]->gru.avg() << " & " << run_statistics[i]->gru.max() << "&" << setprecision(2) << run_statistics[i]->gru.correlate(run_statistics[i]->mse) + << "\\\\" << endl; } } cout << "\\hline" << endl; cout << "\\end{tabular}" << endl; - cout << "\\caption{\\label{table:consolidated_rankings} Hidden node count correlations for EXAMM runs evolving all " - "memory neuron types.}" - << endl; + cout << "\\caption{\\label{table:consolidated_rankings} Hidden node count correlations for EXAMM runs evolving all memory neuron types.}" << endl; cout << "\\end{scriptsize}" << endl; cout << "\\end{table}" << endl; + + + + + + map> output_sorted_statistics; cout << endl << endl; - for (int32_t i = 0; i < (int32_t) output_types.size(); i++) { - for (int32_t j = 0; j < (int32_t) run_statistics.size(); j++) { + for (int32_t i = 0; i < (int32_t)output_types.size(); i++) { + for (int32_t j = 0; j < (int32_t)run_statistics.size(); j++) { if (run_statistics[j]->output_name.compare(output_types[i]) == 0) { output_sorted_statistics[output_types[i]].push_back(run_statistics[j]); } @@ -447,11 +442,11 @@ int main(int argc, char** argv) { map consolidated_statistics; - for (int32_t i = 0; i < (int32_t) run_types.size(); i++) { + for (int32_t i = 0; i < (int32_t)run_types.size(); i++) { consolidated_statistics[run_types[i]] = new ConsolidatedStatistics(run_types[i]); } - for (int32_t i = 0; i < (int32_t) output_types.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_types.size(); i++) { cout << "GENERATING sorted stats for: '" << output_types[i] << "'" << endl; vector current = output_sorted_statistics[output_types[i]]; @@ -462,7 +457,7 @@ int main(int argc, char** argv) { double avg_avg = 0.0; double avg_max = 0.0; - for (int32_t j = 0; j < (int32_t) current.size(); j++) { + for (int32_t j = 0; j < (int32_t)current.size(); j++) { avg_min += current[j]->mse.min(); avg_avg += current[j]->mse.avg(); avg_max += current[j]->mse.max(); @@ -478,7 +473,7 @@ int main(int argc, char** argv) { double stddev_avg = 0.0; double stddev_max = 0.0; - for (int32_t j = 0; j < (int32_t) current.size(); j++) { + for (int32_t j = 0; j < (int32_t)current.size(); j++) { stddev_min += (current[j]->mse.min() - avg_min) * (current[j]->mse.min() - avg_min); stddev_avg += (current[j]->mse.avg() - avg_avg) * (current[j]->mse.avg() - avg_avg); stddev_max += (current[j]->mse.max() - avg_max) * (current[j]->mse.max() - avg_max); @@ -490,16 +485,16 @@ int main(int argc, char** argv) { cout << "calculated stddevs!" << endl; - for (int32_t j = 0; j < (int32_t) current.size(); j++) { + for (int32_t j = 0; j < (int32_t)current.size(); j++) { cout << "current[" << j << "]->run_type: " << current[j]->run_type << endl; current[j]->set_deviation_from_mean_min((current[j]->mse.min() - avg_min) / stddev_min); current[j]->set_deviation_from_mean_avg((current[j]->mse.avg() - avg_avg) / stddev_avg); current[j]->set_deviation_from_mean_max((current[j]->mse.max() - avg_max) / stddev_max); - consolidated_statistics[current[j]->run_type]->dfm_min += current[j]->dfm_min / output_types.size(); - consolidated_statistics[current[j]->run_type]->dfm_avg += current[j]->dfm_avg / output_types.size(); - consolidated_statistics[current[j]->run_type]->dfm_max += current[j]->dfm_max / output_types.size(); + consolidated_statistics[ current[j]->run_type ]->dfm_min += current[j]->dfm_min / output_types.size(); + consolidated_statistics[ current[j]->run_type ]->dfm_avg += current[j]->dfm_avg / output_types.size(); + consolidated_statistics[ current[j]->run_type ]->dfm_max += current[j]->dfm_max / output_types.size(); } cout << "updated consolidated statistics!" << endl; @@ -522,24 +517,18 @@ int main(int argc, char** argv) { cout << "\\centering" << endl; cout << "\\begin{tabular}{|r|l||r|l||r|l||}" << endl; cout << "\\hline" << endl; - cout << "\\multicolumn{2}{|c||}{{\\bf Best Case}} & \\multicolumn{2}{|c||}{{\\bf Avg. Case}} & " - "\\multicolumn{2}{|c|}{{\\bf Worst Case}} \\\\" - << endl; + cout << "\\multicolumn{2}{|c||}{{\\bf Best Case}} & \\multicolumn{2}{|c||}{{\\bf Avg. Case}} & \\multicolumn{2}{|c|}{{\\bf Worst Case}} \\\\" << endl; cout << "\\hline" << endl; - for (int32_t j = 0; j < (int32_t) current.size(); j++) { - cout << setw(15) << fix_run_type(sorted_by_min[j]->run_type) << " & " << setw(15) << setprecision(5) - << sorted_by_min[j]->dfm_min << " & "; - cout << setw(15) << fix_run_type(sorted_by_avg[j]->run_type) << " & " << setw(15) << setprecision(5) - << sorted_by_avg[j]->dfm_avg << " & "; - cout << setw(15) << fix_run_type(sorted_by_max[j]->run_type) << " & " << setw(15) << setprecision(5) - << sorted_by_max[j]->dfm_max << "\\\\" << endl; + for (int32_t j = 0; j < (int32_t)current.size(); j++) { + cout << setw(15) << fix_run_type(sorted_by_min[j]->run_type) << " & " << setw(15) << setprecision(5) << sorted_by_min[j]->dfm_min << " & "; + cout << setw(15) << fix_run_type(sorted_by_avg[j]->run_type) << " & " << setw(15) << setprecision(5) << sorted_by_avg[j]->dfm_avg << " & "; + cout << setw(15) << fix_run_type(sorted_by_max[j]->run_type) << " & " << setw(15) << setprecision(5) << sorted_by_max[j]->dfm_max << "\\\\" << endl; } cout << "\\hline" << endl; cout << "\\end{tabular}" << endl; - cout << "\\caption{\\label{table:consolidated_rankings} Rankings for all the EXAMM run types predicting " - << output_types[i] << ".}" << endl; + cout << "\\caption{\\label{table:consolidated_rankings} Rankings for all the EXAMM run types predicting " << output_types[i] << ".}" << endl; cout << "\\end{scriptsize}" << endl; cout << "\\end{table}" << endl; } @@ -564,18 +553,13 @@ int main(int argc, char** argv) { cout << "\\centering" << endl; cout << "\\begin{tabular}{|r|l||r|l||r|l||}" << endl; cout << "\\hline" << endl; - cout << "\\multicolumn{2}{|c||}{{\\bf Best Case}} & \\multicolumn{2}{|c||}{{\\bf Avg. Case}} & " - "\\multicolumn{2}{|c|}{{\\bf Worst Case}} \\\\" - << endl; + cout << "\\multicolumn{2}{|c||}{{\\bf Best Case}} & \\multicolumn{2}{|c||}{{\\bf Avg. Case}} & \\multicolumn{2}{|c|}{{\\bf Worst Case}} \\\\" << endl; cout << "\\hline" << endl; - for (int32_t i = 0; i < (int32_t) min_stats_vector.size(); i++) { - cout << setw(15) << fix_run_type(min_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) - << min_stats_vector[i]->dfm_min << " & "; - cout << setw(15) << fix_run_type(avg_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) - << avg_stats_vector[i]->dfm_avg << " & "; - cout << setw(15) << fix_run_type(max_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) - << max_stats_vector[i]->dfm_max << "\\\\" << endl; + for (int32_t i = 0; i < (int32_t)min_stats_vector.size(); i++) { + cout << setw(15) << fix_run_type(min_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) << min_stats_vector[i]->dfm_min << " & "; + cout << setw(15) << fix_run_type(avg_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) << avg_stats_vector[i]->dfm_avg << " & "; + cout << setw(15) << fix_run_type(max_stats_vector[i]->run_type) << " & " << setw(15) << setprecision(5) << max_stats_vector[i]->dfm_max << "\\\\" << endl; } cout << "\\hline" << endl; @@ -586,3 +570,4 @@ int main(int argc, char** argv) { return 0; } + diff --git a/mpi/rnn_kfold_sweep.cxx b/mpi/rnn_kfold_sweep.cxx index c370261a..73780296 100644 --- a/mpi/rnn_kfold_sweep.cxx +++ b/mpi/rnn_kfold_sweep.cxx @@ -1,4 +1,5 @@ #include + #include using std::getline; using std::ifstream; @@ -23,32 +24,37 @@ using std::strchr; #include using std::vector; -// for mkdir -#include +//for mkdir #include +#include #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ typedef struct stat Stat; +#include "mpi.h" + + #include "common/arguments.hxx" #include "common/log.hxx" -#include "mpi.h" -#include "rnn/generate_nn.hxx" +#include "weights/weight_rules.hxx" +#include "weights/weight_update.hxx" + #include "rnn/lstm_node.hxx" #include "rnn/rnn_edge.hxx" #include "rnn/rnn_genome.hxx" #include "rnn/rnn_node.hxx" #include "rnn/rnn_node_interface.hxx" + +#include "rnn/generate_nn.hxx" + #include "time_series/time_series.hxx" -#include "weights/weight_rules.hxx" -#include "weights/weight_update.hxx" #define WORK_REQUEST_TAG 1 -#define JOB_TAG 2 -#define TERMINATE_TAG 3 -#define RESULT_TAG 4 +#define JOB_TAG 2 +#define TERMINATE_TAG 3 +#define RESULT_TAG 4 int32_t time_offset = 1; int32_t bp_iterations; @@ -59,17 +65,23 @@ string weight_initialize_string = "xavier"; string process_name; -WeightUpdate* weight_update_method; -WeightRules* weight_rules; +WeightUpdate *weight_update_method; +WeightRules *weight_rules; -vector rnn_types( - {"one_layer_ff", "two_layer_ff", "jordan", "elman", "one_layer_mgu", "two_layer_mgu", "one_layer_gru", - "two_layer_gru", "one_layer_ugrnn", "two_layer_ugrnn", "one_layer_delta", "two_layer_delta", "one_layer_lstm", - "two_layer_lstm"} -); +vector rnn_types({ + "one_layer_ff", "two_layer_ff", + "jordan", + "elman", + "one_layer_mgu", "two_layer_mgu", + "one_layer_gru", "two_layer_gru", + "one_layer_ugrnn", "two_layer_ugrnn", + "one_layer_delta", "two_layer_delta", + "one_layer_lstm", "two_layer_lstm" + }); TimeSeriesSets* time_series_sets = NULL; + struct ResultSet { int32_t job; double training_mae; @@ -81,6 +93,8 @@ struct ResultSet { vector results; + + void send_work_request_to(int32_t target) { int32_t work_request_message[1]; work_request_message[0] = 0; @@ -101,6 +115,7 @@ void send_job_to(int32_t target, int32_t current_job) { MPI_Send(job_message, 1, MPI_INT, target, JOB_TAG, MPI_COMM_WORLD); } + int32_t receive_job_from(int32_t source) { MPI_Status status; int32_t job_message[1]; @@ -114,9 +129,7 @@ int32_t receive_job_from(int32_t source) { } string result_to_string(ResultSet result) { - return "[result, job: " + to_string(result.job) + ", training mae: " + to_string(result.training_mae) - + ", training mse: " + to_string(result.training_mse) + ", test mae: " + to_string(result.test_mae) - + ", test mse: " + to_string(result.test_mae) + ", millis: " + to_string(result.milliseconds) + "]"; + return "[result, job: " + to_string(result.job) + ", training mae: " + to_string(result.training_mae) + ", training mse: " + to_string(result.training_mse) + ", test mae: " + to_string(result.test_mae) + ", test mse: " + to_string(result.test_mae) + ", millis: " + to_string(result.milliseconds) + "]"; } void send_result_to(int32_t target, ResultSet result) { @@ -153,10 +166,11 @@ void receive_terminate_from(int32_t source) { MPI_Recv(terminate_message, 1, MPI_INT, source, TERMINATE_TAG, MPI_COMM_WORLD, &status); } -// tweaked from: https://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux/29828907 -static int32_t do_mkdir(const char* path, mode_t mode) { - Stat st; - int32_t status = 0; + +//tweaked from: https://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux/29828907 +static int32_t do_mkdir(const char *path, mode_t mode) { + Stat st; + int32_t status = 0; if (stat(path, &st) != 0) { /* Directory does not exist. EEXIST for race condition */ @@ -169,7 +183,7 @@ static int32_t do_mkdir(const char* path, mode_t mode) { status = -1; } - return (status); + return(status); } /** @@ -178,11 +192,11 @@ static int32_t do_mkdir(const char* path, mode_t mode) { * ** each directory in path exists, rather than optimistically creating * ** the last element and working backwards. * */ -int32_t mkpath(const char* path, mode_t mode) { - char* pp; - char* sp; - int32_t status; - char* copypath = strdup(path); +int32_t mkpath(const char *path, mode_t mode) { + char *pp; + char *sp; + int32_t status; + char *copypath = strdup(path); status = 0; pp = copypath; @@ -205,6 +219,9 @@ int32_t mkpath(const char* path, mode_t mode) { return (status); } + + + void master(int32_t max_rank) { if (output_directory != "") { Log::debug("creating directory: '%s'\n", output_directory.c_str()); @@ -213,17 +230,15 @@ void master(int32_t max_rank) { mkdir(output_directory.c_str(), 0777); } - // initialize the results with -1 as the job so we can determine if a particular rnn type has completed - results = vector( - rnn_types.size() * time_series_sets->get_number_series() * repeats, {-1, 0.0, 0.0, 0.0, 0.0, 0} - ); + //initialize the results with -1 as the job so we can determine if a particular rnn type has completed + results = vector(rnn_types.size() * time_series_sets->get_number_series() * repeats, {-1, 0.0, 0.0, 0.0, 0.0, 0}); int32_t terminates_sent = 0; int32_t current_job = 0; int32_t last_job = rnn_types.size() * (time_series_sets->get_number_series() / fold_size) * repeats; while (true) { - // wait for a incoming message + //wait for a incoming message MPI_Status status; MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); @@ -231,29 +246,27 @@ void master(int32_t max_rank) { int32_t tag = status.MPI_TAG; Log::debug("probe returned message from: %d with tag: %d\n", message_source, tag); - // if the message is a work request, send a genome + //if the message is a work request, send a genome if (tag == WORK_REQUEST_TAG) { receive_work_request_from(message_source); if (current_job >= last_job) { - // no more jobs to process if the current job is >= the result vector - // send terminate message + //no more jobs to process if the current job is >= the result vector + //send terminate message Log::debug("terminating worker: %d\n", message_source); send_terminate_to(message_source); terminates_sent++; Log::debug("sent: %d terminates of: %d\n", terminates_sent, (max_rank - 1)); - if (terminates_sent >= max_rank - 1) { - return; - } + if (terminates_sent >= max_rank - 1) return; } else { - // send job + //send job Log::debug("sending job to: %d\n", message_source); send_job_to(message_source, current_job); - // increment the current job for the next worker + //increment the current job for the next worker current_job++; } } else if (tag == RESULT_TAG) { @@ -261,12 +274,12 @@ void master(int32_t max_rank) { ResultSet result = receive_result_from(message_source); results[result.job] = result; - // TODO: - // check and see if this particular set of jobs for rnn_type has completed, - // then write the file for that type if it has + //TODO: + //check and see if this particular set of jobs for rnn_type has completed, + //then write the file for that type if it has int32_t jobs_per_rnn = (time_series_sets->get_number_series() / fold_size) * repeats; - // get the particular rnn type this job was for, and which results should be there + //get the particular rnn type this job was for, and which results should be there int32_t rnn = result.job / jobs_per_rnn; int32_t rnn_job_start = rnn * jobs_per_rnn; int32_t rnn_job_end = (rnn + 1) * jobs_per_rnn; @@ -295,20 +308,17 @@ void master(int32_t max_rank) { int32_t current = rnn_job_start; for (int32_t j = 0; j < (time_series_sets->get_number_series() / fold_size); j++) { for (int32_t k = 0; k < repeats; k++) { - outfile << j << "," << k << "," << results[current].milliseconds << "," - << results[current].training_mse << "," << results[current].training_mae << "," - << results[current].test_mse << "," << results[current].test_mae << endl; - - Log::debug( - "%s, tested on series[%d], repeat: %d, result: %s\n", rnn_types[rnn].c_str(), j, k, - result_to_string(results[current]).c_str() - ); + + outfile << j << "," << k << "," << results[current].milliseconds << "," << results[current].training_mse << "," << results[current].training_mae << "," << results[current].test_mse << "," << results[current].test_mae << endl; + + Log::debug("%s, tested on series[%d], repeat: %d, result: %s\n", rnn_types[rnn].c_str(), j, k, result_to_string(results[current]).c_str()); current++; } } outfile.close(); } + } else { Log::fatal("ERROR: received message from %d with unknown tag: %d\n", message_source, tag); MPI_Abort(MPI_COMM_WORLD, 1); @@ -319,13 +329,13 @@ void master(int32_t max_rank) { ResultSet handle_job(int32_t rank, int32_t current_job) { int32_t jobs_per_rnn = (time_series_sets->get_number_series() / fold_size) * repeats; - // get rnn_type - string rnn_type = rnn_types[current_job / jobs_per_rnn]; - // get j, k + //get rnn_type + string rnn_type = rnn_types[ current_job / jobs_per_rnn ] ; + //get j, k int32_t jobs_per_j = repeats; int32_t j = (current_job % jobs_per_rnn) / jobs_per_j; - // get repeat + //get repeat int32_t repeat = current_job % jobs_per_j; Log::debug("evaluating rnn type '%s' with j: %d, repeat: %d\n", rnn_type.c_str(), j, repeat); @@ -350,10 +360,10 @@ ResultSet handle_job(int32_t rank, int32_t current_job) { time_series_sets->set_training_indexes(training_indexes); time_series_sets->set_test_indexes(test_indexes); - vector > > training_inputs; - vector > > training_outputs; - vector > > validation_inputs; - vector > > validation_outputs; + vector< vector< vector > > training_inputs; + vector< vector< vector > > training_outputs; + vector< vector< vector > > validation_inputs; + vector< vector< vector > > validation_outputs; time_series_sets->export_training_series(time_offset, training_inputs, training_outputs); time_series_sets->export_test_series(time_offset, validation_inputs, validation_outputs); @@ -362,9 +372,9 @@ ResultSet handle_job(int32_t rank, int32_t current_job) { vector output_parameter_names = time_series_sets->get_output_parameter_names(); int32_t number_inputs = time_series_sets->get_number_inputs(); - // int32_t number_outputs = time_series_sets->get_number_outputs(); + //int32_t number_outputs = time_series_sets->get_number_outputs(); - RNN_Genome* genome = NULL; + RNN_Genome *genome = NULL; if (rnn_type == "one_layer_lstm") { genome = create_lstm(input_parameter_names, 1, number_inputs, output_parameter_names, 1, weight_rules); @@ -417,14 +427,10 @@ ResultSet handle_job(int32_t rank, int32_t current_job) { RNN* rnn = genome->get_rnn(); int32_t number_of_weights = genome->get_number_weights(); - Log::debug( - "RNN INFO FOR '%s', nodes: %d, edges: %d, rec: %d, weights: %d\n", rnn_type.c_str(), - genome->get_enabled_node_count(), genome->get_enabled_edge_count(), genome->get_enabled_recurrent_edge_count(), - number_of_weights - ); + Log::debug("RNN INFO FOR '%s', nodes: %d, edges: %d, rec: %d, weights: %d\n", rnn_type.c_str(), genome->get_enabled_node_count(), genome->get_enabled_edge_count(), genome->get_enabled_recurrent_edge_count(), number_of_weights); - vector min_bound(number_of_weights, -1.0); - vector max_bound(number_of_weights, 1.0); + vector min_bound(number_of_weights, -1.0); + vector max_bound(number_of_weights, 1.0); vector best_parameters; @@ -444,9 +450,7 @@ ResultSet handle_job(int32_t rank, int32_t current_job) { Log::set_id(backprop_log_id); std::chrono::time_point start = std::chrono::system_clock::now(); - genome->backpropagate_stochastic( - training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method - ); + genome->backpropagate_stochastic(training_inputs, training_outputs, validation_inputs, validation_outputs, weight_update_method); std::chrono::time_point end = std::chrono::system_clock::now(); long milliseconds = std::chrono::duration_cast(end - start).count(); @@ -520,7 +524,9 @@ void worker(int32_t rank) { Log::release_id("worker_" + to_string(rank)); } -int main(int argc, char** argv) { + + +int main(int argc, char **argv) { int32_t rank, max_rank; MPI_Init(&argc, &argv); @@ -537,6 +543,7 @@ int main(int argc, char** argv) { Log::debug("process %d of %d\n", rank, max_rank); Log::restrict_to_rank(0); + get_argument(arguments, "--time_offset", true, time_offset); get_argument(arguments, "--bp_iterations", true, bp_iterations); @@ -548,19 +555,20 @@ int main(int argc, char** argv) { get_argument(arguments, "--fold_size", true, fold_size); weight_rules = new WeightRules(); - weight_rules->initialize_from_args(arguments); + weight_rules->generate_weight_initialize_from_arguments(arguments); weight_update_method = new WeightUpdate(); weight_update_method->generate_from_arguments(arguments); + if (rank == 0) { - // only print verbose info from the master process + //only print verbose info from the master process time_series_sets = TimeSeriesSets::generate_from_arguments(arguments); } else { time_series_sets = TimeSeriesSets::generate_from_arguments(arguments); } - // MPI_Barrier(MPI_COMM_WORLD); + //MPI_Barrier(MPI_COMM_WORLD); Log::clear_rank_restriction(); diff --git a/mpi/run_statistics.cxx b/mpi/run_statistics.cxx index 183fa540..829f332f 100644 --- a/mpi/run_statistics.cxx +++ b/mpi/run_statistics.cxx @@ -1,9 +1,10 @@ #include using std::endl; + #include -using std::setprecision; using std::setw; +using std::setprecision; #include using std::regex; @@ -15,8 +16,10 @@ using std::string; #include using std::ostringstream; -#include "run_statistics.hxx" #include "tracker.hxx" +#include "run_statistics.hxx" + + string fix_run_type(string run_type) { run_type = regex_replace(run_type, regex("_norec"), ""); @@ -29,6 +32,7 @@ ConsolidatedStatistics::ConsolidatedStatistics(string _run_type) : run_type(_run dfm_min = 0.0; dfm_avg = 0.0; dfm_max = 0.0; + } string ConsolidatedStatistics::to_string_min() { @@ -55,6 +59,7 @@ string ConsolidatedStatistics::to_string_max() { return oss.str(); } + RunStatistics::RunStatistics(string _output_name, string _run_type) : output_name(_output_name), run_type(_run_type) { } @@ -73,9 +78,7 @@ void RunStatistics::set_deviation_from_mean_max(double _dfm_max) { string RunStatistics::to_string_min() { ostringstream oss; - oss << output_name << "," << fix_run_type(run_type) << ",min," << mse.min() << "," << mae.min() << "," << edge.min() - << "," << rec_edge.min() << "," << node.min() << "," << ff.min() << "," << lstm.min() << "," << ugrnn.min() - << "," << delta.min() << "," << mgu.min() << "," << gru.min(); + oss << output_name << "," << fix_run_type(run_type) << ",min," << mse.min() << "," << mae.min() << "," << edge.min() << "," << rec_edge.min() << "," << node.min() << "," << ff.min() << "," << lstm.min() << "," << ugrnn.min() << "," << delta.min() << "," << mgu.min() << "," << gru.min(); return oss.str(); } @@ -83,9 +86,7 @@ string RunStatistics::to_string_min() { string RunStatistics::to_string_avg() { ostringstream oss; - oss << output_name << "," << fix_run_type(run_type) << ",avg," << mse.avg() << "," << mae.avg() << "," << edge.avg() - << "," << rec_edge.avg() << "," << node.avg() << "," << ff.avg() << "," << lstm.avg() << "," << ugrnn.avg() - << "," << delta.avg() << "," << mgu.avg() << "," << gru.avg(); + oss << output_name << "," << fix_run_type(run_type) << ",avg," << mse.avg() << "," << mae.avg() << "," << edge.avg() << "," << rec_edge.avg() << "," << node.avg() << "," << ff.avg() << "," << lstm.avg() << "," << ugrnn.avg() << "," << delta.avg() << "," << mgu.avg() << "," << gru.avg(); return oss.str(); } @@ -93,9 +94,8 @@ string RunStatistics::to_string_avg() { string RunStatistics::to_string_max() { ostringstream oss; - oss << output_name << "," << fix_run_type(run_type) << ",max," << mse.max() << "," << mae.max() << "," << edge.max() - << "," << rec_edge.max() << "," << node.max() << "," << ff.max() << "," << lstm.max() << "," << ugrnn.max() - << "," << delta.max() << "," << mgu.max() << "," << gru.max(); + + oss << output_name << "," << fix_run_type(run_type) << ",max," << mse.max() << "," << mae.max() << "," << edge.max() << "," << rec_edge.max() << "," << node.max() << "," << ff.max() << "," << lstm.max() << "," << ugrnn.max() << "," << delta.max() << "," << mgu.max() << "," << gru.max(); return oss.str(); } @@ -103,34 +103,31 @@ string RunStatistics::to_string_max() { string RunStatistics::to_string_stddev() { ostringstream oss; - oss << output_name << "," << fix_run_type(run_type) << ",stddev," << mse.stddev() << "," << mae.stddev() << "," - << edge.stddev() << "," << rec_edge.stddev() << "," << node.stddev() << "," << ff.stddev() << "," - << lstm.stddev() << "," << ugrnn.stddev() << "," << delta.stddev() << "," << mgu.stddev() << "," - << gru.stddev(); + oss << output_name << "," << fix_run_type(run_type) << ",stddev," << mse.stddev() << "," << mae.stddev() << "," << edge.stddev() << "," << rec_edge.stddev() << "," << node.stddev() << "," << ff.stddev() << "," << lstm.stddev() << "," << ugrnn.stddev() << "," << delta.stddev() << "," << mgu.stddev() << "," << gru.stddev(); return oss.str(); } + string RunStatistics::correlate_header() { ostringstream oss; oss << "Prediction & Edges & Rec. Edges & Hidden Nodes & FF & LSTM & UGRNN & Delta & MGU & GRU \\\\"; return oss.str(); } -string RunStatistics::to_string_correlate(string target_name, Tracker& target) { +string RunStatistics::to_string_correlate(string target_name, Tracker &target) { ostringstream oss; - oss << output_name << " & " << edge.correlate(target) << " & " << rec_edge.correlate(target) << " & " - << node.correlate(target) << " & " << ff.correlate(target) << " & " << lstm.correlate(target) << " & " - << ugrnn.correlate(target) << " & " << delta.correlate(target) << " & " << mgu.correlate(target) << " & " - << gru.correlate(target); + oss << output_name << " & " << edge.correlate(target) << " & " << rec_edge.correlate(target) << " & " << node.correlate(target) << " & " << ff.correlate(target) << " & " << lstm.correlate(target) << " & " << ugrnn.correlate(target) << " & " << delta.correlate(target) << " & " << mgu.correlate(target) << " & " << gru.correlate(target); return oss.str(); } + + string RunStatistics::overview_header() { ostringstream oss; - + oss << "\\begin{table*}" << endl; oss << "\\begin{scriptsize}" << endl; oss << "\\centering" << endl; @@ -139,10 +136,10 @@ string RunStatistics::overview_header() { oss << "\\hline" << endl; oss << " " - << " & \\multicolumn{3}{|c|}{MSE}" - << " & \\multicolumn{4}{|c|}{Edges}" - << " & \\multicolumn{4}{|c|}{Rec. Edges}" - << " & \\multicolumn{4}{|c|}{Hidden Nodes}" + << " & \\multicolumn{3}{|c|}{MSE}" + << " & \\multicolumn{4}{|c|}{Edges}" + << " & \\multicolumn{4}{|c|}{Rec. Edges}" + << " & \\multicolumn{4}{|c|}{Hidden Nodes}" << "\\\\" << endl; oss << "\\hline" << endl; @@ -172,21 +169,30 @@ string RunStatistics::overview_footer(string type) { return oss.str(); } + string RunStatistics::to_overview_string() { ostringstream oss; - oss << run_type << " & " << mse.min() << " & " << mse.avg() << " & " << mse.max() << " & " << edge.min() << " & " - << setprecision(2) << edge.avg() << " & " << edge.max() << " & " << setprecision(3) << edge.correlate(mae) - << " & " << rec_edge.min() << " & " << setprecision(2) << rec_edge.avg() << " & " << rec_edge.max() << " & " - << setprecision(3) << rec_edge.correlate(mae) << " & " << node.min() << " & " << setprecision(2) << node.avg() - << " & " << node.max() << " & " << setprecision(3) << node.correlate(mae) << "\\\\"; - + oss << run_type + << " & " << mse.min() << " & " << mse.avg() << " & " << mse.max() + << " & " << edge.min() << " & " << setprecision(2) << edge.avg() << " & " << edge.max() + << " & " << setprecision(3) << edge.correlate(mae) + << " & " << rec_edge.min() << " & " << setprecision(2) << rec_edge.avg() << " & " << rec_edge.max() + << " & " << setprecision(3) << rec_edge.correlate(mae) + << " & " << node.min() << " & " << setprecision(2) << node.avg() << " & " << node.max() + << " & " << setprecision(3) << node.correlate(mae) + << "\\\\"; + return oss.str(); } + + + + string RunStatistics::overview_ff_header() { ostringstream oss; - + oss << "\\begin{table*}" << endl; oss << "\\begin{scriptsize}" << endl; oss << "\\centering" << endl; @@ -195,11 +201,11 @@ string RunStatistics::overview_ff_header() { oss << "\\hline" << endl; oss << " " - << " & \\multicolumn{3}{|c|}{MSE}" - << " & \\multicolumn{4}{|c|}{Edges}" - << " & \\multicolumn{4}{|c|}{Rec. Edges}" - << " & \\multicolumn{4}{|c|}{Memory Nodes}" - << " & \\multicolumn{4}{|c|}{FF Nodes}" + << " & \\multicolumn{3}{|c|}{MSE}" + << " & \\multicolumn{4}{|c|}{Edges}" + << " & \\multicolumn{4}{|c|}{Rec. Edges}" + << " & \\multicolumn{4}{|c|}{Memory Nodes}" + << " & \\multicolumn{4}{|c|}{FF Nodes}" << "\\\\" << endl; oss << "\\hline" << endl; @@ -230,41 +236,45 @@ string RunStatistics::overview_ff_footer(string type) { return oss.str(); } + string RunStatistics::to_overview_ff_string() { ostringstream oss; - oss << run_type << " & " << setprecision(5) << mse.min() << " & " << setprecision(5) << mse.avg() << " & " - << setprecision(5) << mse.max() << " & " << edge.min() << " & " << setprecision(2) << edge.avg() << " & " - << edge.max() << " & " << edge.correlate(mae) << " & " << rec_edge.min() << " & " << setprecision(2) - << rec_edge.avg() << " & " << rec_edge.max() << " & " << setprecision(3) << rec_edge.correlate(mae); + oss << run_type + << " & " << setprecision(5) << mse.min() << " & " << setprecision(5) << mse.avg() << " & " << setprecision(5) << mse.max() + << " & " << edge.min() << " & " << setprecision(2) << edge.avg() << " & " << edge.max() + << " & " << edge.correlate(mae) + << " & " << rec_edge.min() << " & " << setprecision(2) << rec_edge.avg() << " & " << rec_edge.max() + << " & " << setprecision(3) << rec_edge.correlate(mae); if (lstm.max() > 0) { - oss << " & " << lstm.min() << " & " << setprecision(2) << lstm.avg() << " & " << lstm.max() << " & " - << setprecision(3) << lstm.correlate(mae); + oss << " & " << lstm.min() << " & " << setprecision(2) << lstm.avg() << " & " << lstm.max() + << " & " << setprecision(3) << lstm.correlate(mae); } if (ugrnn.max() > 0) { - oss << " & " << ugrnn.min() << " & " << setprecision(2) << ugrnn.avg() << " & " << ugrnn.max() << " & " - << setprecision(3) << ugrnn.correlate(mae); + oss << " & " << ugrnn.min() << " & " << setprecision(2) << ugrnn.avg() << " & " << ugrnn.max() + << " & " << setprecision(3) << ugrnn.correlate(mae); } if (delta.max() > 0) { - oss << " & " << delta.min() << " & " << setprecision(2) << delta.avg() << " & " << delta.max() << " & " - << setprecision(3) << delta.correlate(mae); + oss << " & " << delta.min() << " & " << setprecision(2) << delta.avg() << " & " << delta.max() + << " & " << setprecision(3) << delta.correlate(mae); } if (mgu.max() > 0) { - oss << " & " << mgu.min() << " & " << setprecision(2) << mgu.avg() << " & " << mgu.max() << " & " - << setprecision(3) << mgu.correlate(mae); + oss << " & " << mgu.min() << " & " << setprecision(2) << mgu.avg() << " & " << mgu.max() + << " & " << setprecision(3) << mgu.correlate(mae); } if (gru.max() > 0) { - oss << " & " << gru.min() << " & " << setprecision(2) << gru.avg() << " & " << gru.max() << " & " - << setprecision(3) << gru.correlate(mae); + oss << " & " << gru.min() << " & " << setprecision(2) << gru.avg() << " & " << gru.max() + << " & " << setprecision(3) << gru.correlate(mae); } - oss << " & " << ff.min() << " & " << setprecision(2) << ff.avg() << " & " << ff.max() << " & " << setprecision(3) - << ff.correlate(mae) << "\\\\"; - + oss << " & " << ff.min() << " & " << setprecision(2) << ff.avg() << " & " << ff.max() + << " & " << setprecision(3) << ff.correlate(mae) + << "\\\\"; + return oss.str(); } diff --git a/mpi/run_statistics.hxx b/mpi/run_statistics.hxx index c92e58c1..e11a957d 100644 --- a/mpi/run_statistics.hxx +++ b/mpi/run_statistics.hxx @@ -9,116 +9,130 @@ using std::string; string fix_run_type(string run_type); class ConsolidatedStatistics { - public: - string run_type; + public: + string run_type; - double dfm_min; - double dfm_avg; - double dfm_max; + double dfm_min; + double dfm_avg; + double dfm_max; - ConsolidatedStatistics(string _run_type); + ConsolidatedStatistics(string _run_type); - string to_string_min(); - string to_string_avg(); - string to_string_max(); + string to_string_min(); + string to_string_avg(); + string to_string_max(); }; struct cs_less_than_min { - inline bool operator()(const ConsolidatedStatistics* s1, const ConsolidatedStatistics* s2) { + inline bool operator() (const ConsolidatedStatistics *s1, const ConsolidatedStatistics *s2) + { return (s1->dfm_min < s2->dfm_min); } }; struct cs_less_than_avg { - inline bool operator()(const ConsolidatedStatistics* s1, const ConsolidatedStatistics* s2) { + inline bool operator() (const ConsolidatedStatistics *s1, const ConsolidatedStatistics *s2) + { return (s1->dfm_avg < s2->dfm_avg); } }; struct cs_less_than_max { - inline bool operator()(const ConsolidatedStatistics* s1, const ConsolidatedStatistics* s2) { + inline bool operator() (const ConsolidatedStatistics *s1, const ConsolidatedStatistics *s2) + { return (s1->dfm_max < s2->dfm_max); } }; + class RunStatistics { - public: - string output_name; - string run_type; - - double dfm_min; - double dfm_avg; - double dfm_max; - - Tracker mse; - Tracker mae; - Tracker edge; - Tracker rec_edge; - Tracker node; - Tracker ff; - Tracker lstm; - Tracker ugrnn; - Tracker delta; - Tracker mgu; - Tracker gru; - - RunStatistics(string _output_name, string _run_type); - - void set_deviation_from_mean_min(double _dfm_min); - void set_deviation_from_mean_avg(double _dfm_avg); - void set_deviation_from_mean_max(double _dfm_max); - - string correlate_header(); - - string to_string_min(); - string to_string_avg(); - string to_string_max(); - string to_string_stddev(); - string to_string_correlate(string target_name, Tracker& target); - - string overview_header(); - string overview_footer(string type); - string to_overview_string(); - - string overview_ff_header(); - string overview_ff_footer(string type); - string to_overview_ff_string(); + public: + string output_name; + string run_type; + + double dfm_min; + double dfm_avg; + double dfm_max; + + Tracker mse; + Tracker mae; + Tracker edge; + Tracker rec_edge; + Tracker node; + Tracker ff; + Tracker lstm; + Tracker ugrnn; + Tracker delta; + Tracker mgu; + Tracker gru; + + RunStatistics(string _output_name, string _run_type); + + void set_deviation_from_mean_min(double _dfm_min); + void set_deviation_from_mean_avg(double _dfm_avg); + void set_deviation_from_mean_max(double _dfm_max); + + string correlate_header(); + + string to_string_min(); + string to_string_avg(); + string to_string_max(); + string to_string_stddev(); + string to_string_correlate(string target_name, Tracker &target); + + string overview_header(); + string overview_footer(string type); + string to_overview_string(); + + string overview_ff_header(); + string overview_ff_footer(string type); + string to_overview_ff_string(); }; struct less_than_min { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->mae.min() < s2->mae.min()); } }; struct less_than_avg { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->mae.avg() < s2->mae.avg()); } }; struct less_than_max { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->mae.max() < s2->mae.max()); } }; struct less_than_dfm_min { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->dfm_min < s2->dfm_min); } }; struct less_than_dfm_avg { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->dfm_avg < s2->dfm_avg); } }; struct less_than_dfm_max { - inline bool operator()(const RunStatistics* s1, const RunStatistics* s2) { + inline bool operator() (const RunStatistics *s1, const RunStatistics *s2) + { return (s1->dfm_max < s2->dfm_max); } }; + + + + #endif diff --git a/mpi/test_stream_write.cxx b/mpi/test_stream_write.cxx index e715ae13..45922f02 100644 --- a/mpi/test_stream_write.cxx +++ b/mpi/test_stream_write.cxx @@ -1,8 +1,9 @@ #include + #include +using std::setw; using std::fixed; using std::setprecision; -using std::setw; #include using std::mutex; @@ -16,31 +17,35 @@ using std::thread; #include using std::vector; -#include "common/process_arguments.hxx" -#include "examm/examm.hxx" #include "mpi.h" -#include "rnn/generate_nn.hxx" -#include "time_series/time_series.hxx" + +#include "common/process_arguments.hxx" #include "weights/weight_rules.hxx" #include "weights/weight_update.hxx" +#include "rnn/generate_nn.hxx" +#include "examm/examm.hxx" + +#include "examm/examm.hxx" + +#include "time_series/time_series.hxx" -#define WORK_REQUEST_TAG 1 +#define WORK_REQUEST_TAG 1 #define GENOME_LENGTH_TAG 2 -#define GENOME_TAG 3 -#define TERMINATE_TAG 4 +#define GENOME_TAG 3 +#define TERMINATE_TAG 4 mutex examm_mutex; vector arguments; -EXAMM* examm; +EXAMM *examm; bool finished = false; -vector > > training_inputs; -vector > > training_outputs; -vector > > validation_inputs; -vector > > validation_outputs; +vector< vector< vector > > training_inputs; +vector< vector< vector > > training_outputs; +vector< vector< vector > > validation_inputs; +vector< vector< vector > > validation_outputs; int main(int argc, char** argv) { std::cout << "starting up!" << std::endl; @@ -64,34 +69,33 @@ int main(int argc, char** argv) { std::cout << "initailized log!" << std::endl; - TimeSeriesSets* time_series_sets = NULL; + TimeSeriesSets *time_series_sets = NULL; time_series_sets = TimeSeriesSets::generate_from_arguments(arguments); - get_train_validation_data( - arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs - ); + get_train_validation_data(arguments, time_series_sets, training_inputs, training_outputs, validation_inputs, validation_outputs); - WeightUpdate* weight_update_method = new WeightUpdate(); + WeightUpdate *weight_update_method = new WeightUpdate(); weight_update_method->generate_from_arguments(arguments); - WeightRules* weight_rules = new WeightRules(); - weight_rules->initialize_from_args(arguments); + WeightRules *weight_rules = new WeightRules(); + weight_rules->generate_weight_initialize_from_arguments(arguments); - RNN_Genome* seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); + RNN_Genome *seed_genome = get_seed_genome(arguments, time_series_sets, weight_rules); if (rank == 0) { - // only have the master process print TSS info + //only have the master process print TSS info write_time_series_to_file(arguments, time_series_sets); - } + } Log::clear_rank_restriction(); examm = generate_examm_from_arguments(arguments, time_series_sets, weight_rules, seed_genome); - RNN_Genome* genome = examm->generate_genome(); + RNN_Genome *genome = examm->generate_genome(); - char* byte_array; + char *byte_array; int32_t length; genome->write_to_array(&byte_array, length); + Log::debug("write to array successful!\n"); Log::set_id("main_" + to_string(rank)); diff --git a/mpi/tracker.cxx b/mpi/tracker.cxx index 6127430c..c7e8620d 100644 --- a/mpi/tracker.cxx +++ b/mpi/tracker.cxx @@ -1,4 +1,5 @@ #include + #include using std::vector; @@ -13,12 +14,8 @@ Tracker::Tracker() { } void Tracker::track(double value) { - if (value < _min) { - _min = value; - } - if (value > _max) { - _max = value; - } + if (value < _min) _min = value; + if (value > _max) _max = value; count++; sum += value; @@ -42,7 +39,7 @@ double Tracker::stddev() { double _avg = avg(); double _stddev = 0; - for (int32_t i = 0; i < (int32_t) values.size(); i++) { + for (int32_t i = 0; i < (int32_t)values.size(); i++) { double tmp = (values[i] - _avg); _stddev += tmp * tmp; } @@ -52,7 +49,7 @@ double Tracker::stddev() { return _stddev; } -double Tracker::correlate(Tracker& other) { +double Tracker::correlate(Tracker &other) { double avg1 = avg(); double avg2 = other.avg(); @@ -61,7 +58,7 @@ double Tracker::correlate(Tracker& other) { double correlation = 0.0; - for (int32_t i = 0; i < (int32_t) values.size(); i++) { + for (int32_t i = 0; i < (int32_t)values.size(); i++) { correlation += (values[i] - avg1) * (other.values[i] - avg2); } @@ -69,3 +66,4 @@ double Tracker::correlate(Tracker& other) { return correlation; } + diff --git a/mpi/tracker.hxx b/mpi/tracker.hxx index a5baf44c..db978393 100644 --- a/mpi/tracker.hxx +++ b/mpi/tracker.hxx @@ -7,25 +7,25 @@ using std::vector; #include "stdint.h" class Tracker { - private: - int32_t count; - double _min; - double sum; - double _max; + private: + int32_t count; + double _min; + double sum; + double _max; - vector values; + vector values; - public: - Tracker(); + public: + Tracker(); - void track(double value); + void track(double value); - double min() const; - double max() const; - double avg() const; - double stddev(); + double min() const; + double max() const; + double avg() const; + double stddev(); - double correlate(Tracker& other); + double correlate(Tracker &other); }; #endif diff --git a/rnn/CMakeLists.txt b/rnn/CMakeLists.txt index 04267570..56ca0786 100644 --- a/rnn/CMakeLists.txt +++ b/rnn/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(examm_nn generate_nn.cxx rnn_genome.cxx rnn.cxx lstm_node.cxx ugrnn_node.cxx delta_node.cxx gru_node.cxx enarc_node.cxx enas_dag_node.cxx random_dag_node.cxx mgu_node.cxx dnas_node.cxx mse.cxx rnn_node.cxx rnn_edge.cxx rnn_recurrent_edge.cxx rnn_node_interface.cxx genome_property.cxx) -target_link_libraries(examm_nn exact_time_series exact_weights exact_common) +add_library(examm_nn generate_nn.cxx rnn_genome.cxx rnn.cxx lstm_node.cxx ugrnn_node.cxx delta_node.cxx gru_node.cxx enarc_node.cxx enas_dag_node.cxx random_dag_node.cxx mgu_node.cxx mse.cxx rnn_node.cxx rnn_edge.cxx rnn_recurrent_edge.cxx rnn_node_interface.cxx genome_property.cxx) +target_link_libraries(examm_nn exact_time_series exact_weights exact_common) \ No newline at end of file diff --git a/rnn/delta_node.cxx b/rnn/delta_node.cxx index 1d122889..e5cf9d8b 100644 --- a/rnn/delta_node.cxx +++ b/rnn/delta_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,25 +16,25 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "delta_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "delta_node.hxx" + #define NUMBER_DELTA_WEIGHTS 6 -Delta_Node::Delta_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { +Delta_Node::Delta_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { node_type = DELTA_NODE; } Delta_Node::~Delta_Node() { } -void Delta_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void Delta_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + alpha = bound(normal_distribution.random(generator, mu, sigma)); beta1 = bound(normal_distribution.random(generator, mu, sigma)); beta2 = bound(normal_distribution.random(generator, mu, sigma)); @@ -42,7 +43,8 @@ void Delta_Node::initialize_lamarckian( z_hat_bias = bound(normal_distribution.random(generator, mu, sigma)); } -void Delta_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void Delta_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + alpha = range * (rng_1_1(generator)); beta1 = range * (rng_1_1(generator)); beta2 = range * (rng_1_1(generator)); @@ -51,7 +53,7 @@ void Delta_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distrib z_hat_bias = range * (rng_1_1(generator)); } -void Delta_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void Delta_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range){ alpha = range * normal_distribution.random(generator, 0, 1); beta1 = range * normal_distribution.random(generator, 0, 1); beta2 = range * normal_distribution.random(generator, 0, 1); @@ -60,7 +62,7 @@ void Delta_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& z_hat_bias = range * normal_distribution.random(generator, 0, 1); } -void Delta_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void Delta_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { alpha = rng(generator); beta1 = rng(generator); beta2 = rng(generator); @@ -72,7 +74,7 @@ void Delta_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real double Delta_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "alpha") { gradient_sum += d_alpha[i]; } else if (gradient_name == "beta1") { @@ -103,17 +105,13 @@ void Delta_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on Delta_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on Delta_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update alpha, beta1, beta2 so they're centered around 2, 1 and 1 + //update alpha, beta1, beta2 so they're centered around 2, 1 and 1 alpha += 2; beta1 += 1; beta2 += 1; @@ -121,9 +119,7 @@ void Delta_Node::input_fired(int32_t time, double incoming_output) { double d2 = input_values[time]; double z_prev = 0.0; - if (time > 0) { - z_prev = output_values[time - 1]; - } + if (time > 0) z_prev = output_values[time - 1]; double d1 = v * z_prev; @@ -142,31 +138,27 @@ void Delta_Node::input_fired(int32_t time, double incoming_output) { double z_1 = z_cap[time] * (1 - r[time]); double z_2 = r[time] * z_prev; - // TODO: - // try this with RELU(0 to 6)) or identity + //TODO: + //try this with RELU(0 to 6)) or identity output_values[time] = tanh(z_1 + z_2); ld_z[time] = tanh_derivative(output_values[time]); - // reset alpha, beta1, beta2 so they don't mess with mean/stddev calculations for - // parameter generation + //reset alpha, beta1, beta2 so they don't mess with mean/stddev calculations for + //parameter generation alpha -= 2.0; beta1 -= 1.0; beta2 -= 1.0; } void Delta_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on Delta_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on Delta_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } - // update the alpha and betas to be their actual value + //update the alpha and betas to be their actual value alpha += 2.0; beta1 += 1.0; beta2 += 1.0; @@ -175,17 +167,14 @@ void Delta_Node::try_update_deltas(int32_t time) { double d2 = input_values[time]; double z_prev = 0.0; - if (time > 0) { - z_prev = output_values[time - 1]; - } + if (time > 0) z_prev = output_values[time - 1]; + - // backprop output gate + //backprop output gate double d_z = error; - if (time < (series_length - 1)) { - d_z += d_z_prev[time + 1]; - } - // get the error into the output (z), it's the error from ahead in the network - // as well as from the previous output of the cell + if (time < (series_length - 1)) d_z += d_z_prev[time + 1]; + //get the error into the output (z), it's the error from ahead in the network + //as well as from the previous output of the cell d_z *= ld_z[time]; @@ -196,25 +185,25 @@ void Delta_Node::try_update_deltas(int32_t time) { d_input[time] = d_r; double d_z_cap = d_z * ld_z_cap[time] * (1 - r[time]); - // d_z_hat_bias route + //d_z_hat_bias route d_z_hat_bias[time] = d_z_cap; - // z_hat_3 route + //z_hat_3 route d_input[time] += d_z_cap * beta2; d_beta2[time] = d_z_cap * d2; - // z_hat_1 route + //z_hat_1 route double d1 = v * z_prev; d_input[time] += d_z_cap * alpha * d1; d_alpha[time] = d_z_cap * d2 * d1; - // z_hat_2 route + //z_hat_2 route d_beta1[time] = d_z_cap * d1; double d_d1 = (d_z_cap * beta1) + (d2 * alpha * d_z_cap); d_v[time] = d_d1 * z_prev; d_z_prev[time] += d_d1 * v; - // reset the alpha/betas to be around 0 + //reset the alpha/betas to be around 0 alpha -= 2.0; beta1 -= 1.0; beta2 -= 1.0; @@ -236,23 +225,25 @@ void Delta_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t Delta_Node::get_number_weights() const { return NUMBER_DELTA_WEIGHTS; } -void Delta_Node::get_weights(vector& parameters) const { +void Delta_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void Delta_Node::set_weights(const vector& parameters) { +void Delta_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void Delta_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; + +void Delta_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; alpha = bound(parameters[offset++]); beta1 = bound(parameters[offset++]); @@ -262,12 +253,12 @@ void Delta_Node::set_weights(int32_t& offset, const vector& parameters) r_bias = bound(parameters[offset++]); z_hat_bias = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::trace("set weights from offset %d to %d on Delta_node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("set weights from offset %d to %d on Delta_node %d\n", start_offset, end_offset, innovation_number); } -void Delta_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void Delta_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; parameters[offset++] = alpha; parameters[offset++] = beta1; @@ -277,11 +268,12 @@ void Delta_Node::get_weights(int32_t& offset, vector& parameters) const parameters[offset++] = r_bias; parameters[offset++] = z_hat_bias; - // int32_t end_offset = offset; - // Log::trace("got weights from offset %d to %d on Delta_node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("got weights from offset %d to %d on Delta_node %d\n", start_offset, end_offset, innovation_number); } -void Delta_Node::get_gradients(vector& gradients) { + +void Delta_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_DELTA_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_DELTA_WEIGHTS; i++) { @@ -329,7 +321,7 @@ void Delta_Node::reset(int32_t _series_length) { RNN_Node_Interface* Delta_Node::copy() const { Delta_Node* n = new Delta_Node(innovation_number, layer_type, depth); - // copy Delta_Node values + //copy Delta_Node values n->d_alpha = d_alpha; n->d_beta1 = d_beta1; n->d_beta2 = d_beta2; @@ -344,7 +336,7 @@ RNN_Node_Interface* Delta_Node::copy() const { n->ld_z_cap = ld_z_cap; n->ld_z = ld_z; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -362,6 +354,6 @@ RNN_Node_Interface* Delta_Node::copy() const { return n; } -void Delta_Node::write_to_stream(ostream& out) { +void Delta_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } diff --git a/rnn/delta_node.hxx b/rnn/delta_node.hxx index ef52d06c..cbdc4f01 100644 --- a/rnn/delta_node.hxx +++ b/rnn/delta_node.hxx @@ -12,68 +12,69 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" class Delta_Node : public RNN_Node_Interface { - private: - double alpha; - double beta1; - double beta2; - double v; + private: + double alpha; + double beta1; + double beta2; + double v; + + double r_bias; + double z_hat_bias; + + vector d_alpha; + vector d_beta1; + vector d_beta2; + vector d_v; + vector d_r_bias; + vector d_z_hat_bias; + vector d_z_prev; - double r_bias; - double z_hat_bias; + vector r; + vector ld_r; + vector z_cap; + vector ld_z_cap; + vector ld_z; - vector d_alpha; - vector d_beta1; - vector d_beta2; - vector d_v; - vector d_r_bias; - vector d_z_hat_bias; - vector d_z_prev; + public: - vector r; - vector ld_r; - vector z_cap; - vector ld_z_cap; - vector ld_z; + Delta_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~Delta_Node(); - public: - Delta_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~Delta_Node(); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void input_fired(int32_t time, double incoming_output); - void input_fired(int32_t time, double incoming_output); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + int32_t get_number_weights() const; - int32_t get_number_weights() const; + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_gradients(vector &gradients); - void get_gradients(vector& gradients); + void reset(int32_t _series_length); - void reset(int32_t _series_length); + void write_to_stream(ostream &out); - void write_to_stream(ostream& out); + RNN_Node_Interface* copy() const; - RNN_Node_Interface* copy() const; + friend class RNN_Edge; - friend class RNN_Edge; }; #endif diff --git a/rnn/enarc_node.cxx b/rnn/enarc_node.cxx index 4f32d3ac..3233eb9c 100644 --- a/rnn/enarc_node.cxx +++ b/rnn/enarc_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,25 +16,25 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "enarc_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "enarc_node.hxx" #define NUMBER_ENARC_WEIGHTS 10 -ENARC_Node::ENARC_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { - node_type = ENARC_NODE; +ENARC_Node::ENARC_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { + node_type = ENARC_NODE; } ENARC_Node::~ENARC_Node() { + } -void ENARC_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void ENARC_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + zw = bound(normal_distribution.random(generator, mu, sigma)); rw = bound(normal_distribution.random(generator, mu, sigma)); @@ -49,7 +50,8 @@ void ENARC_Node::initialize_lamarckian( w8 = bound(normal_distribution.random(generator, mu, sigma)); } -void ENARC_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void ENARC_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + zw = range * (rng_1_1(generator)); rw = range * (rng_1_1(generator)); @@ -65,7 +67,7 @@ void ENARC_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distrib w8 = range * (rng_1_1(generator)); } -void ENARC_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void ENARC_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) { zw = range * normal_distribution.random(generator, 0, 1); rw = range * normal_distribution.random(generator, 0, 1); @@ -81,7 +83,7 @@ void ENARC_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& w8 = range * normal_distribution.random(generator, 0, 1); } -void ENARC_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void ENARC_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { zw = rng(generator); rw = rng(generator); @@ -97,9 +99,12 @@ void ENARC_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real w8 = rng(generator); } + + + double ENARC_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "zw") { gradient_sum += d_zw[i]; } else if (gradient_name == "rw") { @@ -117,6 +122,8 @@ double ENARC_Node::get_gradient(string gradient_name) { } else if (gradient_name == "w4") { gradient_sum += d_w4[i]; + + } else if (gradient_name == "w5") { gradient_sum += d_w5[i]; } else if (gradient_name == "w7") { @@ -124,7 +131,7 @@ double ENARC_Node::get_gradient(string gradient_name) { } else if (gradient_name == "w8") { gradient_sum += d_w8[i]; } else { - Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); + Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); exit(1); } } @@ -140,84 +147,80 @@ void ENARC_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on ENARC_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on ENARC_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1; + //update the reset gate bias so its centered around 1 + //r_bias += 1; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; - double xzw = x * zw; - double hrw = h_prev * rw; - double z_sum = hrw + xzw; + double xzw = x*zw; + double hrw = h_prev*rw; + double z_sum = hrw+xzw; - z[time] = tanh(z_sum); - l_d_z[time] = tanh_derivative(z[time]); + z[time] = tanh(z_sum); + l_d_z[time] = tanh_derivative(z[time]); - /**************1st layer ***************/ + /**************1st layer ***************/ - double w1_z_mul = w1 * z[time]; - w1_z[time] = tanh(w1_z_mul); - l_w1_z[time] = tanh_derivative(w1_z[time]); + double w1_z_mul = w1 * z[time]; + w1_z[time] = tanh(w1_z_mul); + l_w1_z[time] = tanh_derivative(w1_z[time]); - // /**************2nd layer ***************/ + // /**************2nd layer ***************/ - double w6_w1_mul = w6 * w1_z[time]; + double w6_w1_mul = w6*w1_z[time]; w6_w1[time] = swish(w6_w1_mul); - l_w6_w1[time] = swish_derivative(w6_w1_mul, w6_w1[time]); + l_w6_w1[time] = swish_derivative(w6_w1_mul,w6_w1[time]); + + double w2_w1_mul = w2*w1_z[time]; + w2_w1[time] = tanh(w2_w1_mul); + l_w2_w1[time] = tanh_derivative(w2_w1[time]); + + double w3_w1_mul = w3*w1_z[time]; + w3_w1[time] = leakyReLU(w3_w1_mul); + l_w3_w1[time] = leakyReLU_derivative(w3_w1[time]); + + + // *************3rd layer ************** + + double w4_w2_mul = w4*w2_w1[time]; + w4_w2[time] = leakyReLU(w4_w2_mul); + l_w4_w2[time] = leakyReLU_derivative(w4_w2[time]); - double w2_w1_mul = w2 * w1_z[time]; - w2_w1[time] = tanh(w2_w1_mul); - l_w2_w1[time] = tanh_derivative(w2_w1[time]); + double w5_w3_mul = w5*w3_w1[time]; + w5_w3[time] = swish(w5_w3_mul); + l_w5_w3[time] = swish_derivative(w5_w3_mul,w5_w3[time]); - double w3_w1_mul = w3 * w1_z[time]; - w3_w1[time] = leakyReLU(w3_w1_mul); - l_w3_w1[time] = leakyReLU_derivative(w3_w1[time]); + double w7_w3_mul = w7*w3_w1[time]; + w7_w3[time] = tanh(w7_w3_mul); + l_w7_w3[time] = tanh_derivative(w7_w3[time]); - // *************3rd layer ************** + double w8_w3_mul = w8*w3_w1[time]; + w8_w3[time] = swish(w8_w3_mul); + l_w8_w3[time] = swish_derivative(w8_w3_mul,w8_w3[time]); - double w4_w2_mul = w4 * w2_w1[time]; - w4_w2[time] = leakyReLU(w4_w2_mul); - l_w4_w2[time] = leakyReLU_derivative(w4_w2[time]); + /**************4rd layer ***************/ - double w5_w3_mul = w5 * w3_w1[time]; - w5_w3[time] = swish(w5_w3_mul); - l_w5_w3[time] = swish_derivative(w5_w3_mul, w5_w3[time]); + output_values[time] = w6_w1[time] + w4_w2[time] + w5_w3[time] + w7_w3[time] + w8_w3[time]; + - double w7_w3_mul = w7 * w3_w1[time]; - w7_w3[time] = tanh(w7_w3_mul); - l_w7_w3[time] = tanh_derivative(w7_w3[time]); - double w8_w3_mul = w8 * w3_w1[time]; - w8_w3[time] = swish(w8_w3_mul); - l_w8_w3[time] = swish_derivative(w8_w3_mul, w8_w3[time]); - /**************4rd layer ***************/ - output_values[time] = w6_w1[time] + w4_w2[time] + w5_w3[time] + w7_w3[time] + w8_w3[time]; } -void ENARC_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on ENARC_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); +void ENARC_Node::try_update_deltas(int32_t time){ + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on ENARC_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } @@ -225,42 +228,39 @@ void ENARC_Node::try_update_deltas(int32_t time) { double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double d_h = error; - if (time < (series_length - 1)) { - d_h += d_h_prev[time + 1]; - } - - // d_h *= 0.2; + if (time < (series_length - 1)) d_h += d_h_prev[time + 1]; - d_w6[time] = d_h * l_w6_w1[time] * w1_z[time]; + //d_h *= 0.2; - d_w8[time] = d_h * l_w8_w3[time] * w3_w1[time]; - d_w7[time] = d_h * l_w7_w3[time] * w3_w1[time]; - d_w5[time] = d_h * l_w5_w3[time] * w3_w1[time]; + d_w6[time] = d_h*l_w6_w1[time]*w1_z[time]; - d_w4[time] = d_h * l_w4_w2[time] * w2_w1[time]; + d_w8[time] = d_h*l_w8_w3[time]*w3_w1[time]; + d_w7[time] = d_h*l_w7_w3[time]*w3_w1[time]; + d_w5[time] = d_h*l_w5_w3[time]*w3_w1[time]; - double d_h_tanh2 = d_h * l_w4_w2[time] * w4; - double d_h_leaky2 = d_h * l_w8_w3[time] * w8 + d_h * l_w7_w3[time] * w7 + d_h * l_w5_w3[time] * w5; + d_w4[time] = d_h*l_w4_w2[time]*w2_w1[time]; - d_w2[time] = d_h_tanh2 * l_w2_w1[time] * w1_z[time]; - d_w3[time] = d_h_leaky2 * l_w3_w1[time] * w1_z[time]; + double d_h_tanh2 = d_h*l_w4_w2[time]*w4; + double d_h_leaky2 = d_h*l_w8_w3[time]*w8 +d_h*l_w7_w3[time]*w7+ d_h*l_w5_w3[time]*w5; + + + d_w2[time] = d_h_tanh2*l_w2_w1[time]*w1_z[time]; + d_w3[time] = d_h_leaky2*l_w3_w1[time]*w1_z[time]; + + double d_h_tanh1 = d_h*l_w6_w1[time]*w6 + d_h_tanh2*l_w2_w1[time]*w2 + d_h_leaky2*l_w3_w1[time]*w3; - double d_h_tanh1 = d_h * l_w6_w1[time] * w6 + d_h_tanh2 * l_w2_w1[time] * w2 + d_h_leaky2 * l_w3_w1[time] * w3; + d_w1[time] = d_h_tanh1*l_w1_z[time]*z[time]; - d_w1[time] = d_h_tanh1 * l_w1_z[time] * z[time]; + double d_h_tanh = d_h_tanh1*l_w1_z[time]*w1; - double d_h_tanh = d_h_tanh1 * l_w1_z[time] * w1; + d_h_prev[time] += d_h_tanh*l_d_z[time]*rw; + d_rw[time] = d_h_tanh*l_d_z[time]*h_prev; - d_h_prev[time] += d_h_tanh * l_d_z[time] * rw; - d_rw[time] = d_h_tanh * l_d_z[time] * h_prev; - - d_input[time] += d_h_tanh * l_d_z[time] * zw; - d_zw[time] = d_h_tanh * l_d_z[time] * x; + d_input[time] += d_h_tanh*l_d_z[time]*zw; + d_zw[time] = d_h_tanh*l_d_z[time]*x; } void ENARC_Node::error_fired(int32_t time, double error) { @@ -279,49 +279,53 @@ void ENARC_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t ENARC_Node::get_number_weights() const { return NUMBER_ENARC_WEIGHTS; } -void ENARC_Node::get_weights(vector& parameters) const { +void ENARC_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void ENARC_Node::set_weights(const vector& parameters) { +void ENARC_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void ENARC_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; +void ENARC_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; + + zw = bound(parameters[offset++]); + rw = bound(parameters[offset++]); - zw = bound(parameters[offset++]); - rw = bound(parameters[offset++]); + w1 = bound(parameters[offset++]); - w1 = bound(parameters[offset++]); + w2 = bound(parameters[offset++]); + w3 = bound(parameters[offset++]); + w6 = bound(parameters[offset++]); - w2 = bound(parameters[offset++]); - w3 = bound(parameters[offset++]); - w6 = bound(parameters[offset++]); + w4 = bound(parameters[offset++]); + w5 = bound(parameters[offset++]); + w7 = bound(parameters[offset++]); + w8 = bound(parameters[offset++]); - w4 = bound(parameters[offset++]); - w5 = bound(parameters[offset++]); - w7 = bound(parameters[offset++]); - w8 = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::trace("set weights from offset %d to %d on ENARC_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("set weights from offset %d to %d on ENARC_Node %d\n", start_offset, end_offset, innovation_number); } -void ENARC_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void ENARC_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; + + parameters[offset++] = zw; parameters[offset++] = rw; - parameters[offset++] = w1; + parameters[offset++] = w1; parameters[offset++] = w2; parameters[offset++] = w3; @@ -332,11 +336,12 @@ void ENARC_Node::get_weights(int32_t& offset, vector& parameters) const parameters[offset++] = w7; parameters[offset++] = w8; - // int32_t end_offset = offset; - // Log::trace("got weights from offset %d to %d on ENARC_Node %d\n", start_offset, end_offset, innovation_number); + + //int32_t end_offset = offset; + //Log::trace("got weights from offset %d to %d on ENARC_Node %d\n", start_offset, end_offset, innovation_number); } -void ENARC_Node::get_gradients(vector& gradients) { +void ENARC_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_ENARC_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_ENARC_WEIGHTS; i++) { @@ -357,6 +362,7 @@ void ENARC_Node::get_gradients(vector& gradients) { gradients[7] += d_w5[i]; gradients[8] += d_w7[i]; gradients[9] += d_w8[i]; + } } @@ -368,15 +374,15 @@ void ENARC_Node::reset(int32_t _series_length) { d_w1.assign(series_length, 0.0); - d_w2.assign(series_length, 0.0); - d_w3.assign(series_length, 0.0); - d_w6.assign(series_length, 0.0); + d_w2.assign(series_length, 0.0); + d_w3.assign(series_length, 0.0); + d_w6.assign(series_length, 0.0); - d_w4.assign(series_length, 0.0); - d_w5.assign(series_length, 0.0); + d_w4.assign(series_length, 0.0); + d_w5.assign(series_length, 0.0); d_w7.assign(series_length, 0.0); - d_w8.assign(series_length, 0.0); - + d_w8.assign(series_length, 0.0); + d_h_prev.assign(series_length, 0.0); z.assign(series_length, 0.0); @@ -406,7 +412,9 @@ void ENARC_Node::reset(int32_t _series_length) { w8_w3.assign(series_length, 0.0); l_w8_w3.assign(series_length, 0.0); - // reset values from rnn_node_interface + + + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -420,7 +428,7 @@ void ENARC_Node::reset(int32_t _series_length) { RNN_Node_Interface* ENARC_Node::copy() const { ENARC_Node* n = new ENARC_Node(innovation_number, layer_type, depth); - // copy ENARC_Node values + //copy ENARC_Node values n->rw = rw; n->zw = zw; n->w1 = w1; @@ -445,39 +453,40 @@ RNN_Node_Interface* ENARC_Node::copy() const { n->d_w4 = d_w4; n->d_w5 = d_w5; - + n->d_w7 = d_w7; n->d_w8 = d_w8; n->d_h_prev = d_h_prev; n->z = z; - n->l_d_z = l_d_z; - + n->l_d_z = l_d_z; + n->w1_z = w1_z; - n->l_w1_z = l_w1_z; - + n->l_w1_z = l_w1_z; + n->w2_w1 = w2_w1; - n->l_w2_w1 = l_w2_w1; - + n->l_w2_w1 = l_w2_w1; + n->w3_w1 = w3_w1; - n->l_w3_w1 = l_w3_w1; - + n->l_w3_w1 = l_w3_w1; + n->w6_w1 = w6_w1; n->l_w6_w1 = l_w6_w1; - + n->w4_w2 = w4_w2; n->l_w4_w2 = l_w4_w2; - + n->w5_w3 = w5_w3; n->l_w5_w3 = l_w5_w3; - + n->w7_w3 = w7_w3; n->l_w7_w3 = l_w7_w3; + + n->w8_w3 = w8_w3; + n->l_w8_w3 = l_w8_w3; - n->w8_w3 = w8_w3; - n->l_w8_w3 = l_w8_w3; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -495,6 +504,7 @@ RNN_Node_Interface* ENARC_Node::copy() const { return n; } -void ENARC_Node::write_to_stream(ostream& out) { +void ENARC_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } + diff --git a/rnn/enarc_node.hxx b/rnn/enarc_node.hxx index 459b6508..b712e959 100644 --- a/rnn/enarc_node.hxx +++ b/rnn/enarc_node.hxx @@ -12,102 +12,107 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" -class ENARC_Node : public RNN_Node_Interface { - private: - double rw; - double zw; +class ENARC_Node : public RNN_Node_Interface{ + private: + + double rw; + double zw; + + double w1; + double w2; + double w3; + double w6; + double w4; + double w5; + double w7; + double w8; - double w1; - double w2; - double w3; - double w6; - double w4; - double w5; - double w7; - double w8; + vector d_zw; + vector d_rw; - vector d_zw; - vector d_rw; + vector d_w1; - vector d_w1; + vector d_w2; + vector d_w3; + vector d_w6; - vector d_w2; - vector d_w3; - vector d_w6; + vector d_w4; + vector d_w5; + vector d_w7; + vector d_w8; + + vector d_h_prev; - vector d_w4; - vector d_w5; - vector d_w7; - vector d_w8; + vector z; + vector l_d_z; - vector d_h_prev; + vector w1_z; + vector l_w1_z; - vector z; - vector l_d_z; + vector w2_w1; + vector l_w2_w1; - vector w1_z; - vector l_w1_z; + vector w3_w1; + vector l_w3_w1; - vector w2_w1; - vector l_w2_w1; + vector w6_w1; + vector l_w6_w1; - vector w3_w1; - vector l_w3_w1; + vector w4_w2; + vector l_w4_w2; - vector w6_w1; - vector l_w6_w1; + vector w5_w3; + vector l_w5_w3; - vector w4_w2; - vector l_w4_w2; + vector w7_w3; + vector l_w7_w3; - vector w5_w3; - vector l_w5_w3; + vector w8_w3; + vector l_w8_w3; - vector w7_w3; - vector l_w7_w3; - vector w8_w3; - vector l_w8_w3; + public: + ENARC_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~ENARC_Node(); - public: - ENARC_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~ENARC_Node(); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - void input_fired(int32_t time, double incoming_output); + void input_fired(int32_t time, double incoming_output); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - int32_t get_number_weights() const; + int32_t get_number_weights() const; - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_gradients(vector& gradients); + void get_gradients(vector &gradients); - void reset(int32_t _series_length); + void reset(int32_t _series_length); - void write_to_stream(ostream& out); + void write_to_stream(ostream &out); - RNN_Node_Interface* copy() const; + RNN_Node_Interface* copy() const; - friend class RNN_Edge; + friend class RNN_Edge; + }; + + #endif diff --git a/rnn/enas_dag_node.cxx b/rnn/enas_dag_node.cxx index 9efa380d..76f81090 100644 --- a/rnn/enas_dag_node.cxx +++ b/rnn/enas_dag_node.cxx @@ -1,14 +1,16 @@ #include + #include +using std::ostream; using std::getline; using std::ifstream; -using std::ostream; -#include +#include using std::cout; using std::endl; + #include using std::setw; @@ -19,80 +21,81 @@ using std::string; using std::minstd_rand0; using std::uniform_real_distribution; + #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "enas_dag_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "enas_dag_node.hxx" #define NUMBER_ENAS_DAG_WEIGHTS 10 -ENAS_DAG_Node::ENAS_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { - node_type = ENAS_DAG_NODE; + +ENAS_DAG_Node::ENAS_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { + node_type = ENAS_DAG_NODE; } -ENAS_DAG_Node::~ENAS_DAG_Node() { +ENAS_DAG_Node::~ENAS_DAG_Node(){ + } -void ENAS_DAG_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void ENAS_DAG_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + zw = bound(normal_distribution.random(generator, mu, sigma)); rw = bound(normal_distribution.random(generator, mu, sigma)); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - weights.at(new_node_weight) = bound(normal_distribution.random(generator, mu, sigma)); + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ + weights.at(new_node_weight)= bound(normal_distribution.random(generator, mu, sigma)); } + } -void ENAS_DAG_Node::initialize_xavier( - minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range -) { +void ENAS_DAG_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { zw = range * (rng_1_1(generator)); rw = range * (rng_1_1(generator)); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = range * (rng_1_1(generator)); } + } -void ENAS_DAG_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void ENAS_DAG_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) { zw = range * normal_distribution.random(generator, 0, 1); rw = range * normal_distribution.random(generator, 0, 1); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = range * normal_distribution.random(generator, 0, 1); } + } -void ENAS_DAG_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void ENAS_DAG_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { zw = rng(generator); rw = rng(generator); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = rng(generator); } } + double ENAS_DAG_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "zw") { gradient_sum += d_zw[i]; } else if (gradient_name == "rw") { @@ -107,15 +110,15 @@ double ENAS_DAG_Node::get_gradient(string gradient_name) { } else if (gradient_name == "w4") { gradient_sum += d_weights[3][i]; } else if (gradient_name == "w5") { - gradient_sum += d_weights[4][i]; + gradient_sum += d_weights[4][i]; } else if (gradient_name == "w6") { gradient_sum += d_weights[5][i]; } else if (gradient_name == "w7") { - gradient_sum += d_weights[6][i]; + gradient_sum += d_weights[6][i]; } else if (gradient_name == "w8") { - gradient_sum += d_weights[7][i]; + gradient_sum += d_weights[7][i]; } else { - Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); + Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); exit(1); } } @@ -127,120 +130,88 @@ void ENAS_DAG_Node::print_gradient(string gradient_name) { } double ENAS_DAG_Node::activation(double value, int32_t act_operator) { - if (act_operator == 0) { - return sigmoid(value); - } - if (act_operator == 1) { - return tanh(value); - } - if (act_operator == 2) { - return swish(value); - } - if (act_operator == 3) { - return leakyReLU(value); - } - if (act_operator == 4) { - return identity(value); - } + if (act_operator == 0) return sigmoid(value); + if (act_operator == 1) return tanh(value); + if (act_operator == 2) return swish(value); + if (act_operator == 3) return leakyReLU(value); + if (act_operator == 4) return identity(value); - Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); + Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); exit(1); } double ENAS_DAG_Node::activation_derivative(double value, double input, int32_t act_operator) { - if (act_operator == 0) { - return sigmoid_derivative(input); - } - if (act_operator == 1) { - return tanh_derivative(input); - } - if (act_operator == 2) { - return swish_derivative(value, input); - } - if (act_operator == 3) { - return leakyReLU_derivative(input); - } - if (act_operator == 4) { - return identity_derivative(); - } + if (act_operator == 0) return sigmoid_derivative(input); + if (act_operator == 1) return tanh_derivative(input); + if (act_operator == 2) return swish_derivative(value,input); + if (act_operator == 3) return leakyReLU_derivative(input); + if (act_operator == 4) return identity_derivative(); - Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); + Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); exit(1); } void ENAS_DAG_Node::input_fired(int32_t time, double incoming_output) { - vector connections{0, 1, 1, 1, 2, 5, 3, 5, 4}; - vector operations{1, 1, 1, 3, 3, 0, 2, 1, 2}; + + vector connections {0,1,1,1,2,5,3,5,4}; + vector operations {1,1,1,3,3,0,2,1,2}; vector node_output(connections.size(), 1); inputs_fired[time]++; input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on ENAS_DAG_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, - time, inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on ENAS_DAG_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1; - int32_t no_of_nodes = (int32_t) connections.size(); - Log::debug( - "ERROR: inputs_fired on ENAS_DAG_Node %d at time %d is %d and no_of_nodes is %d\n", innovation_number, time, - inputs_fired[time], no_of_nodes - ); + //update the reset gate bias so its centered around 1 + //r_bias += 1; + int32_t no_of_nodes = (int32_t)connections.size(); + Log::debug("ERROR: inputs_fired on ENAS_DAG_Node %d at time %d is %d and no_of_nodes is %d\n", innovation_number, time, inputs_fired[time], no_of_nodes); double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; - double xzw = x * zw; - double hrw = h_prev * rw; - double node0_sum = hrw + xzw; + double xzw = x*zw; + double hrw = h_prev*rw; + double node0_sum = hrw+xzw; - Nodes[0][time] = activation(node0_sum, operations[0]); - l_Nodes[0][time] = activation_derivative(node0_sum, Nodes[0][time], operations[0]); + Nodes[0][time] = activation(node0_sum,operations[0]); + l_Nodes[0][time] = activation_derivative(node0_sum,Nodes[0][time],operations[0]); node_output[0] = 0; - for (int32_t i = 1; i < (int32_t) connections.size(); i++) { + for(int32_t i = 1; i < (int32_t)connections.size(); i++){ int32_t incoming_node = connections[i] - 1; - double node_mul = weights[i - 1] * Nodes[incoming_node][time]; - Nodes[i][time] = activation(node_mul, operations[i]); - l_Nodes[i][time] = activation_derivative(node_mul, Nodes[i][time], operations[i]); + double node_mul = weights[i-1]*Nodes[incoming_node][time]; + Nodes[i][time] = activation(node_mul,operations[i]); + l_Nodes[i][time] = activation_derivative(node_mul,Nodes[i][time],operations[i]); node_output[incoming_node] = 0; } - // int32_t fan_out = 0; - for (int32_t i = 0; i < (int32_t) node_output.size(); ++i) { - if (node_output[i]) { - // fan_out ++; - output_values[time] += Nodes[i][time]; - } + //int32_t fan_out = 0; + for (int32_t i = 0; i < (int32_t)node_output.size(); ++i) + { + if(node_output[i]){ + // fan_out ++; + output_values[time] += Nodes[i][time]; + } } // output_values[time] += Nodes[0][time]; // output_values[time] /= fan_out; - Log::debug( - "DEBUG: input_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + Log::debug("DEBUG: input_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); + + } -void ENAS_DAG_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, - time, outputs_fired[time], total_outputs - ); +void ENAS_DAG_Node::try_update_deltas(int32_t time){ + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } @@ -248,45 +219,41 @@ void ENAS_DAG_Node::try_update_deltas(int32_t time) { double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double d_h = error; - if (time < (series_length - 1)) { - d_h += d_h_prev[time + 1]; - } + if (time < (series_length - 1)) d_h += d_h_prev[time + 1]; - // d_h *= fan_out; + //d_h *= fan_out; - vector connections{0, 1, 1, 1, 2, 5, 3, 5, 4}; - int32_t no_of_nodes = (int32_t) connections.size(); - vector node_output(no_of_nodes, 1); - vector d_node_h(no_of_nodes, 0.0); + vector connections {0,1,1,1,2,5,3,5,4}; + int32_t no_of_nodes = (int32_t)connections.size(); + vector node_output(no_of_nodes,1); + vector d_node_h(no_of_nodes,0.0); node_output[0] = 0; - for (int32_t i = 1; i < (int32_t) connections.size(); i++) { + for(int32_t i = 1; i < (int32_t)connections.size();i++){ int32_t incoming_node = connections[i] - 1; node_output[incoming_node] = 0; } - for (int32_t i = 0; i < no_of_nodes; ++i) { - if (node_output[i]) { - d_node_h[i] = d_h; - } + for (int32_t i = 0; i < no_of_nodes; ++i) + { + if(node_output[i]) d_node_h[i] = d_h; } - for (int32_t i = no_of_nodes - 1; i >= 1; i--) { + for (int32_t i = no_of_nodes - 1; i >= 1; i--) + { int32_t incoming_node = connections[i] - 1; - d_weights[i - 1][time] = d_node_h[i] * l_Nodes[i][time] * Nodes[incoming_node][time]; - d_node_h[incoming_node] += d_node_h[i] * l_Nodes[i][time] * weights[i - 1]; + d_weights[i-1][time] = d_node_h[i]*l_Nodes[i][time]*Nodes[incoming_node][time]; + d_node_h[incoming_node] += d_node_h[i]*l_Nodes[i][time]*weights[i-1]; } - d_h_prev[time] += d_node_h[0] * l_Nodes[0][time] * rw; - d_rw[time] = d_node_h[0] * l_Nodes[0][time] * h_prev; + d_h_prev[time] += d_node_h[0]*l_Nodes[0][time]*rw; + d_rw[time] = d_node_h[0]*l_Nodes[0][time]*h_prev; - d_input[time] += d_node_h[0] * l_Nodes[0][time] * zw; - d_zw[time] = d_node_h[0] * l_Nodes[0][time] * x; + d_input[time] += d_node_h[0]*l_Nodes[0][time]*zw; + d_zw[time] = d_node_h[0]*l_Nodes[0][time]*x; // d_h_prev[time] += d_h*l_Nodes[0][time]*rw; // d_rw[time] = d_h*l_Nodes[0][time]*h_prev; @@ -294,10 +261,10 @@ void ENAS_DAG_Node::try_update_deltas(int32_t time) { // d_input[time] += d_h*l_Nodes[0][time]*zw; // d_zw[time] = d_h*l_Nodes[0][time]*x; - Log::debug( - "DEBUG: output_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + + Log::debug("DEBUG: output_fired on ENAS_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); + + } void ENAS_DAG_Node::error_fired(int32_t time, double error) { @@ -316,57 +283,58 @@ void ENAS_DAG_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t ENAS_DAG_Node::get_number_weights() const { return NUMBER_ENAS_DAG_WEIGHTS; } -void ENAS_DAG_Node::get_weights(vector& parameters) const { +void ENAS_DAG_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void ENAS_DAG_Node::set_weights(const vector& parameters) { +void ENAS_DAG_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void ENAS_DAG_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; +void ENAS_DAG_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above zw = bound(parameters[offset++]); rw = bound(parameters[offset++]); - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - if ((int32_t) weights.size() < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights) { - weights.push_back(bound(parameters[offset++])); - } else { - weights.at(new_node_weight) = bound(parameters[offset++]); + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ + if((int32_t)weights.size() < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights){ + weights.push_back(bound(parameters[offset++])); } + else + weights.at(new_node_weight) = bound(parameters[offset++]); } - Log::debug( - "DEBUG: no of weights on ENAS_DAG_Node %d at time %d is %d \n", innovation_number, time, weights.size() - ); + Log::debug("DEBUG: no of weights on ENAS_DAG_Node %d at time %d is %d \n", innovation_number, time, weights.size()); + + } -void ENAS_DAG_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void ENAS_DAG_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; + - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above parameters[offset++] = zw; parameters[offset++] = rw; - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - parameters[offset++] = weights.at(new_node_weight); - } + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_ENAS_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight) + parameters[offset++] = weights.at(new_node_weight); + } -void ENAS_DAG_Node::get_gradients(vector& gradients) { +void ENAS_DAG_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_ENAS_DAG_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_ENAS_DAG_WEIGHTS; i++) { @@ -387,6 +355,7 @@ void ENAS_DAG_Node::get_gradients(vector& gradients) { gradients[7] += d_weights[5][i]; gradients[8] += d_weights[6][i]; gradients[9] += d_weights[7][i]; + } } @@ -396,12 +365,14 @@ void ENAS_DAG_Node::reset(int32_t _series_length) { d_zw.assign(series_length, 0.0); d_rw.assign(series_length, 0.0); - d_weights.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length, 0.0)); + d_weights.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length,0.0)); d_h_prev.assign(series_length, 0.0); - Nodes.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length, 0.0)); - l_Nodes.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length, 0.0)); + Nodes.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length,0.0)); + l_Nodes.assign(NUMBER_ENAS_DAG_WEIGHTS, vector(series_length,0.0)); + - // reset values from rnn_node_interface + + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -415,26 +386,32 @@ void ENAS_DAG_Node::reset(int32_t _series_length) { RNN_Node_Interface* ENAS_DAG_Node::copy() const { ENAS_DAG_Node* n = new ENAS_DAG_Node(innovation_number, layer_type, depth); - // copy ENAS_DAG_Node values + //copy ENAS_DAG_Node values n->rw = rw; n->zw = zw; n->d_zw = d_zw; n->d_rw = d_rw; - for (int32_t i = 0; i < (int32_t) weights.size(); ++i) { + + for (int32_t i = 0; i < (int32_t)weights.size(); ++i) + { n->weights[i] = weights[i]; n->d_weights[i] = d_weights[i]; } + + n->d_h_prev = d_h_prev; - for (int32_t i = 0; i < (int32_t) Nodes.size(); ++i) { + for (int32_t i = 0; i < (int32_t)Nodes.size(); ++i) + { n->Nodes[i] = Nodes[i]; n->l_Nodes[i] = l_Nodes[i]; } - // copy RNN_Node_Interface values + + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -452,6 +429,7 @@ RNN_Node_Interface* ENAS_DAG_Node::copy() const { return n; } -void ENAS_DAG_Node::write_to_stream(ostream& out) { +void ENAS_DAG_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } + diff --git a/rnn/enas_dag_node.hxx b/rnn/enas_dag_node.hxx index 407bafd5..4b2bf726 100644 --- a/rnn/enas_dag_node.hxx +++ b/rnn/enas_dag_node.hxx @@ -12,76 +12,85 @@ using std::uniform_real_distribution; using std::vector; #include -using std::make_pair; using std::pair; +using std::make_pair; + #include "common/random.hxx" + #include "rnn_node_interface.hxx" -class ENAS_DAG_Node : public RNN_Node_Interface { - private: - // starting node 0 - double rw; - double zw; +class ENAS_DAG_Node : public RNN_Node_Interface{ + private: + + // starting node 0 + double rw; + double zw; + + // weights for other nodes + vector weights; - // weights for other nodes - vector weights; - // gradients of starting node 0 - vector d_zw; - vector d_rw; + // gradients of starting node 0 + vector d_zw; + vector d_rw; - // gradients of other nodes - vector> d_weights; + // gradients of other nodes + vector> d_weights; + + // gradient of prev output + vector d_h_prev; - // gradient of prev output - vector d_h_prev; + // output of edge between node with weight wj from node with weight wi + vector> Nodes; + // derivative of edge between node with weight wj from node with weight wi + vector> l_Nodes; - // output of edge between node with weight wj from node with weight wi - vector> Nodes; - // derivative of edge between node with weight wj from node with weight wi - vector> l_Nodes; + + public: - public: - ENAS_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~ENAS_DAG_Node(); + ENAS_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~ENAS_DAG_Node(); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - double activation(double value, int32_t act_operator); - double activation_derivative(double value, double input, int32_t act_operator); - void input_fired(int32_t time, double incoming_output); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + double activation(double value, int32_t act_operator); + double activation_derivative(double value, double input, int32_t act_operator); - int32_t get_number_weights() const; + void input_fired(int32_t time, double incoming_output); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + int32_t get_number_weights() const; - void get_gradients(vector& gradients); + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void reset(int32_t _series_length); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void write_to_stream(ostream& out); + void get_gradients(vector &gradients); - RNN_Node_Interface* copy() const; + void reset(int32_t _series_length); - friend class RNN_Edge; + void write_to_stream(ostream &out); + + RNN_Node_Interface* copy() const; + + friend class RNN_Edge; + }; + + #endif diff --git a/rnn/generate_nn.cxx b/rnn/generate_nn.cxx index c451a098..0c268f67 100644 --- a/rnn/generate_nn.cxx +++ b/rnn/generate_nn.cxx @@ -1,71 +1,85 @@ -#include "rnn/generate_nn.hxx" - -#include #include -#include using std::string; #include using std::vector; -/* - * node_kind is the type of memory cell (e.g. LSTM, UGRNN) - * innovation_counter - reference to an integer used to keep track if innovation numbers. it will be incremented once. - */ -RNN_Node_Interface* create_hidden_node(int32_t node_kind, int32_t& innovation_counter, double depth) { - switch (node_kind) { - case SIMPLE_NODE: - return new RNN_Node(++innovation_counter, HIDDEN_LAYER, depth, SIMPLE_NODE); - case JORDAN_NODE: - return new RNN_Node(++innovation_counter, HIDDEN_LAYER, depth, JORDAN_NODE); - case ELMAN_NODE: - return new RNN_Node(++innovation_counter, HIDDEN_LAYER, depth, ELMAN_NODE); - case UGRNN_NODE: - return new UGRNN_Node(++innovation_counter, HIDDEN_LAYER, depth); - case MGU_NODE: - return new MGU_Node(++innovation_counter, HIDDEN_LAYER, depth); - case GRU_NODE: - return new GRU_Node(++innovation_counter, HIDDEN_LAYER, depth); - case DELTA_NODE: - return new Delta_Node(++innovation_counter, HIDDEN_LAYER, depth); - case LSTM_NODE: - return new LSTM_Node(++innovation_counter, HIDDEN_LAYER, depth); - case ENARC_NODE: - return new ENARC_Node(++innovation_counter, HIDDEN_LAYER, depth); - case ENAS_DAG_NODE: - return new ENAS_DAG_Node(++innovation_counter, HIDDEN_LAYER, depth); - case RANDOM_DAG_NODE: - return new RANDOM_DAG_Node(++innovation_counter, HIDDEN_LAYER, depth); - case DNAS_NODE: - Log::fatal("You shouldn't be creating DNAS nodes using generate_nn::create_hidden_node.\n"); - exit(1); + +#include "rnn/delta_node.hxx" +#include "rnn/ugrnn_node.hxx" +#include "rnn/gru_node.hxx" +#include "rnn/mgu_node.hxx" +#include "rnn/lstm_node.hxx" +#include "rnn/enarc_node.hxx" +#include "rnn/enas_dag_node.hxx" +#include "rnn/random_dag_node.hxx" +#include "rnn/rnn_edge.hxx" +#include "rnn/rnn_genome.hxx" +#include "rnn/rnn_node.hxx" +#include "rnn/rnn_node_interface.hxx" + +#include "common/log.hxx" + +RNN_Genome* create_ff(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating feed forward network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); } -} + current_layer++; -DNASNode* create_dnas_node(int32_t& innovation_counter, double depth, const vector& node_types) { - vector nodes(node_types.size()); + for (int32_t i = 0; i < (int32_t)number_hidden_layers; i++) { + for (int32_t j = 0; j < (int32_t)number_hidden_nodes; j++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, HIDDEN_LAYER, current_layer, SIMPLE_NODE); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); - int i = 0; - for (auto node_type : node_types) { - nodes[i++] = create_hidden_node(node_type, innovation_counter, depth); + for (int32_t d = 1; d <= max_recurrent_depth; d++) { + recurrent_edges.push_back(new RNN_Recurrent_Edge(++edge_innovation_count, d, layer_nodes[current_layer - 1][k], node)); + } + } + + } + current_layer++; } - DNASNode* n = new DNASNode(std::move(nodes), ++innovation_counter, HIDDEN_LAYER, depth); - return n; + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + + for (int32_t d = 1; d <= max_recurrent_depth; d++) { + recurrent_edges.push_back(new RNN_Recurrent_Edge(++edge_innovation_count, d, layer_nodes[current_layer - 1][k], output_node)); + } + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; } -RNN_Genome* create_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, - std::function make_node, WeightRules* weight_rules -) { - Log::debug( - "creating feed forward network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", - input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), - max_recurrent_depth - ); + +RNN_Genome* create_jordan(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating jordan neural network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); vector rnn_nodes; - vector > layer_nodes(2 + number_hidden_layers); + vector output_layer; + vector< vector > layer_nodes(2 + number_hidden_layers); vector rnn_edges; vector recurrent_edges; @@ -73,114 +87,515 @@ RNN_Genome* create_nn( int32_t edge_innovation_count = 0; int32_t current_layer = 0; - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { - RNN_Node* node = - new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); rnn_nodes.push_back(node); layer_nodes[current_layer].push_back(node); } current_layer++; - for (int32_t i = 0; i < (int32_t) number_hidden_layers; i++) { - for (int32_t j = 0; j < (int32_t) number_hidden_nodes; j++) { - RNN_Node_Interface* node = make_node(node_innovation_count, current_layer); + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, HIDDEN_LAYER, current_layer, JORDAN_NODE); rnn_nodes.push_back(node); layer_nodes[current_layer].push_back(node); - for (int32_t k = 0; k < (int32_t) layer_nodes[current_layer - 1].size(); k++) { + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + output_layer.push_back(output_node); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + //connect the output node with recurrent edges to each hidden node + for (int32_t k = 0; k < (int32_t)output_layer.size(); k++) { + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { for (int32_t d = 1; d <= max_recurrent_depth; d++) { - recurrent_edges.push_back( - new RNN_Recurrent_Edge(++edge_innovation_count, d, layer_nodes[current_layer - 1][k], node) - ); + recurrent_edges.push_back(new RNN_Recurrent_Edge(++edge_innovation_count, d, output_layer[k], layer_nodes[i + 1][j])); } } } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + +RNN_Genome* create_elman(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating elman network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector output_layer; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, HIDDEN_LAYER, current_layer, ELMAN_NODE); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } current_layer++; } - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { - RNN_Node* output_node = - new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + output_layer.push_back(output_node); + rnn_nodes.push_back(output_node); - for (int32_t k = 0; k < (int32_t) layer_nodes[current_layer - 1].size(); k++) { + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } - for (int32_t d = 1; d <= max_recurrent_depth; d++) { - recurrent_edges.push_back( - new RNN_Recurrent_Edge(++edge_innovation_count, d, layer_nodes[current_layer - 1][k], output_node) - ); + //recurrently connect every hidden node to every other hidden node + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + + for (int32_t k = 0; k < number_hidden_layers; k++) { + for (int32_t l = 0; l < number_hidden_nodes; l++) { + + for (int32_t d = 1; d <= max_recurrent_depth; d++) { + recurrent_edges.push_back(new RNN_Recurrent_Edge(++edge_innovation_count, d, layer_nodes[i+1][j], layer_nodes[k+1][l])); + } + } + } + + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + +RNN_Genome* create_lstm(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating LSTM network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + LSTM_Node *node = new LSTM_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); } } + current_layer++; } - RNN_Genome* genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); genome->set_parameter_names(input_parameter_names, output_parameter_names); return genome; } -RNN_Genome* create_dnas_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, vector& node_types, - WeightRules* weight_rules -) { - auto f = [&](int32_t& innovation_counter, double depth) -> RNN_Node_Interface* { - return create_dnas_node(innovation_counter, depth, node_types); - }; - - return create_nn( - input_parameter_names, number_hidden_layers, number_hidden_nodes, output_parameter_names, max_recurrent_depth, - f, weight_rules - ); + +RNN_Genome* create_ugrnn(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating UGRNN network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + UGRNN_Node *node = new UGRNN_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; } -RNN_Genome* get_seed_genome( - const vector& arguments, TimeSeriesSets* time_series_sets, WeightRules* weight_rules -) { + + +RNN_Genome* create_gru(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating GRU network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + GRU_Node *node = new GRU_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + +RNN_Genome* create_enarc(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating ENARC network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + ENARC_Node *node = new ENARC_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + +RNN_Genome* create_enas_dag(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating ENAS_DAG network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + Log::debug("creating ENAS_DAG Node\n"); + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + ENAS_DAG_Node *node = new ENAS_DAG_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + + +RNN_Genome* create_random_dag(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating RANDOM_DAG network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + Log::debug("creating RANDOM_DAG Node\n"); + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + RANDOM_DAG_Node *node = new RANDOM_DAG_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + + +RNN_Genome* create_mgu(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating MGU network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + MGU_Node *node = new MGU_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + + +RNN_Genome* create_delta(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules) { + Log::debug("creating delta network with inputs: %d, hidden: %dx%d, outputs: %d, max recurrent depth: %d\n", input_parameter_names.size(), number_hidden_layers, number_hidden_nodes, output_parameter_names.size(), max_recurrent_depth); + vector rnn_nodes; + vector< vector > layer_nodes(2 + number_hidden_layers); + vector rnn_edges; + vector recurrent_edges; + + int32_t node_innovation_count = 0; + int32_t edge_innovation_count = 0; + int32_t current_layer = 0; + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, current_layer, SIMPLE_NODE, input_parameter_names[i]); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + } + current_layer++; + + for (int32_t i = 0; i < number_hidden_layers; i++) { + for (int32_t j = 0; j < number_hidden_nodes; j++) { + Delta_Node *node = new Delta_Node(++node_innovation_count, HIDDEN_LAYER, current_layer); + rnn_nodes.push_back(node); + layer_nodes[current_layer].push_back(node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], node)); + } + } + current_layer++; + } + + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + RNN_Node *output_node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, current_layer, SIMPLE_NODE, output_parameter_names[i]); + rnn_nodes.push_back(output_node); + + for (int32_t k = 0; k < (int32_t)layer_nodes[current_layer - 1].size(); k++) { + rnn_edges.push_back(new RNN_Edge(++edge_innovation_count, layer_nodes[current_layer - 1][k], output_node)); + } + } + + RNN_Genome *genome = new RNN_Genome(rnn_nodes, rnn_edges, recurrent_edges, weight_rules); + genome->set_parameter_names(input_parameter_names, output_parameter_names); + return genome; +} + +RNN_Genome* get_seed_genome(const vector &arguments, TimeSeriesSets *time_series_sets, WeightRules *weight_rules) { Log::info("Generating seed genome\n"); - RNN_Genome* seed_genome = NULL; + RNN_Genome *seed_genome = NULL; string genome_file_name = ""; string transfer_learning_version = ""; if (get_argument(arguments, "--genome_bin", false, genome_file_name)) { - // TODO: update this part and hopefully related arguments could be processed more organized + //TODO: update this part and hopefully related arguments could be processed more organized Log::info("Getting genome bin from arguments, and the seed genome is not minimal \n"); int32_t min_recurrent_depth = 1; get_argument(arguments, "--min_recurrent_depth", false, min_recurrent_depth); int32_t max_recurrent_depth = 10; get_argument(arguments, "--max_recurrent_depth", false, max_recurrent_depth); - + Log::info("genome path is %s\n", genome_file_name.c_str()); bool epigenetic_weights = argument_exists(arguments, "--epigenetic_weights"); Log::info("Using epigeneratic weights is set to: %s \n", epigenetic_weights ? "True" : "False"); seed_genome = new RNN_Genome(genome_file_name); - seed_genome->set_normalize_bounds( - time_series_sets->get_normalize_type(), time_series_sets->get_normalize_mins(), - time_series_sets->get_normalize_maxs(), time_series_sets->get_normalize_avgs(), - time_series_sets->get_normalize_std_devs() - ); + seed_genome->set_normalize_bounds(time_series_sets->get_normalize_type(), time_series_sets->get_normalize_mins(), time_series_sets->get_normalize_maxs(), time_series_sets->get_normalize_avgs(), time_series_sets->get_normalize_std_devs()); get_argument(arguments, "--transfer_learning_version", true, transfer_learning_version); Log::info("Transfer learning version is set to %s\n", transfer_learning_version.c_str()); - // TODO: rewrite the transfer_to() function, could take advantage of the GenomeProperty class and TimeSeriesSets - // class + // TODO: rewrite the transfer_to() function, could take advantage of the GenomeProperty class and TimeSeriesSets class Log::info("Transfering seed genome\n"); - seed_genome->transfer_to( - time_series_sets->get_input_parameter_names(), time_series_sets->get_output_parameter_names(), - transfer_learning_version, epigenetic_weights, min_recurrent_depth, max_recurrent_depth - ); + seed_genome->transfer_to(time_series_sets->get_input_parameter_names(), time_series_sets->get_output_parameter_names(), transfer_learning_version, epigenetic_weights, min_recurrent_depth, max_recurrent_depth); Log::info("Finished transfering seed genome\n"); } else { if (seed_genome == NULL) { - seed_genome = create_ff( - time_series_sets->get_input_parameter_names(), 0, 0, time_series_sets->get_output_parameter_names(), 0, - weight_rules - ); + seed_genome = create_ff(time_series_sets->get_input_parameter_names(), 0, 0, time_series_sets->get_output_parameter_names(), 0, weight_rules); seed_genome->initialize_randomly(); Log::info("Generated seed genome, seed genome is minimal\n"); - } + } } return seed_genome; -} +} \ No newline at end of file diff --git a/rnn/generate_nn.hxx b/rnn/generate_nn.hxx index 87b080c2..995a3cbc 100644 --- a/rnn/generate_nn.hxx +++ b/rnn/generate_nn.hxx @@ -1,98 +1,38 @@ #ifndef RNN_GENERATE_NN_HXX #define RNN_GENERATE_NN_HXX -#include #include using std::string; #include using std::vector; -#include "common/arguments.hxx" -#include "common/log.hxx" -#include "rnn/delta_node.hxx" -#include "rnn/dnas_node.hxx" -#include "rnn/enarc_node.hxx" -#include "rnn/enas_dag_node.hxx" -#include "rnn/gru_node.hxx" -#include "rnn/lstm_node.hxx" -#include "rnn/mgu_node.hxx" -#include "rnn/random_dag_node.hxx" -#include "rnn/rnn_edge.hxx" #include "rnn/rnn_genome.hxx" -#include "rnn/rnn_node.hxx" -#include "rnn/rnn_node_interface.hxx" -#include "rnn/ugrnn_node.hxx" #include "weights/weight_rules.hxx" +#include "common/arguments.hxx" + +RNN_Genome* create_ff(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_jordan(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_elman(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_lstm(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_delta(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_gru(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_enarc(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_enas_dag(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_random_dag(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_mgu(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); + +RNN_Genome* create_ugrnn(const vector &input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, const vector &output_parameter_names, int32_t max_recurrent_depth, WeightRules *weight_rules); -template -NodeT* create_hidden_memory_cell(int32_t& innovation_counter, double depth) { - return new NodeT(++innovation_counter, HIDDEN_LAYER, depth); -} -RNN_Node_Interface* create_hidden_node(int32_t node_kind, int32_t& innovation_counter, double depth); - -RNN_Genome* create_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, - std::function make_node, WeightRules* weight_rules -); - -template -RNN_Genome* create_simple_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, WeightRules* weight_rules -) { - auto f = [=](int32_t& innovation_counter, double depth) -> RNN_Node_Interface* { - return new RNN_Node(++innovation_counter, HIDDEN_LAYER, depth, Kind); - }; - return create_nn( - input_parameter_names, number_hidden_layers, number_hidden_nodes, output_parameter_names, max_recurrent_depth, - f, weight_rules - ); -} - -#define create_ff(...) create_simple_nn(__VA_ARGS__) -#define create_elman(...) create_simple_nn(__VA_ARGS__) -#define create_jordan(...) create_simple_nn(__VA_ARGS__) - -template -RNN_Genome* create_memory_cell_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, WeightRules* weight_rules -) { - auto f = [=](int32_t& innovation_counter, double depth) -> RNN_Node_Interface* { - return create_hidden_memory_cell(innovation_counter, depth); - }; - - return create_nn( - input_parameter_names, number_hidden_layers, number_hidden_nodes, output_parameter_names, max_recurrent_depth, - f, weight_rules - ); -} - -#define create_mgu(...) create_memory_cell_nn(__VA_ARGS__) -#define create_gru(...) create_memory_cell_nn(__VA_ARGS__) -#define create_delta(...) create_memory_cell_nn(__VA_ARGS__) -#define create_lstm(...) create_memory_cell_nn(__VA_ARGS__) -#define create_enarc(...) create_memory_cell_nn(__VA_ARGS__) -#define create_enas_dag(...) create_memory_cell_nn(__VA_ARGS__) -#define create_random_dag(...) create_memory_cell_nn(__VA_ARGS__) -#define create_ugrnn(...) create_memory_cell_nn(__VA_ARGS__) - -DNASNode* create_dnas_node(int32_t& innovation_counter, double depth, const vector& node_types); - -RNN_Genome* create_dnas_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, vector& node_types, - WeightRules* weight_rules -); - -RNN_Genome* create_nn( - const vector& input_parameter_names, int32_t number_hidden_layers, int32_t number_hidden_nodes, - const vector& output_parameter_names, int32_t max_recurrent_depth, WeightRules* weight_rules -); -RNN_Genome* get_seed_genome( - const vector& arguments, TimeSeriesSets* time_series_sets, WeightRules* weight_rules -); +RNN_Genome* get_seed_genome(const vector &arguments, TimeSeriesSets *time_series_sets, WeightRules *weight_rules); #endif diff --git a/rnn/genome_property.cxx b/rnn/genome_property.cxx index 6bf061b9..de009cb0 100644 --- a/rnn/genome_property.cxx +++ b/rnn/genome_property.cxx @@ -1,5 +1,4 @@ #include "rnn/genome_property.hxx" - #include "common/arguments.hxx" #include "common/log.hxx" @@ -10,7 +9,8 @@ GenomeProperty::GenomeProperty() { max_recurrent_depth = 10; } -void GenomeProperty::generate_genome_property_from_arguments(const vector& arguments) { +void GenomeProperty::generate_genome_property_from_arguments(const vector &arguments) { + get_argument(arguments, "--bp_iterations", true, bp_iterations); use_dropout = get_argument(arguments, "--dropout_probability", false, dropout_probability); @@ -18,23 +18,20 @@ void GenomeProperty::generate_genome_property_from_arguments(const vectorset_bp_iterations(bp_iterations); - if (use_dropout) { - genome->enable_dropout(dropout_probability); - } + if (use_dropout) genome->enable_dropout(dropout_probability); genome->normalize_type = normalize_type; genome->set_parameter_names(input_parameter_names, output_parameter_names); genome->set_normalize_bounds(normalize_type, normalize_mins, normalize_maxs, normalize_avgs, normalize_std_devs); } void GenomeProperty::get_time_series_parameters(TimeSeriesSets* time_series_sets) { + input_parameter_names = time_series_sets->get_input_parameter_names(); output_parameter_names = time_series_sets->get_output_parameter_names(); normalize_type = time_series_sets->get_normalize_type(); diff --git a/rnn/genome_property.hxx b/rnn/genome_property.hxx index 7d220ff6..9f780e59 100644 --- a/rnn/genome_property.hxx +++ b/rnn/genome_property.hxx @@ -1,6 +1,7 @@ #ifndef GENOME_PROPERTY_HXX #define GENOME_PROPERTY_HXX + #include using std::vector; @@ -10,32 +11,36 @@ using std::string; #include "rnn/rnn_genome.hxx" #include "time_series/time_series.hxx" -class GenomeProperty { - private: - int32_t bp_iterations; - bool use_dropout; - double dropout_probability; - int32_t min_recurrent_depth; - int32_t max_recurrent_depth; - - // TimeSeriesSets *time_series_sets; - int32_t number_inputs; - int32_t number_outputs; - vector input_parameter_names; - vector output_parameter_names; - - string normalize_type; - map normalize_mins; - map normalize_maxs; - map normalize_avgs; - map normalize_std_devs; - - public: - GenomeProperty(); - void generate_genome_property_from_arguments(const vector& arguments); - void set_genome_properties(RNN_Genome* genome); - void get_time_series_parameters(TimeSeriesSets* time_series_sets); - uniform_int_distribution get_recurrent_depth_dist(); +class GenomeProperty{ + private: + int32_t bp_iterations; + bool use_dropout; + double dropout_probability; + int32_t min_recurrent_depth; + int32_t max_recurrent_depth; + + // TimeSeriesSets *time_series_sets; + int32_t number_inputs; + int32_t number_outputs; + vector input_parameter_names; + vector output_parameter_names; + + string normalize_type; + map normalize_mins; + map normalize_maxs; + map normalize_avgs; + map normalize_std_devs; + + public: + GenomeProperty(); + void generate_genome_property_from_arguments(const vector &arguments); + void set_genome_properties(RNN_Genome *genome); + void get_time_series_parameters(TimeSeriesSets* time_series_sets); + uniform_int_distribution get_recurrent_depth_dist(); }; + + + + #endif \ No newline at end of file diff --git a/rnn/gru_node.cxx b/rnn/gru_node.cxx index 3f1bc055..4f9fcd63 100644 --- a/rnn/gru_node.cxx +++ b/rnn/gru_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,25 +16,25 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "gru_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "gru_node.hxx" + #define NUMBER_GRU_WEIGHTS 9 -GRU_Node::GRU_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { +GRU_Node::GRU_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { node_type = GRU_NODE; } GRU_Node::~GRU_Node() { } -void GRU_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void GRU_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + zw = bound(normal_distribution.random(generator, mu, sigma)); zu = bound(normal_distribution.random(generator, mu, sigma)); z_bias = bound(normal_distribution.random(generator, mu, sigma)); @@ -47,7 +48,8 @@ void GRU_Node::initialize_lamarckian( h_bias = bound(normal_distribution.random(generator, mu, sigma)); } -void GRU_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void GRU_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + zw = range * (rng_1_1(generator)); zu = range * (rng_1_1(generator)); z_bias = range * (rng_1_1(generator)); @@ -59,9 +61,10 @@ void GRU_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribut hw = range * (rng_1_1(generator)); hu = range * (rng_1_1(generator)); h_bias = range * (rng_1_1(generator)); + } -void GRU_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void GRU_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range){ zw = range * normal_distribution.random(generator, 0, 1); zu = range * normal_distribution.random(generator, 0, 1); z_bias = range * normal_distribution.random(generator, 0, 1); @@ -75,7 +78,7 @@ void GRU_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& n h_bias = range * normal_distribution.random(generator, 0, 1); } -void GRU_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void GRU_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { zw = rng(generator); zu = rng(generator); z_bias = rng(generator); @@ -87,12 +90,13 @@ void GRU_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_d hw = rng(generator); hu = rng(generator); h_bias = rng(generator); + } double GRU_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "zw") { gradient_sum += d_zw[i]; } else if (gradient_name == "zu") { @@ -112,7 +116,7 @@ double GRU_Node::get_gradient(string gradient_name) { } else if (gradient_name == "h_bias") { gradient_sum += d_h_bias[i]; } else { - Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); + Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); exit(1); } } @@ -129,25 +133,19 @@ void GRU_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on GRU_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on GRU_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1; + //update the reset gate bias so its centered around 1 + //r_bias += 1; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double hzu = h_prev * zu; double xzw = x * zw; @@ -176,40 +174,32 @@ void GRU_Node::input_fired(int32_t time, double incoming_output) { output_values[time] = z_h_prev + (1 - z[time]) * h_tanh[time]; - // r_bias so it doesn't mess with mean/stddev calculations for - // parameter generation - // r_bias -= 1.0; + //r_bias so it doesn't mess with mean/stddev calculations for + //parameter generation + //r_bias -= 1.0; } void GRU_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on GRU_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on GRU_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1.0; + //update the reset gate bias so its centered around 1 + //r_bias += 1.0; double error = error_values[time]; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; - // backprop output gate + //backprop output gate double d_h = error; - if (time < (series_length - 1)) { - d_h += d_h_prev[time + 1]; - } - // get the error into the output (z), it's the error from ahead in the network - // as well as from the previous output of the cell + if (time < (series_length - 1)) d_h += d_h_prev[time + 1]; + //get the error into the output (z), it's the error from ahead in the network + //as well as from the previous output of the cell d_h_prev[time] = d_h * z[time]; @@ -239,8 +229,8 @@ void GRU_Node::try_update_deltas(int32_t time) { d_rw[time] = d_r * x; d_input[time] += d_r * rw; - // reset the reset gate bias to be around 0 - // r_bias -= 1.0; + //reset the reset gate bias to be around 0 + //r_bias -= 1.0; } void GRU_Node::error_fired(int32_t time, double error) { @@ -259,23 +249,25 @@ void GRU_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t GRU_Node::get_number_weights() const { return NUMBER_GRU_WEIGHTS; } -void GRU_Node::get_weights(vector& parameters) const { +void GRU_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void GRU_Node::set_weights(const vector& parameters) { +void GRU_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void GRU_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; + +void GRU_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; zw = bound(parameters[offset++]); zu = bound(parameters[offset++]); @@ -289,12 +281,13 @@ void GRU_Node::set_weights(int32_t& offset, const vector& parameters) { hu = bound(parameters[offset++]); h_bias = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::trace("set weights from offset %d to %d on GRU_Node %d\n", start_offset, end_offset, innovation_number); + + //int32_t end_offset = offset; + //Log::trace("set weights from offset %d to %d on GRU_Node %d\n", start_offset, end_offset, innovation_number); } -void GRU_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void GRU_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; parameters[offset++] = zw; parameters[offset++] = zu; @@ -308,11 +301,12 @@ void GRU_Node::get_weights(int32_t& offset, vector& parameters) const { parameters[offset++] = hu; parameters[offset++] = h_bias; - // int32_t end_offset = offset; - // Log::trace("got weights from offset %d to %d on GRU_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("got weights from offset %d to %d on GRU_Node %d\n", start_offset, end_offset, innovation_number); } -void GRU_Node::get_gradients(vector& gradients) { + +void GRU_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_GRU_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_GRU_WEIGHTS; i++) { @@ -358,7 +352,7 @@ void GRU_Node::reset(int32_t _series_length) { h_tanh.assign(series_length, 0.0); ld_h_tanh.assign(series_length, 0.0); - // reset values from rnn_node_interface + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -372,7 +366,7 @@ void GRU_Node::reset(int32_t _series_length) { RNN_Node_Interface* GRU_Node::copy() const { GRU_Node* n = new GRU_Node(innovation_number, layer_type, depth); - // copy GRU_Node values + //copy GRU_Node values n->zw = zw; n->zu = zu; n->z_bias = z_bias; @@ -402,7 +396,7 @@ RNN_Node_Interface* GRU_Node::copy() const { n->h_tanh = h_tanh; n->ld_h_tanh = ld_h_tanh; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -420,6 +414,7 @@ RNN_Node_Interface* GRU_Node::copy() const { return n; } -void GRU_Node::write_to_stream(ostream& out) { +void GRU_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } + diff --git a/rnn/gru_node.hxx b/rnn/gru_node.hxx index bbbbcd47..1b067d94 100644 --- a/rnn/gru_node.hxx +++ b/rnn/gru_node.hxx @@ -12,77 +12,78 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" class GRU_Node : public RNN_Node_Interface { - private: - double zw; - double zu; - double z_bias; + private: + double zw; + double zu; + double z_bias; + + double rw; + double ru; + double r_bias; - double rw; - double ru; - double r_bias; + double hw; + double hu; + double h_bias; - double hw; - double hu; - double h_bias; + vector d_zw; + vector d_zu; + vector d_z_bias; + vector d_rw; + vector d_ru; + vector d_r_bias; + vector d_hw; + vector d_hu; + vector d_h_bias; - vector d_zw; - vector d_zu; - vector d_z_bias; - vector d_rw; - vector d_ru; - vector d_r_bias; - vector d_hw; - vector d_hu; - vector d_h_bias; + vector d_h_prev; - vector d_h_prev; + vector z; + vector ld_z; + vector r; + vector ld_r; + vector h_tanh; + vector ld_h_tanh; - vector z; - vector ld_z; - vector r; - vector ld_r; - vector h_tanh; - vector ld_h_tanh; + public: - public: - GRU_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~GRU_Node(); + GRU_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~GRU_Node(); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); + + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void input_fired(int32_t time, double incoming_output); - void input_fired(int32_t time, double incoming_output); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + int32_t get_number_weights() const; - int32_t get_number_weights() const; + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_gradients(vector &gradients); - void get_gradients(vector& gradients); + void reset(int32_t _series_length); - void reset(int32_t _series_length); + void write_to_stream(ostream &out); - void write_to_stream(ostream& out); + RNN_Node_Interface* copy() const; - RNN_Node_Interface* copy() const; + friend class RNN_Edge; - friend class RNN_Edge; }; #endif diff --git a/rnn/lstm_node.cxx b/rnn/lstm_node.cxx index 2dbc3eb9..b1dc258f 100644 --- a/rnn/lstm_node.cxx +++ b/rnn/lstm_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,98 +16,99 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "lstm_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "lstm_node.hxx" + -LSTM_Node::LSTM_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { +LSTM_Node::LSTM_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { node_type = LSTM_NODE; } LSTM_Node::~LSTM_Node() { } -void LSTM_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void LSTM_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + output_gate_update_weight = bound(normal_distribution.random(generator, mu, sigma)); output_gate_weight = bound(normal_distribution.random(generator, mu, sigma)); output_gate_bias = bound(normal_distribution.random(generator, mu, sigma)); - // output_gate_bias = 0.0; + //output_gate_bias = 0.0; input_gate_update_weight = bound(normal_distribution.random(generator, mu, sigma)); input_gate_weight = bound(normal_distribution.random(generator, mu, sigma)); input_gate_bias = bound(normal_distribution.random(generator, mu, sigma)); - // input_gate_bias = 0.0; + //input_gate_bias = 0.0; forget_gate_update_weight = bound(normal_distribution.random(generator, mu, sigma)); forget_gate_weight = bound(normal_distribution.random(generator, mu, sigma)); forget_gate_bias = bound(normal_distribution.random(generator, mu, sigma)); - // forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); + //forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); cell_weight = bound(normal_distribution.random(generator, mu, sigma)); cell_bias = bound(normal_distribution.random(generator, mu, sigma)); - // cell_bias = 0.0; + //cell_bias = 0.0; } -void LSTM_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void LSTM_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + output_gate_update_weight = range * (rng_1_1(generator)); output_gate_weight = range * (rng_1_1(generator)); output_gate_bias = range * (rng_1_1(generator)); - // output_gate_bias = 0.0; + //output_gate_bias = 0.0; input_gate_update_weight = range * (rng_1_1(generator)); input_gate_weight = range * (rng_1_1(generator)); input_gate_bias = range * (rng_1_1(generator)); - // input_gate_bias = 0.0; + //input_gate_bias = 0.0; forget_gate_update_weight = range * (rng_1_1(generator)); forget_gate_weight = range * (rng_1_1(generator)); forget_gate_bias = range * (rng_1_1(generator)); - // forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); + //forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); cell_weight = range * (rng_1_1(generator)); cell_bias = range * (rng_1_1(generator)); } -void LSTM_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void LSTM_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) { output_gate_update_weight = range * normal_distribution.random(generator, 0, 1); output_gate_weight = range * normal_distribution.random(generator, 0, 1); output_gate_bias = range * normal_distribution.random(generator, 0, 1); - // output_gate_bias = 0.0; + //output_gate_bias = 0.0; input_gate_update_weight = range * normal_distribution.random(generator, 0, 1); input_gate_weight = range * normal_distribution.random(generator, 0, 1); input_gate_bias = range * normal_distribution.random(generator, 0, 1); - // input_gate_bias = 0.0; + //input_gate_bias = 0.0; forget_gate_update_weight = range * normal_distribution.random(generator, 0, 1); forget_gate_weight = range * normal_distribution.random(generator, 0, 1); forget_gate_bias = range * normal_distribution.random(generator, 0, 1); - // forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); + //forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); cell_weight = range * normal_distribution.random(generator, 0, 1); cell_bias = range * normal_distribution.random(generator, 0, 1); } -void LSTM_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void LSTM_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { output_gate_update_weight = rng(generator); output_gate_weight = rng(generator); output_gate_bias = rng(generator); - // output_gate_bias = 0.0; + //output_gate_bias = 0.0; input_gate_update_weight = rng(generator); input_gate_weight = rng(generator); input_gate_bias = rng(generator); - // input_gate_bias = 0.0; + //input_gate_bias = 0.0; forget_gate_update_weight = rng(generator); forget_gate_weight = rng(generator); forget_gate_bias = rng(generator); - // forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); + //forget_gate_bias = 1.0 + bound(normal_distribution.random(generator, mu, sigma)); cell_weight = rng(generator); cell_bias = rng(generator); @@ -115,7 +117,7 @@ void LSTM_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_ double LSTM_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "output_gate_update_weight") { gradient_sum += d_output_gate_update_weight[i]; } else if (gradient_name == "output_gate_weight") { @@ -156,43 +158,33 @@ void LSTM_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on LSTM_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on LSTM_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } double input_value = input_values[time]; double previous_cell_value = 0.0; - if (time > 0) { - previous_cell_value = cell_values[time - 1]; - } + if (time > 0) previous_cell_value = cell_values[time - 1]; - // forget gate bias should be around 1.0 intead of 0, but we do it here to not throw - // off the mu/sigma of the parameters + //forget gate bias should be around 1.0 intead of 0, but we do it here to not throw + //off the mu/sigma of the parameters forget_gate_bias = forget_gate_bias + 1.0; - output_gate_values[time] = - sigmoid(output_gate_weight * input_value + output_gate_update_weight * previous_cell_value + output_gate_bias); - input_gate_values[time] = - sigmoid(input_gate_weight * input_value + input_gate_update_weight * previous_cell_value + input_gate_bias); - forget_gate_values[time] = - sigmoid(forget_gate_weight * input_value + forget_gate_update_weight * previous_cell_value + forget_gate_bias); + output_gate_values[time] = sigmoid(output_gate_weight * input_value + output_gate_update_weight * previous_cell_value + output_gate_bias); + input_gate_values[time] = sigmoid(input_gate_weight * input_value + input_gate_update_weight * previous_cell_value + input_gate_bias); + forget_gate_values[time] = sigmoid(forget_gate_weight * input_value + forget_gate_update_weight * previous_cell_value + forget_gate_bias); ld_output_gate[time] = sigmoid_derivative(output_gate_values[time]); ld_input_gate[time] = sigmoid_derivative(input_gate_values[time]); ld_forget_gate[time] = sigmoid_derivative(forget_gate_values[time]); /* - output_gate_values[time] = output_gate_weight * input_value + output_gate_update_weight * previous_cell_value + - output_gate_bias; input_gate_values[time] = input_gate_weight * input_value + input_gate_update_weight * - previous_cell_value + input_gate_bias; forget_gate_values[time] = forget_gate_weight * input_value + - forget_gate_update_weight * previous_cell_value + forget_gate_bias; + output_gate_values[time] = output_gate_weight * input_value + output_gate_update_weight * previous_cell_value + output_gate_bias; + input_gate_values[time] = input_gate_weight * input_value + input_gate_update_weight * previous_cell_value + input_gate_bias; + forget_gate_values[time] = forget_gate_weight * input_value + forget_gate_update_weight * previous_cell_value + forget_gate_bias; ld_output_gate[time] = 1.0; ld_input_gate[time] = 1.0; @@ -202,15 +194,13 @@ void LSTM_Node::input_fired(int32_t time, double incoming_output) { cell_in_tanh[time] = tanh(cell_weight * input_value + cell_bias); ld_cell_in[time] = tanh_derivative(cell_in_tanh[time]); - cell_values[time] = - (forget_gate_values[time] * previous_cell_value) + (input_gate_values[time] * cell_in_tanh[time]); + cell_values[time] = (forget_gate_values[time] * previous_cell_value) + (input_gate_values[time] * cell_in_tanh[time]); - // The original is a hyperbolic tangent, but the peephole[clarification needed] LSTM paper suggests the activation - // function be linear -- activation(x) = x + //The original is a hyperbolic tangent, but the peephole[clarification needed] LSTM paper suggests the activation function be linear -- activation(x) = x cell_out_tanh[time] = cell_values[time]; ld_cell_out[time] = 1.0; - // cell_out_tanh[time] = tanh(cell_values[time]); - // ld_cell_out[time] = tanh_derivative(cell_out_tanh[time]); + //cell_out_tanh[time] = tanh(cell_values[time]); + //ld_cell_out[time] = tanh_derivative(cell_out_tanh[time]); output_values[time] = output_gate_values[time] * cell_out_tanh[time]; @@ -218,13 +208,9 @@ void LSTM_Node::input_fired(int32_t time, double incoming_output) { } void LSTM_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on LSTM_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on LSTM_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } @@ -232,11 +218,9 @@ void LSTM_Node::try_update_deltas(int32_t time) { double input_value = input_values[time]; double previous_cell_value = 0.00; - if (time > 0) { - previous_cell_value = cell_values[time - 1]; - } + if (time > 0) previous_cell_value = cell_values[time - 1]; - // backprop output gate + //backprop output gate double d_output_gate = error * cell_out_tanh[time] * ld_output_gate[time]; d_output_gate_bias[time] = d_output_gate; d_output_gate_update_weight[time] = d_output_gate * previous_cell_value; @@ -244,15 +228,13 @@ void LSTM_Node::try_update_deltas(int32_t time) { d_prev_cell[time] += d_output_gate * output_gate_update_weight; d_input[time] += d_output_gate * output_gate_weight; - // backprop the cell path + //backprop the cell path double d_cell_out = error * output_gate_values[time] * ld_cell_out[time]; - // propagate error back from the next cell value if there is one - if (time < (series_length - 1)) { - d_cell_out += d_prev_cell[time + 1]; - } + //propagate error back from the next cell value if there is one + if (time < (series_length - 1)) d_cell_out += d_prev_cell[time + 1]; - // backprop forget gate + //backprop forget gate d_prev_cell[time] += d_cell_out * forget_gate_values[time]; double d_forget_gate = d_cell_out * previous_cell_value * ld_forget_gate[time]; @@ -262,7 +244,7 @@ void LSTM_Node::try_update_deltas(int32_t time) { d_prev_cell[time] += d_forget_gate * forget_gate_update_weight; d_input[time] += d_forget_gate * forget_gate_weight; - // backprob input gate + //backprob input gate double d_input_gate = d_cell_out * cell_in_tanh[time] * ld_input_gate[time]; d_input_gate_bias[time] = d_input_gate; d_input_gate_update_weight[time] = d_input_gate * previous_cell_value; @@ -270,7 +252,7 @@ void LSTM_Node::try_update_deltas(int32_t time) { d_prev_cell[time] += d_input_gate * input_gate_update_weight; d_input[time] += d_input_gate * input_gate_weight; - // backprop cell input + //backprop cell input double d_cell_in = d_cell_out * input_gate_values[time] * ld_cell_in[time]; d_cell_bias[time] = d_cell_in; d_cell_weight[time] = d_cell_in * input_value; @@ -297,19 +279,20 @@ int32_t LSTM_Node::get_number_weights() const { return 11; } -void LSTM_Node::get_weights(vector& parameters) const { +void LSTM_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void LSTM_Node::set_weights(const vector& parameters) { +void LSTM_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void LSTM_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; + +void LSTM_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; output_gate_update_weight = bound(parameters[offset++]); output_gate_weight = bound(parameters[offset++]); @@ -326,12 +309,12 @@ void LSTM_Node::set_weights(int32_t& offset, const vector& parameters) { cell_weight = bound(parameters[offset++]); cell_bias = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::trace("set weights from offset %d to %d on LSTM_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("set weights from offset %d to %d on LSTM_Node %d\n", start_offset, end_offset, innovation_number); } -void LSTM_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void LSTM_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; parameters[offset++] = output_gate_update_weight; parameters[offset++] = output_gate_weight; @@ -348,11 +331,12 @@ void LSTM_Node::get_weights(int32_t& offset, vector& parameters) const { parameters[offset++] = cell_weight; parameters[offset++] = cell_bias; - // int32_t end_offset = offset; - // Log::trace("got weights from offset %d to %d on LSTM_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("got weights from offset %d to %d on LSTM_Node %d\n", start_offset, end_offset, innovation_number); } -void LSTM_Node::get_gradients(vector& gradients) { + +void LSTM_Node::get_gradients(vector &gradients) { gradients.assign(11, 0.0); for (int32_t i = 0; i < 11; i++) { @@ -424,7 +408,7 @@ void LSTM_Node::reset(int32_t _series_length) { RNN_Node_Interface* LSTM_Node::copy() const { LSTM_Node* n = new LSTM_Node(innovation_number, layer_type, depth); - // copy LSTM_Node values + //copy LSTM_Node values n->output_gate_update_weight = output_gate_update_weight; n->output_gate_weight = output_gate_weight; n->output_gate_bias = output_gate_bias; @@ -471,7 +455,8 @@ RNN_Node_Interface* LSTM_Node::copy() const { n->d_cell_weight = d_cell_weight; n->d_cell_bias = d_cell_bias; - // copy RNN_Node_Interface values + + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -489,6 +474,6 @@ RNN_Node_Interface* LSTM_Node::copy() const { return n; } -void LSTM_Node::write_to_stream(ostream& out) { +void LSTM_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } diff --git a/rnn/lstm_node.hxx b/rnn/lstm_node.hxx index 330d5267..c9c4365f 100644 --- a/rnn/lstm_node.hxx +++ b/rnn/lstm_node.hxx @@ -12,92 +12,92 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" class LSTM_Node : public RNN_Node_Interface { - private: - double output_gate_update_weight; - double output_gate_weight; - double output_gate_bias; + private: + double output_gate_update_weight; + double output_gate_weight; + double output_gate_bias; + + double input_gate_update_weight; + double input_gate_weight; + double input_gate_bias; - double input_gate_update_weight; - double input_gate_weight; - double input_gate_bias; + double forget_gate_update_weight; + double forget_gate_weight; + double forget_gate_bias; - double forget_gate_update_weight; - double forget_gate_weight; - double forget_gate_bias; + double cell_weight; + double cell_bias; - double cell_weight; - double cell_bias; + vector output_gate_values; + vector input_gate_values; + vector forget_gate_values; + vector cell_values; - vector output_gate_values; - vector input_gate_values; - vector forget_gate_values; - vector cell_values; + vector ld_output_gate; + vector ld_input_gate; + vector ld_forget_gate; - vector ld_output_gate; - vector ld_input_gate; - vector ld_forget_gate; + vector cell_in_tanh; + vector cell_out_tanh; + vector ld_cell_in; + vector ld_cell_out; - vector cell_in_tanh; - vector cell_out_tanh; - vector ld_cell_in; - vector ld_cell_out; + vector d_prev_cell; - vector d_prev_cell; + vector d_output_gate_update_weight; + vector d_output_gate_weight; + vector d_output_gate_bias; - vector d_output_gate_update_weight; - vector d_output_gate_weight; - vector d_output_gate_bias; + vector d_input_gate_update_weight; + vector d_input_gate_weight; + vector d_input_gate_bias; - vector d_input_gate_update_weight; - vector d_input_gate_weight; - vector d_input_gate_bias; + vector d_forget_gate_update_weight; + vector d_forget_gate_weight; + vector d_forget_gate_bias; - vector d_forget_gate_update_weight; - vector d_forget_gate_weight; - vector d_forget_gate_bias; + vector d_cell_weight; + vector d_cell_bias; - vector d_cell_weight; - vector d_cell_bias; + public: - public: - LSTM_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~LSTM_Node(); + LSTM_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~LSTM_Node(); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - void input_fired(int32_t time, double incoming_output); + void input_fired(int32_t time, double incoming_output); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - int32_t get_number_weights() const; + int32_t get_number_weights() const; - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_gradients(vector& gradients); + void get_gradients(vector &gradients); - void reset(int32_t _series_length); + void reset(int32_t _series_length); - void write_to_stream(ostream& out); + void write_to_stream(ostream &out); - RNN_Node_Interface* copy() const; + RNN_Node_Interface* copy() const; - friend class RNN_Edge; + friend class RNN_Edge; }; #endif diff --git a/rnn/mgu_node.cxx b/rnn/mgu_node.cxx index e2a246f1..670682da 100644 --- a/rnn/mgu_node.cxx +++ b/rnn/mgu_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,25 +16,25 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "mgu_node.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" +#include "mgu_node.hxx" + #define NUMBER_MGU_WEIGHTS 6 -MGU_Node::MGU_Node(int32_t _innovation_number, int32_t _layer_type, double _depth) - : RNN_Node_Interface(_innovation_number, _layer_type, _depth) { +MGU_Node::MGU_Node(int32_t _innovation_number, int32_t _layer_type, double _depth) : RNN_Node_Interface(_innovation_number, _layer_type, _depth) { node_type = MGU_NODE; } MGU_Node::~MGU_Node() { } -void MGU_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void MGU_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + fw = bound(normal_distribution.random(generator, mu, sigma)); fu = bound(normal_distribution.random(generator, mu, sigma)); f_bias = bound(normal_distribution.random(generator, mu, sigma)); @@ -43,7 +44,8 @@ void MGU_Node::initialize_lamarckian( h_bias = bound(normal_distribution.random(generator, mu, sigma)); } -void MGU_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void MGU_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + fw = range * (rng_1_1(generator)); fu = range * (rng_1_1(generator)); f_bias = range * (rng_1_1(generator)); @@ -51,9 +53,10 @@ void MGU_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribut hw = range * (rng_1_1(generator)); hu = range * (rng_1_1(generator)); h_bias = range * (rng_1_1(generator)); + } -void MGU_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void MGU_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range){ fw = range * normal_distribution.random(generator, 0, 1); fu = range * normal_distribution.random(generator, 0, 1); f_bias = range * normal_distribution.random(generator, 0, 1); @@ -63,7 +66,7 @@ void MGU_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& n h_bias = range * normal_distribution.random(generator, 0, 1); } -void MGU_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void MGU_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { fw = rng(generator); fu = rng(generator); f_bias = rng(generator); @@ -76,7 +79,7 @@ void MGU_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_d double MGU_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "fw") { gradient_sum += d_fw[i]; } else if (gradient_name == "fu") { @@ -107,25 +110,19 @@ void MGU_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on MGU_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on MGU_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1; + //update the reset gate bias so its centered around 1 + //r_bias += 1; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double hfu = h_prev * fu; double xfw = x * fw; @@ -140,17 +137,13 @@ void MGU_Node::input_fired(int32_t time, double incoming_output) { h_tanh[time] = tanh(h_sum); ld_h_tanh[time] = tanh_derivative(h_tanh[time]); - output_values[time] = (1 - f[time]) * h_prev + f[time] * h_tanh[time]; + output_values[time] = (1 - f[time]) * h_prev + f[time] * h_tanh[time]; } void MGU_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on MGU_Node %d at time %d is %d and total_outputs is %d\n:", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on MGU_Node %d at time %d is %d and total_outputs is %d\n:", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } @@ -159,35 +152,33 @@ void MGU_Node::try_update_deltas(int32_t time) { double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; - // backprop output gate + //backprop output gate double d_out = error; - if (time < (series_length - 1)) { - d_out += d_h_prev[time + 1]; - } + if (time < (series_length - 1)) d_out += d_h_prev[time + 1]; + - d_h_prev[time] = d_out * (1 - f[time]); + d_h_prev[time] = d_out * (1-f[time]); - double d_h_tanh = d_out * f[time] * ld_h_tanh[time]; - d_h_bias[time] = d_h_tanh; - d_hw[time] = d_h_tanh * x; - d_hu[time] = d_h_tanh * f[time] * h_prev; - d_input[time] += d_h_tanh * hw; - d_h_prev[time] += d_h_tanh * hu * f[time]; + double d_h_tanh = d_out * f[time] * ld_h_tanh[time]; + d_h_bias[time] = d_h_tanh; + d_hw[time] = d_h_tanh * x; + d_hu[time] = d_h_tanh * f[time] * h_prev; + d_input[time] += d_h_tanh * hw; + d_h_prev[time] += d_h_tanh * hu * f[time]; - double d_f_sigmoid = ((d_out * h_tanh[time]) - (d_out * h_prev)); - d_f_sigmoid += d_h_tanh * hu * h_prev; + double d_f_sigmoid = ((d_out * h_tanh[time]) - (d_out * h_prev)); + d_f_sigmoid += d_h_tanh * hu * h_prev; double d_f = d_f_sigmoid * ld_f[time]; - d_f_bias[time] = d_f; - d_fu[time] = d_f * h_prev; - d_fw[time] = d_f * x; - d_input[time] += d_f * fw; - d_h_prev[time] += d_f * fu; + d_f_bias[time] = d_f; + d_fu[time] = d_f * h_prev; + d_fw[time] = d_f * x; + d_input[time] += d_f * fw; + d_h_prev[time] += d_f * fu; + } void MGU_Node::error_fired(int32_t time, double error) { @@ -206,23 +197,25 @@ void MGU_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t MGU_Node::get_number_weights() const { return NUMBER_MGU_WEIGHTS; } -void MGU_Node::get_weights(vector& parameters) const { +void MGU_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void MGU_Node::set_weights(const vector& parameters) { +void MGU_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void MGU_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; + +void MGU_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; fw = bound(parameters[offset++]); fu = bound(parameters[offset++]); @@ -232,12 +225,13 @@ void MGU_Node::set_weights(int32_t& offset, const vector& parameters) { hu = bound(parameters[offset++]); h_bias = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::trace("set weights from offset %d to %d on MGU_Node %d\n", start_offset, end_offset, innovation_number); + + //int32_t end_offset = offset; + //Log::trace("set weights from offset %d to %d on MGU_Node %d\n", start_offset, end_offset, innovation_number); } -void MGU_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void MGU_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; parameters[offset++] = fw; parameters[offset++] = fu; @@ -247,11 +241,12 @@ void MGU_Node::get_weights(int32_t& offset, vector& parameters) const { parameters[offset++] = hu; parameters[offset++] = h_bias; - // int32_t end_offset = offset; - // Log::trace("got weights from offset %d to %d on MGU_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::trace("got weights from offset %d to %d on MGU_Node %d\n", start_offset, end_offset, innovation_number); } -void MGU_Node::get_gradients(vector& gradients) { + +void MGU_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_MGU_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_MGU_WEIGHTS; i++) { @@ -286,7 +281,7 @@ void MGU_Node::reset(int32_t _series_length) { h_tanh.assign(series_length, 0.0); ld_h_tanh.assign(series_length, 0.0); - // reset values from rnn_node_interface + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -300,7 +295,7 @@ void MGU_Node::reset(int32_t _series_length) { RNN_Node_Interface* MGU_Node::copy() const { MGU_Node* n = new MGU_Node(innovation_number, layer_type, depth); - // copy MGU_Node values + //copy MGU_Node values n->fw = fw; n->fu = fu; n->f_bias = f_bias; @@ -322,7 +317,7 @@ RNN_Node_Interface* MGU_Node::copy() const { n->h_tanh = h_tanh; n->ld_h_tanh = ld_h_tanh; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -340,6 +335,6 @@ RNN_Node_Interface* MGU_Node::copy() const { return n; } -void MGU_Node::write_to_stream(ostream& out) { +void MGU_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } diff --git a/rnn/mgu_node.hxx b/rnn/mgu_node.hxx index cf0c83f2..261df071 100644 --- a/rnn/mgu_node.hxx +++ b/rnn/mgu_node.hxx @@ -12,68 +12,69 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" class MGU_Node : public RNN_Node_Interface { - private: - double fw; - double fu; - double f_bias; + private: + double fw; + double fu; + double f_bias; + + double hw; + double hu; + double h_bias; + + vector d_fw; + vector d_fu; + vector d_f_bias; + vector d_hw; + vector d_hu; + vector d_h_bias; - double hw; - double hu; - double h_bias; + vector d_h_prev; - vector d_fw; - vector d_fu; - vector d_f_bias; - vector d_hw; - vector d_hu; - vector d_h_bias; + vector f; + vector ld_f; + vector h_tanh; + vector ld_h_tanh; - vector d_h_prev; + public: - vector f; - vector ld_f; - vector h_tanh; - vector ld_h_tanh; + MGU_Node(int32_t _innovation_number, int32_t _layer_type, double _depth); + ~MGU_Node(); - public: - MGU_Node(int32_t _innovation_number, int32_t _layer_type, double _depth); - ~MGU_Node(); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void input_fired(int32_t time, double incoming_output); - void input_fired(int32_t time, double incoming_output); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + int32_t get_number_weights() const; - int32_t get_number_weights() const; + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_gradients(vector &gradients); - void get_gradients(vector& gradients); + void reset(int32_t _series_length); - void reset(int32_t _series_length); + void write_to_stream(ostream &out); - void write_to_stream(ostream& out); + RNN_Node_Interface* copy() const; - RNN_Node_Interface* copy() const; + friend class RNN_Edge; - friend class RNN_Edge; }; #endif diff --git a/rnn/min_max_heap.hxx b/rnn/min_max_heap.hxx index 2e63918f..ec6b95aa 100644 --- a/rnn/min_max_heap.hxx +++ b/rnn/min_max_heap.hxx @@ -1,14 +1,15 @@ inline uint32_t log2(uint32_t x) { - // This won't work on non x86 platforms - // https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c + // This won't work on non x86 platforms + // https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c #if defined(__x86_64__) || defined(__i386__) uint32_t y; - asm("\tbsr %1, %0\n" : "=r"(y) : "r"(x)); + asm ( "\tbsr %1, %0\n" + : "=r"(y) + : "r" (x) + ); return y; #else - if (x == 1) { - return 0; - } + if (x == 1) return 0; uint32_t ret = 0; while (x > 1) { x >>= 1; @@ -27,44 +28,30 @@ inline uint32_t log2(uint32_t x) { * * The first layer (e.g. the layer which only contains the root node) contains the maximum element. **/ -template +template class min_max_heap { - typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::const_iterator const_iterator; + vector heap; function less_than; + + static inline uint32_t parent(uint32_t z) { return (z - 1) / 2; } - static inline uint32_t parent(uint32_t z) { - return (z - 1) / 2; - } - - static inline uint32_t left_child(uint32_t z) { - return z + z + 1; - } + static inline uint32_t left_child(uint32_t z) { return z + z + 1; } - static inline uint32_t right_child(uint32_t z) { - return z + z + 2; - } + static inline uint32_t right_child(uint32_t z) { return z + z + 2; } - static inline bool is_on_min_level(uint32_t z) { - return log2(z + 1) % 2 == 1; - } + static inline bool is_on_min_level(uint32_t z) { return log2(z + 1) % 2 == 1; } - static inline bool is_on_max_level(uint32_t z) { - return log2(z + 1) % 2 == 0; - } + static inline bool is_on_max_level(uint32_t z) { return log2(z + 1) % 2 == 0; } - template - void trickle_up_inner(uint32_t z) { - if (z == 0) { - return; - } + template void trickle_up_inner(uint32_t z) { + if (z == 0) return; uint32_t z_grandparent = parent(z); - if (z_grandparent == 0) { - return; - } - + if (z_grandparent == 0) return; + z_grandparent = parent(z_grandparent); if (less_than(heap[z], heap[z_grandparent]) ^ max_level) { @@ -74,9 +61,7 @@ class min_max_heap { } void trickle_up(uint32_t z) { - if (z == 0) { - return; - } + if (z == 0) return; uint32_t z_parent = parent(z); @@ -97,52 +82,42 @@ class min_max_heap { } } - template - void trickle_down_inner(const uint32_t z) { - if (z >= heap.size()) { + template void trickle_down_inner(const uint32_t z) { + if (z >= heap.size()) throw std::invalid_argument("Element specified by z does not exist"); - } uint32_t smallest_node = z; uint32_t left = left_child(z); uint32_t right = left + 1; - if (left < heap.size() && (less_than(heap[left], heap[smallest_node]) ^ max_level)) { + if (left < heap.size() && (less_than(heap[left], heap[smallest_node]) ^ max_level)) smallest_node = left; - } - if (right < heap.size() && (less_than(heap[right], heap[smallest_node]) ^ max_level)) { + if (right < heap.size() && (less_than(heap[right], heap[smallest_node]) ^ max_level)) smallest_node = right; - } uint32_t left_grandchild = left_child(left); - for (uint32_t i = 0; i < 4 && left_grandchild + i < heap.size(); i++) { - if (less_than(heap[left_grandchild + i], heap[smallest_node]) ^ max_level) { + for (uint32_t i = 0; i < 4 && left_grandchild + i < heap.size(); i++) + if (less_than(heap[left_grandchild + i], heap[smallest_node]) ^ max_level) smallest_node = left_grandchild + i; - } - } - - if (z == smallest_node) { - return; - } - + + if (z == smallest_node) return; + std::swap(heap[z], heap[smallest_node]); - if (smallest_node - left > 1) { // smallest node was a grandchild - if (less_than(heap[parent(smallest_node)], heap[smallest_node]) ^ max_level) { + if (smallest_node - left > 1) { // smallest node was a grandchild + if (less_than(heap[parent(smallest_node)], heap[smallest_node]) ^ max_level) std::swap(heap[parent(smallest_node)], heap[smallest_node]); - } trickle_down_inner(smallest_node); } } void trickle_down(uint32_t z) { - if (is_on_min_level(z)) { + if (is_on_min_level(z)) trickle_down_inner(z); - } else { + else trickle_down_inner(z); - } } - + uint32_t find_min_index() const { switch (heap.size()) { case 0: @@ -157,9 +132,8 @@ class min_max_heap { } T delete_element(uint32_t z) { - if (z >= (uint32_t) heap.size()) { + if (z >= (uint32_t) heap.size()) throw std::underflow_error("Cannot delete element from the heap because it does not exist"); - } if (z == heap.size() - 1) { T e = heap.back(); @@ -171,36 +145,32 @@ class min_max_heap { T e = heap.back(); heap.pop_back(); - + trickle_down(z); return e; } - public: +public: + /** * Creates a new min_max_heap. The only parameter is a function that will compare two elements, * and determine if the first is less than the second. This could probably be done in a better way * with generics but I'm not confident in doing so. **/ - min_max_heap(std::function _less_than, uint32_t size_hint = -1) : less_than(_less_than) { - if (size_hint >= 0) { + min_max_heap(std::function _less_than, uint32_t size_hint=-1) + : less_than(_less_than) { + if (size_hint >= 0) heap.reserve(size_hint); - } - } - ~min_max_heap() { } + ~min_max_heap() { } - bool empty() const { - return heap.size() == 0; - } + bool empty() const { return heap.size() == 0; } - uint32_t size() const { - return (uint32_t) heap.size(); - } + uint32_t size() const { return (uint32_t) heap.size(); } /** - * Adds the element e to the heap (in the correct order of course). + * Adds the element e to the heap (in the correct order of course). **/ void enqueue(const T& e) { heap.push_back(e); @@ -208,9 +178,8 @@ class min_max_heap { } const T& find_max() const { - if (empty()) { + if (empty()) throw std::underflow_error("There is no max element because the heap is empty"); - } return heap[0]; } @@ -224,25 +193,21 @@ class min_max_heap { * underflow_error **/ T pop_max() { - if (heap.size() == 0) { + if (heap.size() == 0) throw std::underflow_error("No max element exists because the heap is empty"); - } return delete_element(0); } - T pop() { - return pop_max(); - } + T pop() { return pop_max(); } /** * Returns and removes the minimum item in this min-max heap. If the heap is empty, it will throw * an underflow_error **/ T pop_min() { - if (heap.size() == 0) { + if (heap.size() == 0) throw std::underflow_error("No minimum element exists because the heap is empty"); - } return delete_element(find_min_index()); } @@ -254,9 +219,9 @@ class min_max_heap { const_iterator cbegin() { return heap.begin(); } - + /** - * returns the const_iterator pointing past the end of the underlying vector + * returns the const_iterator pointing past the end of the underlying vector * (i.e. this is an invalid reference). There is no non-const end iterator because the ordering of the * data structure must be preserved. **/ @@ -284,7 +249,7 @@ class min_max_heap { void reserve(size_t n) { heap.reserve(n); } - + /** * Deletes every element in this heap. **/ diff --git a/rnn/mse.cxx b/rnn/mse.cxx index ab7b211c..a65f8315 100644 --- a/rnn/mse.cxx +++ b/rnn/mse.cxx @@ -1,17 +1,17 @@ #include + #include using std::vector; -#include "common/log.hxx" #include "rnn.hxx" -void get_mse(const vector& output_values, const vector& expected, double& mse, vector& deltas) { +void get_mse(const vector &output_values, const vector &expected, double &mse, vector &deltas) { deltas.assign(expected.size(), 0.0); mse = 0.0; double error; - for (int32_t j = 0; j < (int32_t) expected.size(); j++) { + for (int32_t j = 0; j < (int32_t)expected.size(); j++) { error = output_values[j] - expected[j]; deltas[j] = error; @@ -21,21 +21,21 @@ void get_mse(const vector& output_values, const vector& expected mse /= expected.size(); double d_mse = mse * (1.0 / expected.size()) * 2.0; - for (int32_t j = 0; j < (int32_t) expected.size(); j++) { + for (int32_t j = 0; j < (int32_t)expected.size(); j++) { deltas[j] *= d_mse; } } -void get_mse(RNN* genome, const vector >& expected, double& mse_sum, vector >& deltas) { +void get_mse(RNN *genome, const vector< vector > &expected, double &mse_sum, vector< vector > &deltas) { deltas.assign(genome->output_nodes.size(), vector(expected[0].size(), 0.0)); mse_sum = 0.0; double mse; double error; - for (int32_t i = 0; i < (int32_t) genome->output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genome->output_nodes.size(); i++) { mse = 0.0; - for (int32_t j = 0; j < (int32_t) expected[i].size(); j++) { + for (int32_t j = 0; j < (int32_t)expected[i].size(); j++) { error = genome->output_nodes[i]->output_values[j] - expected[i][j]; deltas[i][j] = error; @@ -47,20 +47,20 @@ void get_mse(RNN* genome, const vector >& expected, double& mse_s } double d_mse = mse_sum * (1.0 / expected[0].size()) * 2.0; - for (int32_t i = 0; i < (int32_t) genome->output_nodes.size(); i++) { - for (int32_t j = 0; j < (int32_t) expected[i].size(); j++) { + for (int32_t i = 0; i < (int32_t)genome->output_nodes.size(); i++) { + for (int32_t j = 0; j < (int32_t)expected[i].size(); j++) { deltas[i][j] *= d_mse; } } } -void get_mae(const vector& output_values, const vector& expected, double& mae, vector& deltas) { +void get_mae(const vector &output_values, const vector &expected, double &mae, vector &deltas) { deltas.assign(expected.size(), 0.0); mae = 0.0; double error; - for (int32_t j = 0; j < (int32_t) expected.size(); j++) { + for (int32_t j = 0; j < (int32_t)expected.size(); j++) { error = fabs(output_values[j] - expected[j]); if (error == 0) { deltas[j] = 0; @@ -73,22 +73,22 @@ void get_mae(const vector& output_values, const vector& expected mae /= expected.size(); - double d_mae = mae * (1.0 / (int32_t) expected.size()); - for (int32_t j = 0; j < (int32_t) expected.size(); j++) { + double d_mae = mae * (1.0 / (int32_t)expected.size()); + for (int32_t j = 0; j < (int32_t)expected.size(); j++) { deltas[j] *= d_mae; } } -void get_mae(RNN* genome, const vector >& expected, double& mae_sum, vector >& deltas) { +void get_mae(RNN *genome, const vector< vector > &expected, double &mae_sum, vector< vector > &deltas) { deltas.assign(genome->output_nodes.size(), vector(expected[0].size(), 0.0)); mae_sum = 0.0; double mae; double error; - for (int32_t i = 0; i < (int32_t) genome->output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)genome->output_nodes.size(); i++) { mae = 0.0; - for (int32_t j = 0; j < (int32_t) expected[i].size(); j++) { + for (int32_t j = 0; j <(int32_t) expected[i].size(); j++) { error = fabs(genome->output_nodes[i]->output_values[j] - expected[i][j]); if (error == 0) { deltas[i][j] = 0; @@ -104,8 +104,8 @@ void get_mae(RNN* genome, const vector >& expected, double& mae_s } double d_mae = mae_sum * (1.0 / expected[0].size()); - for (int32_t i = 0; i < (int32_t) genome->output_nodes.size(); i++) { - for (int32_t j = 0; j < (int32_t) expected[i].size(); j++) { + for (int32_t i = 0; i < (int32_t)genome->output_nodes.size(); i++) { + for (int32_t j = 0; j < (int32_t)expected[i].size(); j++) { deltas[i][j] *= d_mae; } } diff --git a/rnn/mse.hxx b/rnn/mse.hxx index ed246974..063dc6f2 100644 --- a/rnn/mse.hxx +++ b/rnn/mse.hxx @@ -6,10 +6,11 @@ using std::vector; #include "rnn.hxx" -void get_mse(const vector& output_values, const vector& expected, double& mse, vector& deltas); -void get_mse(RNN* genome, const vector >& expected, double& mse, vector >& deltas); +void get_mse(const vector &output_values, const vector &expected, double &mse, vector &deltas); +void get_mse(RNN* genome, const vector< vector > &expected, double &mse, vector< vector > &deltas); + +void get_mae(const vector &output_values, const vector &expected, double &mae, vector &deltas); +void get_mae(RNN* genome, const vector< vector > &expected, double &mae, vector< vector > &deltas); -void get_mae(const vector& output_values, const vector& expected, double& mae, vector& deltas); -void get_mae(RNN* genome, const vector >& expected, double& mae, vector >& deltas); #endif diff --git a/rnn/random_dag_node.cxx b/rnn/random_dag_node.cxx index b2947f33..1900dc5d 100644 --- a/rnn/random_dag_node.cxx +++ b/rnn/random_dag_node.cxx @@ -1,14 +1,16 @@ #include + #include +using std::ostream; using std::getline; using std::ifstream; -using std::ostream; -#include +#include using std::cout; using std::endl; + #include using std::setw; @@ -19,82 +21,82 @@ using std::string; using std::minstd_rand0; using std::uniform_real_distribution; + #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" +#include "common/log.hxx" + + +#include "rnn_node_interface.hxx" #include "mse.hxx" #include "random_dag_node.hxx" -#include "rnn_node_interface.hxx" #define NUMBER_RANDOM_DAG_WEIGHTS 10 -RANDOM_DAG_Node::RANDOM_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { - node_type = RANDOM_DAG_NODE; + +RANDOM_DAG_Node::RANDOM_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { + node_type = RANDOM_DAG_NODE; } -RANDOM_DAG_Node::~RANDOM_DAG_Node() { +RANDOM_DAG_Node::~RANDOM_DAG_Node(){ + } -void RANDOM_DAG_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void RANDOM_DAG_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { zw = bound(normal_distribution.random(generator, mu, sigma)); rw = bound(normal_distribution.random(generator, mu, sigma)); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - weights.at(new_node_weight) = bound(normal_distribution.random(generator, mu, sigma)); + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ + weights.at(new_node_weight)= bound(normal_distribution.random(generator, mu, sigma)); } + } -void RANDOM_DAG_Node::initialize_xavier( - minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range -) { +void RANDOM_DAG_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { zw = range * (rng_1_1(generator)); rw = range * (rng_1_1(generator)); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = range * (rng_1_1(generator)); } + } -void RANDOM_DAG_Node::initialize_kaiming( - minstd_rand0& generator, NormalDistribution& normal_distribution, double range -) { +void RANDOM_DAG_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) { zw = range * normal_distribution.random(generator, 0, 1); rw = range * normal_distribution.random(generator, 0, 1); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = range * normal_distribution.random(generator, 0, 1); } + } -void RANDOM_DAG_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void RANDOM_DAG_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { zw = rng(generator); rw = rng(generator); - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ weights.at(new_node_weight) = rng(generator); } } + + + double RANDOM_DAG_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "zw") { gradient_sum += d_zw[i]; } else if (gradient_name == "rw") { @@ -109,15 +111,15 @@ double RANDOM_DAG_Node::get_gradient(string gradient_name) { } else if (gradient_name == "w4") { gradient_sum += d_weights[3][i]; } else if (gradient_name == "w5") { - gradient_sum += d_weights[4][i]; + gradient_sum += d_weights[4][i]; } else if (gradient_name == "w6") { gradient_sum += d_weights[5][i]; } else if (gradient_name == "w7") { - gradient_sum += d_weights[6][i]; + gradient_sum += d_weights[6][i]; } else if (gradient_name == "w8") { - gradient_sum += d_weights[7][i]; + gradient_sum += d_weights[7][i]; } else { - Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); + Log::fatal("ERROR: tried to get unknown gradient: '%s'\n", gradient_name.c_str()); exit(1); } } @@ -129,193 +131,166 @@ void RANDOM_DAG_Node::print_gradient(string gradient_name) { } double RANDOM_DAG_Node::activation(double value, int32_t act_operator) { - if (act_operator == 0) { - return sigmoid(value); - } - if (act_operator == 1) { - return tanh(value); - } - if (act_operator == 2) { - return swish(value); - } - if (act_operator == 3) { - return leakyReLU(value); - } - if (act_operator == 4) { - return identity(value); - } + if (act_operator == 0) return sigmoid(value); + if (act_operator == 1) return tanh(value); + if (act_operator == 2) return swish(value); + if (act_operator == 3) return leakyReLU(value); + if (act_operator == 4) return identity(value); - Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); + Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); exit(1); } double RANDOM_DAG_Node::activation_derivative(double value, double input, int32_t act_operator) { - if (act_operator == 0) { - return sigmoid_derivative(input); - } - if (act_operator == 1) { - return tanh_derivative(input); - } - if (act_operator == 2) { - return swish_derivative(value, input); - } - if (act_operator == 3) { - return leakyReLU_derivative(input); - } - if (act_operator == 4) { - return identity_derivative(); - } + if(act_operator == 0) return sigmoid_derivative(input); + if(act_operator == 1) return tanh_derivative(input); + if(act_operator == 2) return swish_derivative(value,input); + if(act_operator == 3) return leakyReLU_derivative(input); + if(act_operator == 4) return identity_derivative(); - Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); + Log::fatal("ERROR: invalid act_operator: %d\n", act_operator); exit(1); } void RANDOM_DAG_Node::input_fired(int32_t time, double incoming_output) { - vector> connections{ - {0, 0, 0, 0, 0, 1, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 1}, - {0, 0, 0, 0, 0, 0, 0, 0} - }; - vector operations{1, 1, 1, 3, 3, 0, 2, 1, 2}; - int32_t no_of_nodes = (int32_t) connections.size(); - for (int32_t i = 0; i < no_of_nodes; i++) { - if ((int32_t) node_output.size() < no_of_nodes) { - node_output.push_back(1); - } else { + + vector> connections { + {0,0,0,0,0,1,1,1}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,1}, + {0,0,0,0,0,0,0,1}, + {0,0,0,0,0,0,0,0} + }; + vector operations {1,1,1,3,3,0,2,1,2}; + int32_t no_of_nodes = (int32_t)connections.size(); + for(int32_t i = 0;i total_inputs) { - Log::fatal( - "ERROR: inputs_fired on RANDOM_DAG_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, - time, inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on RANDOM_DAG_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // r_bias += 1; + //update the reset gate bias so its centered around 1 + //r_bias += 1; + + Log::debug("ERROR: inputs_fired on RANDOM_DAG_Node %d at time %d is %d and no_of_nodes is %d\n", innovation_number, time, inputs_fired[time], no_of_nodes); - Log::debug( - "inputs_fired on RANDOM_DAG_Node %d at time %d is %d and no_of_nodes is %d\n", innovation_number, time, - inputs_fired[time], no_of_nodes - ); double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; + + double xzw = x*zw; + double hrw = h_prev*rw; + double node0_sum = hrw+xzw; - double xzw = x * zw; - double hrw = h_prev * rw; - double node0_sum = hrw + xzw; - Nodes[0][time] = activation(node0_sum, operations[0]); - l_Nodes[0][time] = activation_derivative(node0_sum, Nodes[0][time], operations[0]); + Nodes[0][time] = activation(node0_sum,operations[0]); + l_Nodes[0][time] = activation_derivative(node0_sum,Nodes[0][time],operations[0]); node_output[0] = 0; - for (int32_t i = 1; i < no_of_nodes; i++) { + for(int32_t i = 1;i < no_of_nodes;i++){ double node_mul = 0; - // std::cout<<"i : "< total_outputs) { - Log::fatal( - "ERROR: outputs_fired on RANDOM_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, - time, outputs_fired[time], total_outputs - ); +void RANDOM_DAG_Node::try_update_deltas(int32_t time){ + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on RANDOM_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } - // Log::info(" trying to update\n"); + //Log::info(" trying to update\n"); double error = error_values[time]; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double d_h = error; - if (time < (series_length - 1)) { - d_h += d_h_prev[time + 1]; - } - - // d_h *= fan_out; - - vector> connections{ - {0, 0, 0, 0, 0, 1, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 1}, - {0, 0, 0, 0, 0, 0, 0, 0} - }; - int32_t no_of_nodes = (int32_t) connections.size(); - vector d_node_h(no_of_nodes, 0.0); - - for (int32_t i = no_of_nodes - 1; i >= 1; i--) { - for (int32_t j = 0; j < no_of_nodes; j++) { - if (connections[i][j]) { + if (time < (series_length - 1)) d_h += d_h_prev[time + 1]; + + //d_h *= fan_out; + + vector> connections { + {0,0,0,0,0,1,1,1}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,1}, + {0,0,0,0,0,0,0,1}, + {0,0,0,0,0,0,0,0} + }; + int32_t no_of_nodes = (int32_t)connections.size(); + vector d_node_h(no_of_nodes,0.0); + + for (int32_t i = no_of_nodes - 1; i >= 1; i--) + { + + for(int32_t j = 0; j < no_of_nodes;j++){ + if(connections[i][j]){ int32_t incoming_node = connections[i][j]; - d_weights[i - 1][time] += d_node_h[i] * l_Nodes[i][time] * Nodes[incoming_node][time]; - d_node_h[incoming_node] += d_node_h[i] * l_Nodes[i][time] * weights[i - 1]; + d_weights[i-1][time] += d_node_h[i]*l_Nodes[i][time]*Nodes[incoming_node][time]; + d_node_h[incoming_node] += d_node_h[i]*l_Nodes[i][time]*weights[i-1]; } + } } - d_h_prev[time] += d_node_h[0] * l_Nodes[0][time] * rw; - d_rw[time] = d_node_h[0] * l_Nodes[0][time] * h_prev; + d_h_prev[time] += d_node_h[0]*l_Nodes[0][time]*rw; + d_rw[time] = d_node_h[0]*l_Nodes[0][time]*h_prev; - d_input[time] += d_node_h[0] * l_Nodes[0][time] * zw; - d_zw[time] = d_node_h[0] * l_Nodes[0][time] * x; + d_input[time] += d_node_h[0]*l_Nodes[0][time]*zw; + d_zw[time] = d_node_h[0]*l_Nodes[0][time]*x; // d_h_prev[time] += d_h*l_Nodes[0][time]*rw; // d_rw[time] = d_h*l_Nodes[0][time]*h_prev; @@ -323,10 +298,10 @@ void RANDOM_DAG_Node::try_update_deltas(int32_t time) { // d_input[time] += d_h*l_Nodes[0][time]*zw; // d_zw[time] = d_h*l_Nodes[0][time]*x; - Log::debug( - "DEBUG: output_fired on RANDOM_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + + Log::debug("DEBUG: output_fired on RANDOM_DAG_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); + + } void RANDOM_DAG_Node::error_fired(int32_t time, double error) { @@ -345,57 +320,58 @@ void RANDOM_DAG_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t RANDOM_DAG_Node::get_number_weights() const { return NUMBER_RANDOM_DAG_WEIGHTS; } -void RANDOM_DAG_Node::get_weights(vector& parameters) const { +void RANDOM_DAG_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void RANDOM_DAG_Node::set_weights(const vector& parameters) { +void RANDOM_DAG_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void RANDOM_DAG_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; +void RANDOM_DAG_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above zw = bound(parameters[offset++]); rw = bound(parameters[offset++]); - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - if ((int32_t) weights.size() < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights) { - weights.push_back(bound(parameters[offset++])); - } else { - weights.at(new_node_weight) = bound(parameters[offset++]); + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight){ + if((int32_t)weights.size() < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights){ + weights.push_back(bound(parameters[offset++])); } + else + weights.at(new_node_weight) = bound(parameters[offset++]); } - Log::debug( - "DEBUG: no of weights on RANDOM_DAG_Node %d at time %d is %d \n", innovation_number, time, weights.size() - ); + Log::debug("DEBUG: no of weights on RANDOM_DAG_Node %d at time %d is %d \n", innovation_number, time, weights.size()); + + } -void RANDOM_DAG_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void RANDOM_DAG_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; - int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above + + + int32_t assigned_node_weights = 2; // 2 weights for the starting node assigned above parameters[offset++] = zw; parameters[offset++] = rw; - for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; - ++new_node_weight) { - parameters[offset++] = weights.at(new_node_weight); - } + for (int32_t new_node_weight = 0; new_node_weight < NUMBER_RANDOM_DAG_WEIGHTS - assigned_node_weights; ++new_node_weight) + parameters[offset++] = weights.at(new_node_weight); + } -void RANDOM_DAG_Node::get_gradients(vector& gradients) { +void RANDOM_DAG_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_RANDOM_DAG_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_RANDOM_DAG_WEIGHTS; i++) { @@ -416,6 +392,7 @@ void RANDOM_DAG_Node::get_gradients(vector& gradients) { gradients[7] += d_weights[5][i]; gradients[8] += d_weights[6][i]; gradients[9] += d_weights[7][i]; + } } @@ -425,12 +402,14 @@ void RANDOM_DAG_Node::reset(int32_t _series_length) { d_zw.assign(series_length, 0.0); d_rw.assign(series_length, 0.0); - d_weights.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length, 0.0)); + d_weights.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length,0.0)); d_h_prev.assign(series_length, 0.0); - Nodes.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length, 0.0)); - l_Nodes.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length, 0.0)); + Nodes.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length,0.0)); + l_Nodes.assign(NUMBER_RANDOM_DAG_WEIGHTS, vector(series_length,0.0)); + - // reset values from rnn_node_interface + + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -444,26 +423,32 @@ void RANDOM_DAG_Node::reset(int32_t _series_length) { RNN_Node_Interface* RANDOM_DAG_Node::copy() const { RANDOM_DAG_Node* n = new RANDOM_DAG_Node(innovation_number, layer_type, depth); - // copy RANDOM_DAG_Node values + //copy RANDOM_DAG_Node values n->rw = rw; n->zw = zw; n->d_zw = d_zw; n->d_rw = d_rw; - for (int32_t i = 0; i < (int32_t) weights.size(); ++i) { + + for (int32_t i = 0; i < (int32_t)weights.size(); ++i) + { n->weights[i] = weights[i]; n->d_weights[i] = d_weights[i]; } + + n->d_h_prev = d_h_prev; - for (int32_t i = 0; i < (int32_t) Nodes.size(); ++i) { + for (int32_t i = 0; i < (int32_t)Nodes.size(); ++i) + { n->Nodes[i] = Nodes[i]; n->l_Nodes[i] = l_Nodes[i]; } - // copy RNN_Node_Interface values + + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -481,6 +466,7 @@ RNN_Node_Interface* RANDOM_DAG_Node::copy() const { return n; } -void RANDOM_DAG_Node::write_to_stream(ostream& out) { +void RANDOM_DAG_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } + diff --git a/rnn/random_dag_node.hxx b/rnn/random_dag_node.hxx index b7b528c5..75de9688 100644 --- a/rnn/random_dag_node.hxx +++ b/rnn/random_dag_node.hxx @@ -12,77 +12,86 @@ using std::uniform_real_distribution; using std::vector; #include -using std::make_pair; using std::pair; +using std::make_pair; + #include "common/random.hxx" + #include "rnn_node_interface.hxx" -class RANDOM_DAG_Node : public RNN_Node_Interface { - private: - vector node_output; - // starting node 0 - double rw; - double zw; +class RANDOM_DAG_Node : public RNN_Node_Interface{ + private: + + vector node_output; + // starting node 0 + double rw; + double zw; + + // weights for other nodes + vector weights; - // weights for other nodes - vector weights; - // gradients of starting node 0 - vector d_zw; - vector d_rw; + // gradients of starting node 0 + vector d_zw; + vector d_rw; - // gradients of other nodes - vector> d_weights; + // gradients of other nodes + vector> d_weights; + + // gradient of prev output + vector d_h_prev; - // gradient of prev output - vector d_h_prev; + // output of edge between node with weight wj from node with weight wi + vector> Nodes; + // derivative of edge between node with weight wj from node with weight wi + vector> l_Nodes; - // output of edge between node with weight wj from node with weight wi - vector> Nodes; - // derivative of edge between node with weight wj from node with weight wi - vector> l_Nodes; + + public: - public: - RANDOM_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~RANDOM_DAG_Node(); + RANDOM_DAG_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~RANDOM_DAG_Node(); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); - double activation(double value, int32_t act_operator); - double activation_derivative(double value, double input, int32_t act_operator); - void input_fired(int32_t time, double incoming_output); + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + double activation(double value, int32_t act_operator); + double activation_derivative(double value, double input, int32_t act_operator); - int32_t get_number_weights() const; + void input_fired(int32_t time, double incoming_output); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + int32_t get_number_weights() const; - void get_gradients(vector& gradients); + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void reset(int32_t _series_length); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void write_to_stream(ostream& out); + void get_gradients(vector &gradients); - RNN_Node_Interface* copy() const; + void reset(int32_t _series_length); - friend class RNN_Edge; + void write_to_stream(ostream &out); + + RNN_Node_Interface* copy() const; + + friend class RNN_Edge; + }; + + #endif diff --git a/rnn/rnn.cxx b/rnn/rnn.cxx index e8353e5b..74a50f6f 100644 --- a/rnn/rnn.cxx +++ b/rnn/rnn.cxx @@ -3,6 +3,7 @@ using std::sort; using std::upper_bound; #include + #include using std::numeric_limits; @@ -11,8 +12,8 @@ using std::fixed; using std::setw; #include -using std::cout; using std::endl; +using std::cout; #include using std::ofstream; @@ -24,66 +25,58 @@ using std::uniform_real_distribution; #include using std::vector; -#include "gru_node.hxx" -#include "lstm_node.hxx" -#include "rnn/rnn_genome.hxx" + #include "rnn_edge.hxx" -#include "rnn_node.hxx" -#include "rnn_node_interface.hxx" #include "rnn_recurrent_edge.hxx" +#include "rnn/rnn_genome.hxx" +#include "rnn_node_interface.hxx" +#include "rnn_node.hxx" +#include "lstm_node.hxx" +#include "gru_node.hxx" // #include "enarc_node.hxx" // #include "enas_dag_node.hxx" -#include "common/log.hxx" +#include "random_dag_node.hxx" #include "mgu_node.hxx" #include "mse.hxx" -#include "random_dag_node.hxx" + +#include "common/log.hxx" + #include "time_series/time_series.hxx" // #include "word_series/word_series.hxx" -void RNN::validate_parameters( - const vector& input_parameter_names, const vector& output_parameter_names -) { - Log::debug( - "validating parameters -- input_parameter_names.size(): %d, output_parameter_names.size(): %d\n", - input_parameter_names.size(), output_parameter_names.size() - ); +void RNN::validate_parameters(const vector &input_parameter_names, const vector &output_parameter_names) { + Log::debug("validating parameters -- input_parameter_names.size(): %d, output_parameter_names.size(): %d\n", input_parameter_names.size(), output_parameter_names.size()); if (Log::at_level(Log::DEBUG)) { Log::debug("\tinput_parameter_names:"); - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { Log::debug("\t\t'%s'\n", input_parameter_names[i].c_str()); } Log::debug("\tinput_node names:"); - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { Log::debug("\t\t'%s'\n", input_nodes[i]->parameter_name.c_str()); } Log::debug("\toutput_parameter_names:"); - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { Log::debug("\t\t'%s'\n", output_parameter_names[i].c_str()); } Log::debug("\toutput_node names:"); - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { Log::debug("\t\t'%s'\n", output_nodes[i]->parameter_name.c_str()); } } if (input_nodes.size() != input_parameter_names.size()) { - Log::fatal( - "ERROR: number of input nodes (%d) != number of input parameters (%d)\n", input_nodes.size(), - input_parameter_names.size() - ); + Log::fatal("ERROR: number of input nodes (%d) != number of input parameters (%d)\n", input_nodes.size(), input_parameter_names.size()); exit(1); } bool parameter_mismatch = false; - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { if (input_nodes[i]->parameter_name.compare(input_parameter_names[i]) != 0) { - Log::fatal( - "ERROR: input_nodes[%d]->parameter_name '%s' != input_parmater_names[%d] '%s'\n", i, - input_nodes[i]->parameter_name.c_str(), i, input_parameter_names[i].c_str() - ); + Log::fatal("ERROR: input_nodes[%d]->parameter_name '%s' != input_parmater_names[%d] '%s'\n", i, input_nodes[i]->parameter_name.c_str(), i, input_parameter_names[i].c_str()); parameter_mismatch = true; } } @@ -92,20 +85,14 @@ void RNN::validate_parameters( } if (output_nodes.size() != output_parameter_names.size()) { - Log::fatal( - "ERROR: number of output nodes (%d) != number of output parameters (%d)\n", output_nodes.size(), - output_parameter_names.size() - ); + Log::fatal("ERROR: number of output nodes (%d) != number of output parameters (%d)\n", output_nodes.size(), output_parameter_names.size()); exit(1); } parameter_mismatch = false; - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { if (output_nodes[i]->parameter_name.compare(output_parameter_names[i]) != 0) { - Log::fatal( - "ERROR: output_nodes[%d]->parameter_name '%s' != output_parmater_names[%d] '%s'\n", i, - output_nodes[i]->parameter_name.c_str(), i, output_parameter_names[i].c_str() - ); + Log::fatal("ERROR: output_nodes[%d]->parameter_name '%s' != output_parmater_names[%d] '%s'\n", i, output_nodes[i]->parameter_name.c_str(), i, output_parameter_names[i].c_str()); parameter_mismatch = true; } } @@ -114,43 +101,36 @@ void RNN::validate_parameters( } } -void RNN::fix_parameter_orders( - const vector& input_parameter_names, const vector& output_parameter_names -) { +void RNN::fix_parameter_orders(const vector &input_parameter_names, const vector &output_parameter_names) { vector ordered_input_nodes; - Log::debug( - "fixing parameter orders -- input_parameter_names.size(): %d, output_parameter_names.size(): %d\n", - input_parameter_names.size(), output_parameter_names.size() - ); + Log::debug("fixing parameter orders -- input_parameter_names.size(): %d, output_parameter_names.size(): %d\n", input_parameter_names.size(), output_parameter_names.size()); if (Log::at_level(Log::DEBUG)) { Log::debug("\tinput_parameter_names:"); - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { Log::debug("\t\t'%s'\n", input_parameter_names[i].c_str()); } Log::debug("\tinput_node names:"); - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { Log::debug("\t\t'%s'\n", input_nodes[i]->parameter_name.c_str()); } Log::debug("\toutput_parameter_names:"); - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { Log::debug("\t\t'%s'\n", output_parameter_names[i].c_str()); } Log::debug("\toutput_node names:"); - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { Log::debug("\t\t'%s'\n", output_nodes[i]->parameter_name.c_str()); } } - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { - for (int32_t j = (int32_t) input_nodes.size() - 1; j >= 0; j--) { - Log::debug( - "checking input node name '%s' vs parameter name '%s'\n", input_nodes[j]->parameter_name.c_str(), - input_parameter_names[i].c_str() - ); + + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { + for (int32_t j = (int32_t)input_nodes.size() - 1; j >= 0; j--) { + Log::debug("checking input node name '%s' vs parameter name '%s'\n", input_nodes[j]->parameter_name.c_str(), input_parameter_names[i].c_str()); if (input_nodes[j]->parameter_name.compare(input_parameter_names[i]) == 0) { Log::debug("erasing node!\n"); @@ -164,8 +144,8 @@ void RNN::fix_parameter_orders( vector ordered_output_nodes; - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { - for (int32_t j = (int32_t) output_nodes.size() - 1; j >= 0; j--) { + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + for (int32_t j = (int32_t)output_nodes.size() - 1; j >= 0; j--) { if (output_nodes[j]->parameter_name.compare(output_parameter_names[i]) == 0) { ordered_output_nodes.push_back(output_nodes[j]); output_nodes.erase(output_nodes.begin() + j); @@ -176,17 +156,14 @@ void RNN::fix_parameter_orders( output_nodes = ordered_output_nodes; } -RNN::RNN( - vector& _nodes, vector& _edges, const vector& input_parameter_names, - const vector& output_parameter_names -) { +RNN::RNN(vector &_nodes, vector &_edges, const vector &input_parameter_names, const vector &output_parameter_names) { nodes = _nodes; edges = _edges; - // sort edges by depth + //sort edges by depth sort(edges.begin(), edges.end(), sort_RNN_Edges_by_depth()); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->layer_type == INPUT_LAYER) { input_nodes.push_back(nodes[i]); } else if (nodes[i]->layer_type == OUTPUT_LAYER) { @@ -198,19 +175,16 @@ RNN::RNN( validate_parameters(input_parameter_names, output_parameter_names); } -RNN::RNN( - vector& _nodes, vector& _edges, vector& _recurrent_edges, - const vector& input_parameter_names, const vector& output_parameter_names -) { +RNN::RNN(vector &_nodes, vector &_edges, vector &_recurrent_edges, const vector &input_parameter_names, const vector &output_parameter_names) { nodes = _nodes; edges = _edges; recurrent_edges = _recurrent_edges; - // sort nodes by depth - // sort edges by depth + //sort nodes by depth + //sort edges by depth Log::debug("creating rnn with %d nodes, %d edges\n", nodes.size(), edges.size()); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->layer_type == INPUT_LAYER) { input_nodes.push_back(nodes[i]); Log::debug("had input node!\n"); @@ -225,13 +199,11 @@ RNN::RNN( Log::debug("validating parameters, input_node.size: %d\n", input_nodes.size()); validate_parameters(input_parameter_names, output_parameter_names); - Log::trace( - "got RNN with %d nodes, %d edges, %d recurrent edges\n", nodes.size(), edges.size(), recurrent_edges.size() - ); + Log::trace("got RNN with %d nodes, %d edges, %d recurrent edges\n", nodes.size(), edges.size(), recurrent_edges.size()); } RNN::~RNN() { - RNN_Node_Interface* node; + RNN_Node_Interface *node; while (nodes.size() > 0) { node = nodes.back(); @@ -239,7 +211,7 @@ RNN::~RNN() { delete node; } - RNN_Edge* edge; + RNN_Edge *edge; while (edges.size() > 0) { edge = edges.back(); @@ -247,7 +219,7 @@ RNN::~RNN() { delete edge; } - RNN_Recurrent_Edge* recurrent_edge; + RNN_Recurrent_Edge *recurrent_edge; while (recurrent_edges.size() > 0) { recurrent_edge = recurrent_edges.back(); @@ -255,20 +227,17 @@ RNN::~RNN() { delete recurrent_edge; } - while (input_nodes.size() > 0) { - input_nodes.pop_back(); - } - while (output_nodes.size() > 0) { - output_nodes.pop_back(); - } + while (input_nodes.size() > 0) input_nodes.pop_back(); + while (output_nodes.size() > 0) output_nodes.pop_back(); } + int32_t RNN::get_number_nodes() { - return (int32_t) nodes.size(); + return (int32_t)nodes.size(); } int32_t RNN::get_number_edges() { - return (int32_t) edges.size(); + return (int32_t)edges.size(); } RNN_Node_Interface* RNN::get_node(int32_t i) { @@ -279,235 +248,212 @@ RNN_Edge* RNN::get_edge(int32_t i) { return edges[i]; } -void RNN::get_weights(vector& parameters) { + + +void RNN::get_weights(vector ¶meters) { parameters.resize(get_number_weights()); int32_t current = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->get_weights(current, parameters); - // if (nodes[i]->is_reachable()) nodes[i]->get_weights(current, parameters); + //if (nodes[i]->is_reachable()) nodes[i]->get_weights(current, parameters); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { parameters[current++] = edges[i]->weight; - // if (edges[i]->is_reachable()) parameters[current++] = edges[i]->weight; + //if (edges[i]->is_reachable()) parameters[current++] = edges[i]->weight; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { parameters[current++] = recurrent_edges[i]->weight; - // if (recurrent_edges[i]->is_reachable()) parameters[current++] = recurrent_edges[i]->weight; + //if (recurrent_edges[i]->is_reachable()) parameters[current++] = recurrent_edges[i]->weight; } } -void RNN::set_weights(const vector& parameters) { - if ((int32_t) parameters.size() != get_number_weights()) { - Log::fatal( - "ERROR! Trying to set weights where the RNN has %d weights, and the parameters vector has %d weights!\n", - get_number_weights(), parameters.size() - ); +void RNN::set_weights(const vector ¶meters) { + if ((int32_t)parameters.size() != get_number_weights()) { + Log::fatal("ERROR! Trying to set weights where the RNN has %d weights, and the parameters vector has %d weights!\n", get_number_weights(), parameters.size()); exit(1); } int32_t current = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->set_weights(current, parameters); - // if (nodes[i]->is_reachable()) nodes[i]->set_weights(current, parameters); + //if (nodes[i]->is_reachable()) nodes[i]->set_weights(current, parameters); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { edges[i]->weight = parameters[current++]; - // if (edges[i]->is_reachable()) edges[i]->weight = parameters[current++]; + //if (edges[i]->is_reachable()) edges[i]->weight = parameters[current++]; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { recurrent_edges[i]->weight = parameters[current++]; - // if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->weight = parameters[current++]; + //if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->weight = parameters[current++]; } + } int32_t RNN::get_number_weights() { int32_t number_weights = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { number_weights += nodes[i]->get_number_weights(); - // if (nodes[i]->is_reachable()) number_weights += nodes[i]->get_number_weights(); + //if (nodes[i]->is_reachable()) number_weights += nodes[i]->get_number_weights(); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { number_weights++; - // if (edges[i]->is_reachable()) number_weights++; + //if (edges[i]->is_reachable()) number_weights++; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { number_weights++; - // if (recurrent_edges[i]->is_reachable()) number_weights++; + //if (recurrent_edges[i]->is_reachable()) number_weights++; } return number_weights; } -void RNN::forward_pass( - const vector >& series_data, bool using_dropout, bool training, double dropout_probability -) { +void RNN::forward_pass(const vector< vector > &series_data, bool using_dropout, bool training, double dropout_probability) { series_length = series_data[0].size(); if (input_nodes.size() != series_data.size()) { - Log::fatal( - "ERROR: number of input nodes (%d) != number of time series data input fields (%d)\n", input_nodes.size(), - series_data.size() - ); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - Log::fatal( - "node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d\n", i, nodes[i]->get_innovation_number(), - nodes[i]->get_depth(), nodes[i]->get_layer_type(), nodes[i]->get_node_type() - ); + Log::fatal("ERROR: number of input nodes (%d) != number of time series data input fields (%d)\n", input_nodes.size(), series_data.size()); + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + Log::fatal("node[%d], in: %d, depth: %lf, layer_type: %d, node_type: %d\n", i, nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_layer_type(), nodes[i]->get_node_type()); } exit(1); } - // TODO: want to check that all vectors in series_data are of same length + //TODO: want to check that all vectors in series_data are of same length + - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->reset(series_length); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { edges[i]->reset(series_length); } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { recurrent_edges[i]->reset(series_length); } - // do a propagate forward for time == -1 so that the the input - // fired count on each node will be correct for the first pass - // through the RNN - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->is_reachable()) { - recurrent_edges[i]->first_propagate_forward(); - } + //do a propagate forward for time == -1 so that the the input + //fired count on each node will be correct for the first pass + //through the RNN + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->first_propagate_forward(); } for (int32_t time = 0; time < series_length; time++) { - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { - if (input_nodes[i]->is_reachable()) { - input_nodes[i]->input_fired(time, series_data[i][time]); - } + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { + if(input_nodes[i]->is_reachable()) input_nodes[i]->input_fired(time, series_data[i][time]); } - // feed forward + //feed forward if (using_dropout) { - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->is_reachable()) { - edges[i]->propagate_forward(time, training, dropout_probability); - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->is_reachable()) edges[i]->propagate_forward(time, training, dropout_probability); } } else { - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->is_reachable()) { - edges[i]->propagate_forward(time); - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->is_reachable()) edges[i]->propagate_forward(time); } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->is_reachable()) { - recurrent_edges[i]->propagate_forward(time); - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->propagate_forward(time); } } } void RNN::backward_pass(double error, bool using_dropout, bool training, double dropout_probability) { - // do a propagate forward for time == (series_length - 1) so that the - // output fired count on each node will be correct for the first pass - // through the RNN - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->is_reachable()) { - recurrent_edges[i]->first_propagate_backward(); - } + //do a propagate forward for time == (series_length - 1) so that the + // output fired count on each node will be correct for the first pass + //through the RNN + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->first_propagate_backward(); } for (int32_t time = series_length - 1; time >= 0; time--) { - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { output_nodes[i]->error_fired(time, error); } if (using_dropout) { - for (int32_t i = (int32_t) edges.size() - 1; i >= 0; i--) { - if (edges[i]->is_reachable()) { - edges[i]->propagate_backward(time, training, dropout_probability); - } + for (int32_t i = (int32_t)edges.size() - 1; i >= 0; i--) { + if (edges[i]->is_reachable()) edges[i]->propagate_backward(time, training, dropout_probability); } } else { - for (int32_t i = (int32_t) edges.size() - 1; i >= 0; i--) { - if (edges[i]->is_reachable()) { - edges[i]->propagate_backward(time); - } + for (int32_t i = (int32_t)edges.size() - 1; i >= 0; i--) { + if (edges[i]->is_reachable()) edges[i]->propagate_backward(time); } } - for (int32_t i = (int32_t) recurrent_edges.size() - 1; i >= 0; i--) { - if (recurrent_edges[i]->is_reachable()) { - recurrent_edges[i]->propagate_backward(time); - } + for (int32_t i = (int32_t)recurrent_edges.size() - 1; i >= 0; i--) { + if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->propagate_backward(time); } } } -double RNN::calculate_error_softmax(const vector >& expected_outputs) { +double RNN::calculate_error_softmax(const vector< vector > &expected_outputs) { + + double cross_entropy_sum = 0.0; double error; double softmax = 0.0; - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { output_nodes[i]->error_values.resize(expected_outputs[i].size()); } - // for each time step j - for (int32_t j = 0; j < (int32_t) expected_outputs[0].size(); j++) { + // for each time step j + for (int32_t j = 0; j < (int32_t)expected_outputs[0].size(); j++) { double softmax_sum = 0.0; double cross_entropy = 0.0; // get sum of all the outputs of the timestep j from all output node i - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { softmax_sum += exp(output_nodes[i]->output_values[j]); } - // for each + // for each - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { softmax = exp(output_nodes[i]->output_values[j]) / softmax_sum; error = softmax - expected_outputs[i][j]; output_nodes[i]->error_values[j] = error; - // std::cout<<"softmax ::::: "<output_values[j]<<" - // "<output_values[j]<<" "< >& expected_outputs) { +double RNN::calculate_error_mse(const vector< vector > &expected_outputs) { double mse_sum = 0.0; double mse; double error; - - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { output_nodes[i]->error_values.resize(expected_outputs[i].size()); mse = 0.0; - for (int32_t j = 0; j < (int32_t) expected_outputs[i].size(); j++) { + for (int32_t j = 0; j < (int32_t)expected_outputs[i].size(); j++) { error = output_nodes[i]->output_values[j] - expected_outputs[i][j]; - // std::cout<<"why this ???? mse ::::: "<output_values[j]<<" - // "<output_values[j]<<" "<error_values[j] = error; mse += error * error; @@ -518,16 +464,16 @@ double RNN::calculate_error_mse(const vector >& expected_outputs) return mse_sum; } -double RNN::calculate_error_mae(const vector >& expected_outputs) { +double RNN::calculate_error_mae(const vector< vector > &expected_outputs) { double mae_sum = 0.0; double mae; double error; - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { output_nodes[i]->error_values.resize(expected_outputs[i].size()); mae = 0.0; - for (int32_t j = 0; j < (int32_t) expected_outputs[i].size(); j++) { + for (int32_t j = 0; j < (int32_t)expected_outputs[i].size(); j++) { error = fabs(output_nodes[i]->output_values[j] - expected_outputs[i][j]); mae += error; @@ -538,6 +484,7 @@ double RNN::calculate_error_mae(const vector >& expected_outputs) error = (output_nodes[i]->output_values[j] - expected_outputs[i][j]) / error; } output_nodes[i]->error_values[j] = error; + } mae_sum += mae / expected_outputs[i].size(); } @@ -545,78 +492,63 @@ double RNN::calculate_error_mae(const vector >& expected_outputs) return mae_sum; } -double RNN::prediction_softmax( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability -) { + +double RNN::prediction_softmax(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability) { forward_pass(series_data, using_dropout, training, dropout_probability); return calculate_error_softmax(expected_outputs); } -double RNN::prediction_mse( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability -) { +double RNN::prediction_mse(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability) { forward_pass(series_data, using_dropout, training, dropout_probability); return calculate_error_mse(expected_outputs); } -double RNN::prediction_mae( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability -) { +double RNN::prediction_mae(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability) { forward_pass(series_data, using_dropout, training, dropout_probability); return calculate_error_mae(expected_outputs); } -vector RNN::get_predictions( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - double dropout_probability -) { +vector RNN::get_predictions(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, double dropout_probability) { forward_pass(series_data, using_dropout, false, dropout_probability); vector result; for (int32_t j = 0; j < series_length; j++) { - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { result.push_back(output_nodes[i]->output_values[j]); } } - // TODO: returning a vector isn't the most efficient, but i don't think we'll be using this for things that are - // performance critical -- Travis + //TODO: returning a vector isn't the most efficient, but i don't think we'll be using this for things that are performance + //critical -- Travis return result; } -void RNN::write_predictions( - string output_filename, const vector& input_parameter_names, const vector& output_parameter_names, - const vector >& series_data, const vector >& expected_outputs, - TimeSeriesSets* time_series_sets, bool using_dropout, double dropout_probability -) { +void RNN::write_predictions(string output_filename, const vector &input_parameter_names, const vector &output_parameter_names, const vector< vector > &series_data, const vector< vector > &expected_outputs, TimeSeriesSets *time_series_sets, bool using_dropout, double dropout_probability) { forward_pass(series_data, using_dropout, false, dropout_probability); + Log::debug("series_length: %d, series_data.size(): %d, series_data[0].size(): %d\n", series_length, series_data.size(), series_data[0].size()); + Log::debug("input_nodes.size(): %d, output_nodes.size(): %d\n", input_nodes.size(), output_nodes.size()); ofstream outfile(output_filename); outfile << "#"; - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { - if (i > 0) { - outfile << ","; - } + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { + if (i > 0) outfile << ","; outfile << input_parameter_names[i]; Log::debug("input_parameter_names[%d]: '%s'\n", i, input_parameter_names[i].c_str()); } - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { outfile << ","; outfile << "expected_" << output_parameter_names[i]; Log::debug("output_parameter_names[%d]: '%s'\n", i, output_parameter_names[i].c_str()); } - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { outfile << ","; outfile << "predicted_" << output_parameter_names[i]; @@ -625,23 +557,21 @@ void RNN::write_predictions( outfile << endl; for (int32_t j = 0; j < series_length; j++) { - for (int32_t i = 0; i < (int32_t) input_nodes.size(); i++) { - if (i > 0) { - outfile << ","; - } - // outfile << series_data[i][j]; + for (int32_t i = 0; i < (int32_t)input_nodes.size(); i++) { + if (i > 0) outfile << ","; + //outfile << series_data[i][j]; outfile << time_series_sets->denormalize(input_parameter_names[i], series_data[i][j]); } - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { outfile << ","; - // outfile << expected_outputs[i][j]; + //outfile << expected_outputs[i][j]; outfile << time_series_sets->denormalize(output_parameter_names[i], expected_outputs[i][j]); } - for (int32_t i = 0; i < (int32_t) output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_nodes.size(); i++) { outfile << ","; - // outfile << output_nodes[i]->output_values[j]; + //outfile << output_nodes[i]->output_values[j]; outfile << time_series_sets->denormalize(output_parameter_names[i], output_nodes[i]->output_values[j]); } outfile << endl; @@ -649,41 +579,37 @@ void RNN::write_predictions( outfile.close(); } -void RNN::get_analytic_gradient( - const vector& test_parameters, const vector >& inputs, - const vector >& outputs, double& mse, vector& analytic_gradient, bool using_dropout, - bool training, double dropout_probability -) { +void RNN::get_analytic_gradient(const vector &test_parameters, const vector< vector > &inputs, const vector< vector > &outputs, double &mse, vector &analytic_gradient, bool using_dropout, bool training, double dropout_probability) { analytic_gradient.assign(test_parameters.size(), 0.0); set_weights(test_parameters); forward_pass(inputs, using_dropout, training, dropout_probability); mse = calculate_error_mse(outputs); - backward_pass(mse * (1.0 / outputs[0].size()) * 2.0, using_dropout, training, dropout_probability); - + backward_pass(mse * (1.0 / outputs[0].size())*2.0, using_dropout, training, dropout_probability); + vector current_gradients; int32_t current = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->is_reachable()) { nodes[i]->get_gradients(current_gradients); - for (int32_t j = 0; j < (int32_t) current_gradients.size(); j++) { + for (int32_t j = 0; j < (int32_t)current_gradients.size(); j++) { analytic_gradient[current] = current_gradients[j]; current++; } } } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->is_reachable()) { analytic_gradient[current] = edges[i]->get_gradient(); current++; } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->is_reachable()) { analytic_gradient[current] = recurrent_edges[i]->get_gradient(); current++; @@ -691,14 +617,11 @@ void RNN::get_analytic_gradient( } } -void RNN::get_empirical_gradient( - const vector& test_parameters, const vector >& inputs, - const vector >& outputs, double& mse, vector& empirical_gradient, bool using_dropout, - bool training, double dropout_probability -) { +void RNN::get_empirical_gradient(const vector &test_parameters, const vector< vector > &inputs, const vector< vector > &outputs, double &mse, vector &empirical_gradient, bool using_dropout, bool training, double dropout_probability) { empirical_gradient.assign(test_parameters.size(), 0.0); - vector > deltas; + vector< vector > deltas; + set_weights(test_parameters); forward_pass(inputs, using_dropout, training, dropout_probability); @@ -709,7 +632,7 @@ void RNN::get_empirical_gradient( double mse1, mse2; vector parameters = test_parameters; - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { save = parameters[i]; parameters[i] = save - diff; @@ -738,7 +661,7 @@ void RNN::initialize_randomly() { unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); minstd_rand0 generator(seed); uniform_real_distribution rng(-0.5, 0.5); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { parameters[i] = rng(generator); } set_weights(parameters); diff --git a/rnn/rnn.hxx b/rnn/rnn.hxx index 95ac821d..69ea2c20 100644 --- a/rnn/rnn.hxx +++ b/rnn/rnn.hxx @@ -7,100 +7,68 @@ using std::string; #include using std::vector; -#include "rnn_edge.hxx" + #include "rnn_node_interface.hxx" +#include "rnn_edge.hxx" #include "rnn_recurrent_edge.hxx" + #include "time_series/time_series.hxx" // #include "word_series/word_series.hxx" class RNN { - private: - int32_t series_length; - - vector input_nodes; - vector output_nodes; - - vector nodes; - vector edges; - vector recurrent_edges; - - public: - RNN(vector& _nodes, vector& _edges, const vector& input_parameter_names, - const vector& output_parameter_names); - RNN(vector& _nodes, vector& _edges, vector& _recurrent_edges, - const vector& input_parameter_names, const vector& output_parameter_names); - ~RNN(); - - void fix_parameter_orders( - const vector& input_parameter_names, const vector& output_parameter_names - ); - void validate_parameters(const vector& input_parameter_names, const vector& output_parameter_names); - - int32_t get_number_nodes(); - int32_t get_number_edges(); - - RNN_Node_Interface* get_node(int32_t i); - RNN_Edge* get_edge(int32_t i); - - void forward_pass( - const vector >& series_data, bool using_dropout, bool training, double dropout_probability - ); - void backward_pass(double error, bool using_dropout, bool training, double dropout_probability); - - double calculate_error_softmax(const vector >& expected_outputs); - double calculate_error_mse(const vector >& expected_outputs); - double calculate_error_mae(const vector >& expected_outputs); - - double prediction_softmax( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability - ); - double prediction_mse( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability - ); - double prediction_mae( - const vector >& series_data, const vector >& expected_outputs, bool using_dropout, - bool training, double dropout_probability - ); - - vector get_predictions( - const vector >& series_data, const vector >& expected_outputs, bool usng_dropout, - double dropout_probability - ); - - void write_predictions( - string output_filename, const vector& input_parameter_names, - const vector& output_parameter_names, const vector >& series_data, - const vector >& expected_outputs, TimeSeriesSets* time_series_sets, bool using_dropout, - double dropout_probability - ); - - void initialize_randomly(); - void get_weights(vector& parameters); - void set_weights(const vector& parameters); - - int32_t get_number_weights(); - - void get_analytic_gradient( - const vector& test_parameters, const vector >& inputs, - const vector >& outputs, double& mse, vector& analytic_gradient, bool using_dropout, - bool training, double dropout_probability - ); - void get_empirical_gradient( - const vector& test_parameters, const vector >& inputs, - const vector >& outputs, double& mae, vector& empirical_gradient, bool using_dropout, - bool training, double dropout_probability - ); - - // RNN* copy(); - - friend void get_mse( - RNN* genome, const vector >& expected, double& mse, vector >& deltas - ); - friend void get_mae( - RNN* genome, const vector >& expected, double& mae, vector >& deltas - ); + private: + int32_t series_length; + + vector input_nodes; + vector output_nodes; + + vector nodes; + vector edges; + vector recurrent_edges; + + public: + RNN(vector &_nodes, vector &_edges, const vector &input_parameter_names, const vector &output_parameter_names); + RNN(vector &_nodes, vector &_edges, vector &_recurrent_edges, const vector &input_parameter_names, const vector &output_parameter_names); + ~RNN(); + + void fix_parameter_orders(const vector &input_parameter_names, const vector &output_parameter_names); + void validate_parameters(const vector &input_parameter_names, const vector &output_parameter_names); + + int32_t get_number_nodes(); + int32_t get_number_edges(); + + RNN_Node_Interface* get_node(int32_t i); + RNN_Edge* get_edge(int32_t i); + + void forward_pass(const vector< vector > &series_data, bool using_dropout, bool training, double dropout_probability); + void backward_pass(double error, bool using_dropout, bool training, double dropout_probability); + + double calculate_error_softmax(const vector< vector > &expected_outputs); + double calculate_error_mse(const vector< vector > &expected_outputs); + double calculate_error_mae(const vector< vector > &expected_outputs); + + double prediction_softmax(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability); + double prediction_mse(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability); + double prediction_mae(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool using_dropout, bool training, double dropout_probability); + + + vector get_predictions(const vector< vector > &series_data, const vector< vector > &expected_outputs, bool usng_dropout, double dropout_probability); + + void write_predictions(string output_filename, const vector &input_parameter_names, const vector &output_parameter_names, const vector< vector > &series_data, const vector< vector > &expected_outputs, TimeSeriesSets *time_series_sets, bool using_dropout, double dropout_probability); + + void initialize_randomly(); + void get_weights(vector ¶meters); + void set_weights(const vector ¶meters); + + int32_t get_number_weights(); + + void get_analytic_gradient(const vector &test_parameters, const vector< vector > &inputs, const vector< vector > &outputs, double &mse, vector &analytic_gradient, bool using_dropout, bool training, double dropout_probability); + void get_empirical_gradient(const vector &test_parameters, const vector< vector > &inputs, const vector< vector > &outputs, double &mae, vector &empirical_gradient, bool using_dropout, bool training, double dropout_probability); + + //RNN* copy(); + + friend void get_mse(RNN* genome, const vector< vector > &expected, double &mse, vector< vector > &deltas); + friend void get_mae(RNN* genome, const vector< vector > &expected, double &mae, vector< vector > &deltas); }; #endif diff --git a/rnn/rnn_edge.cxx b/rnn/rnn_edge.cxx index 3227e961..5de39e58 100644 --- a/rnn/rnn_edge.cxx +++ b/rnn/rnn_edge.cxx @@ -2,7 +2,7 @@ #include "common/log.hxx" -RNN_Edge::RNN_Edge(int32_t _innovation_number, RNN_Node_Interface* _input_node, RNN_Node_Interface* _output_node) { +RNN_Edge::RNN_Edge(int32_t _innovation_number, RNN_Node_Interface *_input_node, RNN_Node_Interface *_output_node) { innovation_number = _innovation_number; input_node = _input_node; output_node = _output_node; @@ -17,15 +17,10 @@ RNN_Edge::RNN_Edge(int32_t _innovation_number, RNN_Node_Interface* _input_node, input_node->total_outputs++; output_node->total_inputs++; - Log::debug( - "\t\tcreated edge %d from %d to %d\n", innovation_number, input_innovation_number, output_innovation_number - ); + Log::debug("\t\tcreated edge %d from %d to %d\n", innovation_number, input_innovation_number, output_innovation_number); } -RNN_Edge::RNN_Edge( - int32_t _innovation_number, int32_t _input_innovation_number, int32_t _output_innovation_number, - const vector& nodes -) { +RNN_Edge::RNN_Edge(int32_t _innovation_number, int32_t _input_innovation_number, int32_t _output_innovation_number, const vector &nodes) { innovation_number = _innovation_number; input_innovation_number = _input_innovation_number; @@ -33,13 +28,10 @@ RNN_Edge::RNN_Edge( input_node = NULL; output_node = NULL; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->innovation_number == _input_innovation_number) { if (input_node != NULL) { - Log::fatal( - "ERROR in copying RNN_Edge, list of nodes has multiple nodes with same input_innovation_number -- " - "this should never happen.\n" - ); + Log::fatal("ERROR in copying RNN_Edge, list of nodes has multiple nodes with same input_innovation_number -- this should never happen.\n"); exit(1); } @@ -48,10 +40,7 @@ RNN_Edge::RNN_Edge( if (nodes[i]->innovation_number == _output_innovation_number) { if (output_node != NULL) { - Log::fatal( - "ERROR in copying RNN_Edge, list of nodes has multiple nodes with same output_innovation_number -- " - "this should never happen.\n" - ); + Log::fatal("ERROR in copying RNN_Edge, list of nodes has multiple nodes with same output_innovation_number -- this should never happen.\n"); exit(1); } @@ -60,18 +49,12 @@ RNN_Edge::RNN_Edge( } if (input_node == NULL) { - Log::fatal( - "ERROR initializing RNN_Edge, input node with innovation number; %d was not found!\n", - input_innovation_number - ); + Log::fatal("ERROR initializing RNN_Edge, input node with innovation number; %d was not found!\n", input_innovation_number); exit(1); } if (output_node == NULL) { - Log::fatal( - "ERROR initializing RNN_Edge, output node with innovation number; %d was not found!\n", - output_innovation_number - ); + Log::fatal("ERROR initializing RNN_Edge, output node with innovation number; %d was not found!\n", output_innovation_number); exit(1); } } @@ -91,42 +74,34 @@ RNN_Edge* RNN_Edge::copy(const vector new_nodes) { return e; } + + + void RNN_Edge::propagate_forward(int32_t time) { if (input_node->inputs_fired[time] != input_node->total_inputs) { - Log::fatal( - "ERROR! propagate forward called on edge %d where input_node->inputs_fired[%d] (%d) != total_inputs (%d)\n", - innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs - ); - Log::fatal( - "input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, - output_node->innovation_number - ); + Log::fatal("ERROR! propagate forward called on edge %d where input_node->inputs_fired[%d] (%d) != total_inputs (%d)\n", innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs); + Log::fatal("input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, output_node->innovation_number); exit(1); } - // Log::debug("input_node %p %d\n", input_node, input_node->output_values.size()); double output = input_node->output_values[time] * weight; - // Log::debug("propagating forward at time %d from %d to %d, value: %lf, input: %lf, weight: %lf\n", time, - // input_node->innovation_number, output_node->innovation_number, output, input_node->output_values[time], weight); + //Log::trace("propagating forward at time %d from %d to %d, value: %lf, input: %lf, weight: %lf\n", time, input_node->innovation_number, output_node->innovation_number, output, input_node->output_values[time], weight); outputs[time] = output; output_node->input_fired(time, output); } + void RNN_Edge::propagate_forward(int32_t time, bool training, double dropout_probability) { if (input_node->inputs_fired[time] != input_node->total_inputs) { - Log::fatal( - "ERROR! propagate forward called on edge %d where input_node->inputs_fired[%d] (%d) != total_inputs (%d)\n", - innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs - ); + Log::fatal("ERROR! propagate forward called on edge %d where input_node->inputs_fired[%d] (%d) != total_inputs (%d)\n", innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs); exit(1); } double output = input_node->output_values[time] * weight; - // Log::trace("propagating forward at time %d from %d to %d, value: %lf, input: %lf, weight: %lf\n", time, - // input_node->innovation_number, output_node->innovation_number, output, input_node->output_values[time], weight); + //Log::trace("propagating forward at time %d from %d to %d, value: %lf, input: %lf, weight: %lf\n", time, input_node->innovation_number, output_node->innovation_number, output, input_node->output_values[time], weight); if (training) { if (drand48() < dropout_probability) { @@ -145,21 +120,13 @@ void RNN_Edge::propagate_forward(int32_t time, bool training, double dropout_pro void RNN_Edge::propagate_backward(int32_t time) { if (output_node->outputs_fired[time] != output_node->total_outputs) { - Log::fatal( - "ERROR! propagate backward called on edge %d where output_node->outputs_fired[%d] (%d) != total_outputs " - "(%d)\n", - innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs - ); - Log::fatal( - "input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, - output_node->innovation_number - ); + Log::fatal("ERROR! propagate backward called on edge %d where output_node->outputs_fired[%d] (%d) != total_outputs (%d)\n", innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs); + Log::fatal("input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, output_node->innovation_number); Log::fatal("series_length: %d\n", input_node->series_length); exit(1); } - // Log::trace("propgating backward on edge %d at time %d from node %d to node %d\n", innovation_number, time, - // output_innovation_number, input_innovation_number); + //Log::trace("propgating backward on edge %d at time %d from node %d to node %d\n", innovation_number, time, output_innovation_number, input_innovation_number); double delta = output_node->d_input[time]; @@ -170,28 +137,18 @@ void RNN_Edge::propagate_backward(int32_t time) { void RNN_Edge::propagate_backward(int32_t time, bool training, double dropout_probability) { if (output_node->outputs_fired[time] != output_node->total_outputs) { - Log::fatal( - "ERROR! propagate backward called on edge %d where output_node->outputs_fired[%d] (%d) != total_outputs " - "(%d)\n", - innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs - ); - Log::fatal( - "input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, - output_node->innovation_number - ); + Log::fatal("ERROR! propagate backward called on edge %d where output_node->outputs_fired[%d] (%d) != total_outputs (%d)\n", innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs); + Log::fatal("input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, output_node->innovation_number); Log::fatal("series_length: %d\n", input_node->series_length); exit(1); } - // Log::trace("propgating backward on edge %d at time %d from node %d to node %d\n", innovation_number, time, - // output_innovation_number, input_innovation_number); + //Log::trace("propgating backward on edge %d at time %d from node %d to node %d\n", innovation_number, time, output_innovation_number, input_innovation_number); double delta = output_node->d_input[time]; if (training) { - if (dropped_out[time]) { - delta = 0.0; - } + if (dropped_out[time]) delta = 0.0; } d_weight += delta * input_node->output_values[time]; @@ -206,10 +163,6 @@ void RNN_Edge::reset(int32_t series_length) { dropped_out.resize(series_length); } -void RNN_Edge::set_weight(double weight) { - this->weight = weight; -} - double RNN_Edge::get_gradient() const { return d_weight; } @@ -222,10 +175,12 @@ int32_t RNN_Edge::get_input_innovation_number() const { return input_innovation_number; } + int32_t RNN_Edge::get_output_innovation_number() const { return output_innovation_number; } + const RNN_Node_Interface* RNN_Edge::get_input_node() const { return input_node; } @@ -242,16 +197,15 @@ bool RNN_Edge::is_reachable() const { return forward_reachable && backward_reachable; } -bool RNN_Edge::equals(RNN_Edge* other) const { - if (innovation_number == other->innovation_number && enabled == other->enabled) { - return true; - } + +bool RNN_Edge::equals(RNN_Edge *other) const { + if (innovation_number == other->innovation_number && enabled == other->enabled) return true; return false; } -void RNN_Edge::write_to_stream(ostream& out) { - out.write((char*) &innovation_number, sizeof(int32_t)); - out.write((char*) &input_innovation_number, sizeof(int32_t)); - out.write((char*) &output_innovation_number, sizeof(int32_t)); - out.write((char*) &enabled, sizeof(bool)); +void RNN_Edge::write_to_stream(ostream &out) { + out.write((char*)&innovation_number, sizeof(int32_t)); + out.write((char*)&input_innovation_number, sizeof(int32_t)); + out.write((char*)&output_innovation_number, sizeof(int32_t)); + out.write((char*)&enabled, sizeof(bool)); } diff --git a/rnn/rnn_edge.hxx b/rnn/rnn_edge.hxx index 7dbeb33c..b1735222 100644 --- a/rnn/rnn_edge.hxx +++ b/rnn/rnn_edge.hxx @@ -4,75 +4,71 @@ #include "rnn_node_interface.hxx" class RNN_Edge { - private: - int32_t innovation_number; + private: + int32_t innovation_number; - vector outputs; - vector deltas; - vector dropped_out; + vector outputs; + vector deltas; + vector dropped_out; - double weight; - double d_weight; + double weight; + double d_weight; - bool enabled; - bool forward_reachable; - bool backward_reachable; + bool enabled; + bool forward_reachable; + bool backward_reachable; - int32_t input_innovation_number; - int32_t output_innovation_number; + int32_t input_innovation_number; + int32_t output_innovation_number; - RNN_Node_Interface* input_node; - RNN_Node_Interface* output_node; + RNN_Node_Interface *input_node; + RNN_Node_Interface *output_node; - public: - RNN_Edge(int32_t _innovation_number, RNN_Node_Interface* _input_node, RNN_Node_Interface* _output_node); + public: + RNN_Edge(int32_t _innovation_number, RNN_Node_Interface *_input_node, RNN_Node_Interface *_output_node); - RNN_Edge( - int32_t _innovation_number, int32_t _input_innovation_number, int32_t _output_innovation_number, - const vector& nodes - ); + RNN_Edge(int32_t _innovation_number, int32_t _input_innovation_number, int32_t _output_innovation_number, const vector &nodes); - RNN_Edge* copy(const vector new_nodes); + RNN_Edge* copy(const vector new_nodes); - void reset(int32_t series_length); + void reset(int32_t series_length); - void propagate_forward(int32_t time); - void propagate_backward(int32_t time); + void propagate_forward(int32_t time); + void propagate_backward(int32_t time); - void propagate_forward(int32_t time, bool training, double dropout_probability); - void propagate_backward(int32_t time, bool training, double dropout_probability); + void propagate_forward(int32_t time, bool training, double dropout_probability); + void propagate_backward(int32_t time, bool training, double dropout_probability); - void set_weight(double weight); + double get_gradient() const; + int32_t get_innovation_number() const; + int32_t get_input_innovation_number() const; + int32_t get_output_innovation_number() const; - double get_gradient() const; - int32_t get_innovation_number() const; - int32_t get_input_innovation_number() const; - int32_t get_output_innovation_number() const; + const RNN_Node_Interface* get_input_node() const; + const RNN_Node_Interface* get_output_node() const; - const RNN_Node_Interface* get_input_node() const; - const RNN_Node_Interface* get_output_node() const; + bool is_enabled() const; + bool is_reachable() const; - bool is_enabled() const; - bool is_reachable() const; + bool equals (RNN_Edge *other) const; - bool equals(RNN_Edge* other) const; + void write_to_stream(ostream &out); - void write_to_stream(ostream& out); - - friend class RNN_Genome; - friend class RNN; - friend class EXAMM; + friend class RNN_Genome; + friend class RNN; + friend class EXAMM; }; + struct sort_RNN_Edges_by_depth { - bool operator()(RNN_Edge* n1, RNN_Edge* n2) { + bool operator()(RNN_Edge *n1, RNN_Edge *n2) { if (n1->get_input_node()->get_depth() < n2->get_input_node()->get_depth()) { return true; } else if (n1->get_input_node()->get_depth() == n2->get_input_node()->get_depth()) { - // make sure the order of the edges is *always* the same - // going through the edges in different orders may effect the output - // of backpropagation + //make sure the order of the edges is *always* the same + //going through the edges in different orders may effect the output + //of backpropagation if (n1->get_innovation_number() < n2->get_innovation_number()) { return true; } else { @@ -82,18 +78,18 @@ struct sort_RNN_Edges_by_depth { } else { return false; } - } + } }; struct sort_RNN_Edges_by_output_depth { - bool operator()(RNN_Edge* n1, RNN_Edge* n2) { + bool operator()(RNN_Edge *n1, RNN_Edge *n2) { if (n1->get_output_node()->get_depth() < n2->get_output_node()->get_depth()) { return true; } else if (n1->get_output_node()->get_depth() == n2->get_output_node()->get_depth()) { - // make sure the order of the edges is *always* the same - // going through the edges in different orders may effect the output - // of backpropagation + //make sure the order of the edges is *always* the same + //going through the edges in different orders may effect the output + //of backpropagation if (n1->get_innovation_number() < n2->get_innovation_number()) { return true; } else { @@ -103,13 +99,18 @@ struct sort_RNN_Edges_by_output_depth { } else { return false; } - } + } }; + struct sort_RNN_Edges_by_innovation { - bool operator()(RNN_Edge* n1, RNN_Edge* n2) { + bool operator()(RNN_Edge *n1, RNN_Edge *n2) { return n1->get_innovation_number() < n2->get_innovation_number(); - } + } }; + + + + #endif diff --git a/rnn/rnn_genome.cxx b/rnn/rnn_genome.cxx index c7b60b43..8cbf9a9f 100644 --- a/rnn/rnn_genome.cxx +++ b/rnn/rnn_genome.cxx @@ -3,15 +3,16 @@ using std::sort; using std::upper_bound; #include + #include -using std::ifstream; using std::istream; -using std::ofstream; +using std::ifstream; using std::ostream; +using std::ofstream; #include -using std::setfill; using std::setw; +using std::setfill; #include using std::hex; @@ -29,8 +30,8 @@ using std::thread; #include using std::minstd_rand0; -using std::uniform_int_distribution; using std::uniform_real_distribution; +using std::uniform_int_distribution; #include using std::istringstream; @@ -43,22 +44,23 @@ using std::to_string; #include using std::vector; +#include "common/random.hxx" #include "common/color_table.hxx" #include "common/log.hxx" -#include "common/random.hxx" -#include "delta_node.hxx" -#include "dnas_node.hxx" + +#include "time_series/time_series.hxx" + +#include "rnn.hxx" +#include "rnn_node.hxx" +#include "lstm_node.hxx" +#include "gru_node.hxx" #include "enarc_node.hxx" #include "enas_dag_node.hxx" -#include "gru_node.hxx" -#include "lstm_node.hxx" -#include "mgu_node.hxx" #include "random_dag_node.hxx" -#include "rnn.hxx" -#include "rnn_genome.hxx" -#include "rnn_node.hxx" -#include "time_series/time_series.hxx" +#include "delta_node.hxx" #include "ugrnn_node.hxx" +#include "mgu_node.hxx" +#include "rnn_genome.hxx" string parse_fitness(double fitness) { if (fitness == EXAMM_MAX_DOUBLE) { @@ -68,6 +70,7 @@ string parse_fitness(double fitness) { } } + void RNN_Genome::sort_nodes_by_depth() { sort(nodes.begin(), nodes.end(), sort_RNN_Nodes_by_depth()); } @@ -78,15 +81,19 @@ void RNN_Genome::sort_edges_by_depth() { void RNN_Genome::sort_recurrent_edges_by_depth() { sort(recurrent_edges.begin(), recurrent_edges.end(), sort_RNN_Recurrent_Edges_by_depth()); + } -RNN_Genome::RNN_Genome( - vector& _nodes, vector& _edges, vector& _recurrent_edges, - WeightRules* _weight_rules -) { +RNN_Genome::RNN_Genome(vector &_nodes, + vector &_edges, + vector &_recurrent_edges, + WeightRules *_weight_rules) { generation_id = -1; group_id = -1; + int16_t seed = std::chrono::system_clock::now().time_since_epoch().count(); + generator = minstd_rand0(seed); + best_validation_mse = EXAMM_MAX_DOUBLE; best_validation_mae = EXAMM_MAX_DOUBLE; @@ -101,12 +108,19 @@ RNN_Genome::RNN_Genome( sort_nodes_by_depth(); sort_edges_by_depth(); - // set default values + //set default values bp_iterations = 20000; - // learning_rate = 0.001; - // adapt_learning_rate = false; - // use_nesterov_momentum = false; - // use_reset_weights = false; + + //SHO SY + //learning_rate = 0.001; + rng_lr = uniform_real_distribution(0.0001, 0.03); + rng_ilr = uniform_real_distribution(0.001, 0.05); + learning_rate = rng_lr(generator); + initial_learning_rate = rng_ilr(generator); + + //adapt_learning_rate = false; + //use_nesterov_momentum = false; + //use_reset_weights = false; // use_high_norm = true; // high_threshold = 1.0; @@ -118,8 +132,7 @@ RNN_Genome::RNN_Genome( log_filename = ""; - int16_t seed = std::chrono::system_clock::now().time_since_epoch().count(); - generator = minstd_rand0(seed); + rng = uniform_real_distribution(-0.5, 0.5); rng_0_1 = uniform_real_distribution(0.0, 1.0); rng_1_1 = uniform_real_distribution(-1.0, 1.0); @@ -127,46 +140,48 @@ RNN_Genome::RNN_Genome( assign_reachability(); } -RNN_Genome::RNN_Genome( - vector& _nodes, vector& _edges, vector& _recurrent_edges, - int16_t seed, WeightRules* _weight_rules -) - : RNN_Genome(_nodes, _edges, _recurrent_edges, _weight_rules) { +RNN_Genome::RNN_Genome(vector &_nodes, + vector &_edges, + vector &_recurrent_edges, + int16_t seed, + WeightRules *_weight_rules) : + RNN_Genome(_nodes, _edges, _recurrent_edges, _weight_rules) { + generator = minstd_rand0(seed); } -void RNN_Genome::set_parameter_names( - const vector& _input_parameter_names, const vector& _output_parameter_names -) { +void RNN_Genome::set_parameter_names(const vector &_input_parameter_names, const vector &_output_parameter_names) { input_parameter_names = _input_parameter_names; output_parameter_names = _output_parameter_names; } + RNN_Genome* RNN_Genome::copy() { vector node_copies; vector edge_copies; vector recurrent_edge_copies; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - node_copies.push_back(nodes[i]->copy()); + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + node_copies.push_back( nodes[i]->copy() ); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - edge_copies.push_back(edges[i]->copy(node_copies)); + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + edge_copies.push_back( edges[i]->copy(node_copies) ); } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - recurrent_edge_copies.push_back(recurrent_edges[i]->copy(node_copies)); + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + recurrent_edge_copies.push_back( recurrent_edges[i]->copy(node_copies) ); } - RNN_Genome* other = new RNN_Genome(node_copies, edge_copies, recurrent_edge_copies, weight_rules); + RNN_Genome *other = new RNN_Genome(node_copies, edge_copies, recurrent_edge_copies, weight_rules); other->group_id = group_id; other->bp_iterations = bp_iterations; other->generation_id = generation_id; - // other->learning_rate = learning_rate; - // other->adapt_learning_rate = adapt_learning_rate; - // other->use_reset_weights = use_reset_weights; + //SHO SY TODO: should we also update the initial learning rate for the copies?? + other->learning_rate = learning_rate; + //other->adapt_learning_rate = adapt_learning_rate; + //other->use_reset_weights = use_reset_weights; // other->use_high_norm = use_high_norm; // other->high_threshold = high_threshold; @@ -195,14 +210,15 @@ RNN_Genome* RNN_Genome::copy() { other->normalize_avgs = normalize_avgs; other->normalize_std_devs = normalize_std_devs; - // reachability is assigned in the constructor - // other->assign_reachability(); + //reachability is assigned in the constructor + //other->assign_reachability(); return other; } + RNN_Genome::~RNN_Genome() { - RNN_Node_Interface* node; + RNN_Node_Interface *node; while (nodes.size() > 0) { node = nodes.back(); @@ -210,7 +226,7 @@ RNN_Genome::~RNN_Genome() { delete node; } - RNN_Edge* edge; + RNN_Edge *edge; while (edges.size() > 0) { edge = edges.back(); @@ -218,7 +234,7 @@ RNN_Genome::~RNN_Genome() { delete edge; } - RNN_Recurrent_Edge* recurrent_edge; + RNN_Recurrent_Edge *recurrent_edge; while (recurrent_edges.size() > 0) { recurrent_edge = recurrent_edges.back(); @@ -230,10 +246,23 @@ RNN_Genome::~RNN_Genome() { string RNN_Genome::print_statistics_header() { ostringstream oss; - oss << std::left << setw(12) << "MSE" << setw(12) << "MAE" << setw(12) << "Edges" << setw(12) << "Rec Edges" - << setw(12) << "Simple" << setw(12) << "Jordan" << setw(12) << "Elman" << setw(12) << "UGRNN" << setw(12) - << "MGU" << setw(12) << "GRU" << setw(12) << "Delta" << setw(12) << "LSTM" << setw(12) << "ENARC" << setw(12) - << "ENAS_DAG" << setw(12) << "RANDOM_DAG" << setw(12) << "Total" + oss << std::left + << setw(12) << "MSE" + << setw(12) << "MAE" + << setw(12) << "Edges" + << setw(12) << "Rec Edges" + << setw(12) << "Simple" + << setw(12) << "Jordan" + << setw(12) << "Elman" + << setw(12) << "UGRNN" + << setw(12) << "MGU" + << setw(12) << "GRU" + << setw(12) << "Delta" + << setw(12) << "LSTM" + << setw(12) << "ENARC" + << setw(12) << "ENAS_DAG" + << setw(12) << "RANDOM_DAG" + << setw(12) << "Total" << "Generated"; return oss.str(); @@ -241,14 +270,23 @@ string RNN_Genome::print_statistics_header() { string RNN_Genome::print_statistics() { ostringstream oss; - oss << std::left << setw(12) << parse_fitness(best_validation_mse) << setw(12) << parse_fitness(best_validation_mae) - << setw(12) << get_edge_count_str(false) << setw(12) << get_edge_count_str(true) << setw(12) - << get_node_count_str(SIMPLE_NODE) << setw(12) << get_node_count_str(JORDAN_NODE) << setw(12) - << get_node_count_str(ELMAN_NODE) << setw(12) << get_node_count_str(UGRNN_NODE) << setw(12) - << get_node_count_str(MGU_NODE) << setw(12) << get_node_count_str(GRU_NODE) << setw(12) - << get_node_count_str(DELTA_NODE) << setw(12) << get_node_count_str(LSTM_NODE) << setw(12) - << get_node_count_str(ENARC_NODE) << setw(12) << get_node_count_str(ENAS_DAG_NODE) << setw(12) - << get_node_count_str(RANDOM_DAG_NODE) << setw(12) << get_node_count_str(-1) //-1 does all nodes + oss << std::left + << setw(12) << parse_fitness(best_validation_mse) + << setw(12) << parse_fitness(best_validation_mae) + << setw(12) << get_edge_count_str(false) + << setw(12) << get_edge_count_str(true) + << setw(12) << get_node_count_str(SIMPLE_NODE) + << setw(12) << get_node_count_str(JORDAN_NODE) + << setw(12) << get_node_count_str(ELMAN_NODE) + << setw(12) << get_node_count_str(UGRNN_NODE) + << setw(12) << get_node_count_str(MGU_NODE) + << setw(12) << get_node_count_str(GRU_NODE) + << setw(12) << get_node_count_str(DELTA_NODE) + << setw(12) << get_node_count_str(LSTM_NODE) + << setw(12) << get_node_count_str(ENARC_NODE) + << setw(12) << get_node_count_str(ENAS_DAG_NODE) + << setw(12) << get_node_count_str(RANDOM_DAG_NODE) + << setw(12) << get_node_count_str(-1) //-1 does all nodes << generated_by_string(); return oss.str(); } @@ -256,17 +294,15 @@ string RNN_Genome::print_statistics() { double RNN_Genome::get_avg_recurrent_depth() const { int32_t count = 0; double average = 0.0; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->is_reachable()) { average += recurrent_edges[i]->get_recurrent_depth(); count++; } } - // in case there are no recurrent edges - if (count == 0) { - return 0; - } + //in case there are no recurrent edges + if (count == 0) return 0; return average / count; } @@ -289,20 +325,34 @@ string RNN_Genome::get_node_count_str(int32_t node_type) { int32_t enabled_nodes = get_enabled_node_count(node_type); int32_t total_nodes = get_node_count(node_type); - if (total_nodes > 0) { - oss << enabled_nodes << " (" << total_nodes << ")"; - } + if (total_nodes > 0) oss << enabled_nodes << " (" << total_nodes << ")"; } return oss.str(); } +//SHO SY TODO: const removed +double RNN_Genome::get_learning_rate(){ + return learning_rate; +} + +double RNN_Genome::get_initial_learning_rate(){ + return initial_learning_rate; +} + +double RNN_Genome::get_best_learning_rate(){ + return best_learning_rate; +} + +void RNN_Genome::set_learning_rate(double _learning_rate) { + learning_rate = _learning_rate; +} + + int32_t RNN_Genome::get_enabled_node_count() { int32_t count = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->enabled) { - count++; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->enabled) count++; } return count; @@ -311,39 +361,38 @@ int32_t RNN_Genome::get_enabled_node_count() { int32_t RNN_Genome::get_enabled_node_count(int32_t node_type) { int32_t count = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->enabled && nodes[i]->layer_type == HIDDEN_LAYER && nodes[i]->node_type == node_type) { - count++; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->enabled && nodes[i]->layer_type == HIDDEN_LAYER && nodes[i]->node_type == node_type) count++; } return count; } int32_t RNN_Genome::get_node_count() { - return (int32_t) nodes.size(); + return (int32_t)nodes.size(); } + int32_t RNN_Genome::get_node_count(int32_t node_type) { int32_t count = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->node_type == node_type) { - count++; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->node_type == node_type) count++; } return count; } + void RNN_Genome::clear_generated_by() { generated_by_map.clear(); } -void RNN_Genome::update_generation_map(map& generation_map) { +void RNN_Genome::update_generation_map(map &generation_map) { for (auto i = generated_by_map.begin(); i != generated_by_map.end(); i++) { generation_map[i->first] += i->second; } + } string RNN_Genome::generated_by_string() { @@ -351,9 +400,7 @@ string RNN_Genome::generated_by_string() { oss << "["; bool first = true; for (auto i = generated_by_map.begin(); i != generated_by_map.end(); i++) { - if (!first) { - oss << ", "; - } + if (!first) oss << ", "; oss << i->first << ":" << i->second; first = false; } @@ -362,7 +409,7 @@ string RNN_Genome::generated_by_string() { return oss.str(); } -const map* RNN_Genome::get_generated_by_map() { +const map *RNN_Genome::get_generated_by_map() { return &generated_by_map; } @@ -374,10 +421,7 @@ vector RNN_Genome::get_output_parameter_names() const { return output_parameter_names; } -void RNN_Genome::set_normalize_bounds( - string _normalize_type, const map& _normalize_mins, const map& _normalize_maxs, - const map& _normalize_avgs, const map& _normalize_std_devs -) { +void RNN_Genome::set_normalize_bounds(string _normalize_type, const map &_normalize_mins, const map &_normalize_maxs, const map &_normalize_avgs, const map &_normalize_std_devs) { normalize_type = _normalize_type; normalize_mins = _normalize_mins; normalize_maxs = _normalize_maxs; @@ -389,19 +433,19 @@ string RNN_Genome::get_normalize_type() const { return normalize_type; } -map RNN_Genome::get_normalize_mins() const { +map RNN_Genome::get_normalize_mins() const { return normalize_mins; } -map RNN_Genome::get_normalize_maxs() const { +map RNN_Genome::get_normalize_maxs() const { return normalize_maxs; } -map RNN_Genome::get_normalize_avgs() const { +map RNN_Genome::get_normalize_avgs() const { return normalize_avgs; } -map RNN_Genome::get_normalize_std_devs() const { +map RNN_Genome::get_normalize_std_devs() const { return normalize_std_devs; } @@ -416,10 +460,8 @@ void RNN_Genome::set_group_id(int32_t _group_id) { int32_t RNN_Genome::get_enabled_edge_count() { int32_t count = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->enabled) { - count++; - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->enabled) count++; } return count; @@ -428,10 +470,8 @@ int32_t RNN_Genome::get_enabled_edge_count() { int32_t RNN_Genome::get_enabled_recurrent_edge_count() { int32_t count = 0; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->enabled) { - count++; - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->enabled) count++; } return count; @@ -447,7 +487,7 @@ void RNN_Genome::set_bp_iterations(int32_t _bp_iterations) { // Log::info("Setting bp interation %d to genome %d \n", bp_iterations, generation_id); // } else { - bp_iterations = _bp_iterations; + bp_iterations = _bp_iterations; // } } @@ -490,58 +530,56 @@ void RNN_Genome::set_log_filename(string _log_filename) { log_filename = _log_filename; } -void RNN_Genome::get_weights(vector& parameters) { +void RNN_Genome::get_weights(vector ¶meters) { parameters.resize(get_number_weights()); int32_t current = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->get_weights(current, parameters); - // if (nodes[i]->is_reachable()) nodes[i]->get_weights(current, parameters); + //if (nodes[i]->is_reachable()) nodes[i]->get_weights(current, parameters); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { parameters[current++] = edges[i]->weight; - // if (edges[i]->is_reachable()) parameters[current++] = edges[i]->weight; + //if (edges[i]->is_reachable()) parameters[current++] = edges[i]->weight; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { parameters[current++] = recurrent_edges[i]->weight; - // if (recurrent_edges[i]->is_reachable()) parameters[current++] = recurrent_edges[i]->weight; + //if (recurrent_edges[i]->is_reachable()) parameters[current++] = recurrent_edges[i]->weight; } } -void RNN_Genome::set_weights(const vector& parameters) { - if ((int32_t) parameters.size() != get_number_weights()) { - Log::fatal( - "ERROR! Trying to set weights where the RNN has %d weights, and the parameters vector has %d weights!\n", - get_number_weights(), parameters.size() - ); +void RNN_Genome::set_weights(const vector ¶meters) { + if ((int32_t)parameters.size() != get_number_weights()) { + Log::fatal("ERROR! Trying to set weights where the RNN has %d weights, and the parameters vector has %d weights!\n", get_number_weights(), parameters.size()); exit(1); } int32_t current = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->set_weights(current, parameters); - // if (nodes[i]->is_reachable()) nodes[i]->set_weights(current, parameters); + //if (nodes[i]->is_reachable()) nodes[i]->set_weights(current, parameters); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { edges[i]->weight = bound(parameters[current++]); - // if (edges[i]->is_reachable()) edges[i]->weight = parameters[current++]; + //if (edges[i]->is_reachable()) edges[i]->weight = parameters[current++]; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { recurrent_edges[i]->weight = bound(parameters[current++]); - // if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->weight = parameters[current++]; + //if (recurrent_edges[i]->is_reachable()) recurrent_edges[i]->weight = parameters[current++]; } + } int32_t RNN_Genome::get_number_inputs() { int32_t number_inputs = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->get_layer_type() == INPUT_LAYER) { number_inputs++; } @@ -553,7 +591,7 @@ int32_t RNN_Genome::get_number_inputs() { int32_t RNN_Genome::get_number_outputs() { int32_t number_outputs = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->get_layer_type() == OUTPUT_LAYER) { number_outputs++; } @@ -562,44 +600,47 @@ int32_t RNN_Genome::get_number_outputs() { return number_outputs; } + int32_t RNN_Genome::get_number_weights() { int32_t number_weights = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { number_weights += nodes[i]->get_number_weights(); - // if (nodes[i]->is_reachable()) number_weights += nodes[i]->get_number_weights(); + //if (nodes[i]->is_reachable()) number_weights += nodes[i]->get_number_weights(); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { number_weights++; - // if (edges[i]->is_reachable()) number_weights++; + //if (edges[i]->is_reachable()) number_weights++; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { number_weights++; - // if (recurrent_edges[i]->is_reachable()) number_weights++; + //if (recurrent_edges[i]->is_reachable()) number_weights++; } return number_weights; } + double RNN_Genome::get_avg_edge_weight() { double avg_weight; double weights = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->enabled) { - if (edges[i]->weight > 10) { - Log::error("ERROR: edge %d has weight %f \n", i, edges[i]->weight); + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i] -> enabled) { + if(edges[i] -> weight > 10) { + Log::error("ERROR: edge %d has weight %f \n", i, edges[i]-> weight); } - weights += edges[i]->weight; + weights += edges[i] -> weight; } + } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->enabled) { - if (recurrent_edges[i]->weight > 10) { - Log::error("ERROR: recurrent edge %d has weight %f \n", i, recurrent_edges[i]->weight); + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i] -> enabled) { + if(recurrent_edges[i] -> weight > 10) { + Log::error("ERROR: recurrent edge %d has weight %f \n", i, recurrent_edges[i]-> weight); } - weights += recurrent_edges[i]->weight; + weights += recurrent_edges[i] -> weight; } } int32_t N = edges.size() + recurrent_edges.size(); @@ -614,25 +655,22 @@ void RNN_Genome::initialize_randomly() { WeightType weight_initialize = weight_rules->get_weight_initialize_method(); if (weight_initialize == WeightType::RANDOM) { - for (int32_t i = 0; i < (int32_t) initial_parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)initial_parameters.size(); i++) { initial_parameters[i] = rng(generator); } this->set_weights(initial_parameters); } else if (weight_initialize == WeightType::XAVIER) { - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { initialize_xavier(nodes[i]); } get_weights(initial_parameters); } else if (weight_initialize == WeightType::KAIMING) { - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { initialize_kaiming(nodes[i]); } get_weights(initial_parameters); } else { - Log::fatal( - "ERROR: trying to initialize a genome randomly with unknown weight initalization strategy: '%d'\n", - weight_initialize - ); + Log::fatal("ERROR: trying to initialize a genome randomly with unknown weight initalization strategy: '%d'\n", weight_initialize); exit(1); } @@ -641,21 +679,20 @@ void RNN_Genome::initialize_randomly() { } void RNN_Genome::initialize_xavier(RNN_Node_Interface* n) { - vector input_edges; - vector input_recurrent_edges; + + vector input_edges; + vector input_recurrent_edges; get_input_edges(n->innovation_number, input_edges, input_recurrent_edges); - int32_t fan_in = (int32_t) (input_edges.size() + input_recurrent_edges.size()); + int32_t fan_in = (int32_t)(input_edges.size() + input_recurrent_edges.size()); int32_t fan_out = get_fan_out(n->innovation_number); int32_t sum = fan_in + fan_out; - if (sum <= 0) { - sum = 1; - } - double range = sqrt(6) / sqrt(sum); - for (int32_t j = 0; j < (int32_t) input_edges.size(); j++) { + if(sum <= 0) sum = 1; + double range = sqrt(6)/sqrt(sum); + for(int32_t j = 0; j < (int32_t)input_edges.size(); j++) { double edge_weight = range * rng_1_1(generator); input_edges[j]->weight = edge_weight; } - for (int32_t j = 0; j < (int32_t) input_recurrent_edges.size(); j++) { + for(int32_t j = 0; j < (int32_t)input_recurrent_edges.size(); j++) { double edge_weight = range * rng_1_1(generator); input_recurrent_edges[j]->weight = edge_weight; } @@ -663,44 +700,40 @@ void RNN_Genome::initialize_xavier(RNN_Node_Interface* n) { } void RNN_Genome::initialize_kaiming(RNN_Node_Interface* n) { - vector input_edges; - vector input_recurrent_edges; + vector input_edges; + vector input_recurrent_edges; get_input_edges(n->innovation_number, input_edges, input_recurrent_edges); - int32_t fan_in = (int32_t) (input_edges.size() + input_recurrent_edges.size()); + int32_t fan_in = (int32_t)(input_edges.size() + input_recurrent_edges.size()); - if (fan_in <= 0) { - fan_in = 1; - } + if(fan_in <= 0) fan_in = 1; double range = sqrt(2) / sqrt(fan_in); - for (int32_t j = 0; j < (int32_t) input_edges.size(); j++) { + for(int32_t j = 0; j < (int32_t)input_edges.size(); j++) { double edge_weight = range * normal_distribution.random(generator, 0, 1); input_edges[j]->weight = edge_weight; } - for (int32_t j = 0; j < (int32_t) input_recurrent_edges.size(); j++) { + for(int32_t j = 0; j < (int32_t)input_recurrent_edges.size(); j++) { double edge_weight = range * normal_distribution.random(generator, 0, 1); input_recurrent_edges[j]->weight = edge_weight; } n->initialize_kaiming(generator, normal_distribution, range); } + double RNN_Genome::get_xavier_weight(RNN_Node_Interface* output_node) { int32_t sum = get_fan_in(output_node->innovation_number) + get_fan_out(output_node->innovation_number); - if (sum <= 0) { - sum = 1; - } - double range = sqrt(6) / sqrt(sum); + if(sum <= 0) sum =1; + double range = sqrt(6)/sqrt(sum); // double range = sqrt(6)/sqrt(output_node->fan_in + output_node->fan_out); return range * (rng_1_1(generator)); } double RNN_Genome::get_kaiming_weight(RNN_Node_Interface* output_node) { int32_t fan_in = get_fan_in(output_node->innovation_number); - if (fan_in <= 0) { - fan_in = 1; - } + if(fan_in <= 0) fan_in =1; double range = sqrt(2) / sqrt(fan_in); // double range = sqrt(6)/sqrt(output_node->fan_in + output_node->fan_out); return range * normal_distribution.random(generator, 0, 1); + } double RNN_Genome::get_random_weight() { @@ -713,17 +746,13 @@ void RNN_Genome::initialize_node_randomly(RNN_Node_Interface* n) { if (mutated_component_weight == weight_initialize) { if (weight_initialize == WeightType::XAVIER) { int32_t sum = get_fan_in(n->innovation_number) + get_fan_out(n->innovation_number); - if (sum <= 0) { - sum = 1; - } - double range = sqrt(6) / sqrt(sum); + if(sum <= 0) sum = 1; + double range = sqrt(6)/sqrt(sum); // double range = sqrt(6)/sqrt(n->fan_in + n->fan_out); n->initialize_xavier(generator, rng_1_1, range); } else if (weight_initialize == WeightType::KAIMING) { int32_t fan_in = get_fan_in(n->innovation_number); - if (fan_in <= 0) { - fan_in = 1; - } + if(fan_in <= 0) fan_in =1; double range = sqrt(2) / sqrt(fan_in); n->initialize_kaiming(generator, normal_distribution, range); } else if (weight_initialize == WeightType::RANDOM) { @@ -736,10 +765,8 @@ void RNN_Genome::initialize_node_randomly(RNN_Node_Interface* n) { } } -void RNN_Genome::get_input_edges( - int32_t node_innovation, vector& input_edges, vector& input_recurrent_edges -) { - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { +void RNN_Genome::get_input_edges(int32_t node_innovation, vector< RNN_Edge*> &input_edges, vector< RNN_Recurrent_Edge*> &input_recurrent_edges) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++){ if (edges[i]->enabled) { if (edges[i]->output_node->innovation_number == node_innovation) { input_edges.push_back(edges[i]); @@ -747,7 +774,7 @@ void RNN_Genome::get_input_edges( } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++){ if (recurrent_edges[i]->enabled) { if (recurrent_edges[i]->output_node->innovation_number == node_innovation) { input_recurrent_edges.push_back(recurrent_edges[i]); @@ -758,18 +785,18 @@ void RNN_Genome::get_input_edges( int32_t RNN_Genome::get_fan_in(int32_t node_innovation) { int32_t fan_in = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++){ if (edges[i]->enabled) { if (edges[i]->output_node->innovation_number == node_innovation) { - fan_in++; + fan_in ++; } } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++){ if (recurrent_edges[i]->enabled) { if (recurrent_edges[i]->output_node->innovation_number == node_innovation) { - fan_in++; + fan_in ++; } } } @@ -778,18 +805,18 @@ int32_t RNN_Genome::get_fan_in(int32_t node_innovation) { int32_t RNN_Genome::get_fan_out(int32_t node_innovation) { int32_t fan_out = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++){ if (edges[i]->enabled) { if (edges[i]->input_node->innovation_number == node_innovation) { - fan_out++; + fan_out ++; } } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++){ if (recurrent_edges[i]->enabled) { if (recurrent_edges[i]->input_node->innovation_number == node_innovation) { - fan_out++; + fan_out ++; } } } @@ -801,21 +828,19 @@ RNN* RNN_Genome::get_rnn() { vector edge_copies; vector recurrent_edge_copies; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - node_copies.push_back(nodes[i]->copy()); - // if (nodes[i]->layer_type == INPUT_LAYER || nodes[i]->layer_type == OUTPUT_LAYER || nodes[i]->is_reachable()) - // node_copies.push_back( nodes[i]->copy() ); + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + node_copies.push_back( nodes[i]->copy() ); + //if (nodes[i]->layer_type == INPUT_LAYER || nodes[i]->layer_type == OUTPUT_LAYER || nodes[i]->is_reachable()) node_copies.push_back( nodes[i]->copy() ); } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - edge_copies.push_back(edges[i]->copy(node_copies)); - // if (edges[i]->is_reachable()) edge_copies.push_back( edges[i]->copy(node_copies) ); + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + edge_copies.push_back( edges[i]->copy(node_copies) ); + //if (edges[i]->is_reachable()) edge_copies.push_back( edges[i]->copy(node_copies) ); } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - recurrent_edge_copies.push_back(recurrent_edges[i]->copy(node_copies)); - // if (recurrent_edges[i]->is_reachable()) recurrent_edge_copies.push_back( - // recurrent_edges[i]->copy(node_copies) ); + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + recurrent_edge_copies.push_back( recurrent_edges[i]->copy(node_copies) ); + //if (recurrent_edges[i]->is_reachable()) recurrent_edge_copies.push_back( recurrent_edges[i]->copy(node_copies) ); } return new RNN(node_copies, edge_copies, recurrent_edge_copies, input_parameter_names, output_parameter_names); @@ -825,13 +850,13 @@ vector RNN_Genome::get_best_parameters() const { return best_parameters; } -// INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING -void RNN_Genome::set_best_parameters(vector parameters) { +//INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING +void RNN_Genome::set_best_parameters( vector parameters) { best_parameters = parameters; } -// INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING -void RNN_Genome::set_initial_parameters(vector parameters) { +//INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING +void RNN_Genome::set_initial_parameters( vector parameters) { initial_parameters = parameters; } @@ -844,8 +869,9 @@ void RNN_Genome::set_generation_id(int32_t _generation_id) { } double RNN_Genome::get_fitness() const { + return best_validation_mse; - // return best_validation_mae; + //return best_validation_mae; } double RNN_Genome::get_best_validation_mse() const { @@ -856,6 +882,7 @@ double RNN_Genome::get_best_validation_mae() const { return best_validation_mae; } + void RNN_Genome::set_generated_by(string type) { generated_by_map[type]++; } @@ -868,53 +895,41 @@ bool RNN_Genome::sanity_check() { return true; } -void forward_pass_thread_regression( - RNN* rnn, const vector& parameters, const vector >& inputs, - const vector >& outputs, int32_t i, double* mses, bool use_dropout, bool training, - double dropout_probability -) { + +void forward_pass_thread_regression(RNN* rnn, const vector ¶meters, const vector< vector > &inputs, const vector< vector > &outputs, int32_t i, double *mses, bool use_dropout, bool training, double dropout_probability) { rnn->set_weights(parameters); rnn->forward_pass(inputs, use_dropout, training, dropout_probability); mses[i] = rnn->calculate_error_mse(outputs); - // mses[i] = rnn->calculate_error_mae(outputs); + //mses[i] = rnn->calculate_error_mae(outputs); Log::trace("mse[%d]: %lf\n", i, mses[i]); } -void forward_pass_thread_classification( - RNN* rnn, const vector& parameters, const vector >& inputs, - const vector >& outputs, int32_t i, double* mses, bool use_dropout, bool training, - double dropout_probability -) { +void forward_pass_thread_classification(RNN* rnn, const vector ¶meters, const vector< vector > &inputs, const vector< vector > &outputs, int32_t i, double *mses, bool use_dropout, bool training, double dropout_probability) { rnn->set_weights(parameters); rnn->forward_pass(inputs, use_dropout, training, dropout_probability); mses[i] = rnn->calculate_error_softmax(outputs); - // mses[i] = rnn->calculate_error_mae(outputs); + //mses[i] = rnn->calculate_error_mae(outputs); Log::trace("mse[%d]: %lf\n", i, mses[i]); } -void RNN_Genome::get_analytic_gradient( - vector& rnns, const vector& parameters, const vector > >& inputs, - const vector > >& outputs, double& mse, vector& analytic_gradient, bool training -) { - double* mses = new double[rnns.size()]; +void RNN_Genome::get_analytic_gradient(vector &rnns, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, double &mse, vector &analytic_gradient, bool training) { + + double *mses = new double[rnns.size()]; double mse_sum = 0.0; vector threads; - for (int32_t i = 0; i < (int32_t) rnns.size(); i++) { - threads.push_back(thread( - forward_pass_thread_regression, rnns[i], parameters, inputs[i], outputs[i], i, mses, use_dropout, training, - dropout_probability - )); + for (int32_t i = 0; i < (int32_t)rnns.size(); i++) { + threads.push_back( thread(forward_pass_thread_regression, rnns[i], parameters, inputs[i], outputs[i], i, mses, use_dropout, training, dropout_probability) ); } - for (int32_t i = 0; i < (int32_t) rnns.size(); i++) { + for (int32_t i = 0; i < (int32_t)rnns.size(); i++) { threads[i].join(); mse_sum += mses[i]; } - delete[] mses; + delete [] mses; - for (int32_t i = 0; i < (int32_t) rnns.size(); i++) { + for (int32_t i = 0; i < (int32_t)rnns.size(); i++) { double d_mse = 0.0; d_mse = mse_sum * (1.0 / outputs[i][0].size()) * 2.0; rnns[i]->backward_pass(d_mse, use_dropout, training, dropout_probability); @@ -924,12 +939,13 @@ void RNN_Genome::get_analytic_gradient( vector current_gradients; analytic_gradient.assign(parameters.size(), 0.0); - for (int32_t k = 0; k < (int32_t) rnns.size(); k++) { + for (int32_t k = 0; k < (int32_t)rnns.size(); k++) { + int32_t current = 0; for (int32_t i = 0; i < rnns[k]->get_number_nodes(); i++) { rnns[k]->get_node(i)->get_gradients(current_gradients); - for (int32_t j = 0; j < (int32_t) current_gradients.size(); j++) { + for (int32_t j = 0; j < (int32_t)current_gradients.size(); j++) { analytic_gradient[current] += current_gradients[j]; current++; } @@ -942,19 +958,18 @@ void RNN_Genome::get_analytic_gradient( } } -void RNN_Genome::backpropagate( - const vector > >& inputs, const vector > >& outputs, - const vector > >& validation_inputs, - const vector > >& validation_outputs, WeightUpdate* weight_update_method -) { + +void RNN_Genome::backpropagate(const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, const vector< vector< vector > > &validation_inputs, const vector< vector< vector > > &validation_outputs, WeightUpdate *weight_update_method) { + + Log::error("SY: learning rate backprop before: %lf",this->learning_rate); // double learning_rate = weight_update_method->get_learning_rate() / inputs.size(); // double low_threshold = sqrt(weight_update_method->get_low_threshold() * inputs.size()); // double high_threshold = sqrt(weight_update_method->get_high_threshold() * inputs.size()); - int32_t n_series = (int32_t) inputs.size(); + int32_t n_series = (int32_t)inputs.size(); vector rnns; for (int32_t i = 0; i < n_series; i++) { - rnns.push_back(this->get_rnn()); + rnns.push_back( this->get_rnn() ); } int32_t n_parameters = this->get_number_weights(); vector parameters = initial_parameters; @@ -966,7 +981,7 @@ void RNN_Genome::backpropagate( double mse; double norm = 0.0; - // initialize the initial previous values + //initialize the initial previous values get_analytic_gradient(rnns, parameters, inputs, outputs, mse, analytic_gradient, true); double validation_mse = get_mse(parameters, validation_inputs, validation_outputs); best_validation_mse = validation_mse; @@ -975,7 +990,7 @@ void RNN_Genome::backpropagate( norm = weight_update_method->get_norm(analytic_gradient); - ofstream* output_log = create_log_file(); + ofstream *output_log = create_log_file(); for (int32_t iteration = 0; iteration < bp_iterations; iteration++) { prev_gradient = analytic_gradient; @@ -989,18 +1004,20 @@ void RNN_Genome::backpropagate( } norm = weight_update_method->get_norm(analytic_gradient); if (output_log != NULL) { - (*output_log) << iteration << " " << mse << " " << validation_mse << " " << best_validation_mse << endl; + (*output_log) << iteration + << " " << mse + << " " << validation_mse + << " " << best_validation_mse << endl; } weight_update_method->norm_gradients(analytic_gradient, norm); - weight_update_method->update_weights(parameters, velocity, prev_velocity, analytic_gradient, iteration); - Log::info( - "iteration %10d, mse: %10lf, v_mse: %10lf, bv_mse: %10lf, norm: %lf", iteration, mse, validation_mse, - best_validation_mse, norm - ); + weight_update_method->update_weights(parameters, velocity, prev_velocity, analytic_gradient, iteration, this->learning_rate); + Log::info("iteration %10d, mse: %10lf, v_mse: %10lf, bv_mse: %10lf, norm: %lf", iteration, mse, validation_mse, best_validation_mse, norm); Log::info_no_header("\n"); + //TODO: In other implementation, here there was a use_nesterov_momentum if-else block which used learning rate to set + //prev_velocity } - RNN* g; + RNN *g; while (rnns.size() > 0) { g = rnns.back(); rnns.pop_back(); @@ -1009,13 +1026,9 @@ void RNN_Genome::backpropagate( this->set_weights(best_parameters); } -void RNN_Genome::backpropagate_stochastic( - const vector > >& inputs, const vector > >& outputs, - const vector > >& validation_inputs, - const vector > >& validation_outputs, WeightUpdate* weight_update_method -) { +void RNN_Genome::backpropagate_stochastic(const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, const vector< vector< vector > > &validation_inputs, const vector< vector< vector > > &validation_outputs, WeightUpdate *weight_update_method) { int32_t n_parameters = this->get_number_weights(); - int32_t n_series = (int32_t) inputs.size(); + int32_t n_series = (int32_t)inputs.size(); vector parameters = initial_parameters; vector velocity(n_parameters, 0.0); @@ -1027,25 +1040,19 @@ void RNN_Genome::backpropagate_stochastic( double norm = 0.0; RNN* rnn = get_rnn(); rnn->set_weights(parameters); - + std::chrono::time_point startClock = std::chrono::system_clock::now(); - // initialize the initial previous values + //initialize the initial previous values for (int32_t i = 0; i < n_series; i++) { - Log::trace( - "getting analytic gradient for input/output: %d, n_series: %d, parameters.size: %d, inputs.size(): %d, " - "outputs.size(): %d, log filename: '%s'\n", - i, n_series, parameters.size(), inputs.size(), outputs.size(), log_filename.c_str() - ); - rnn->get_analytic_gradient( - parameters, inputs[i], outputs[i], mse, analytic_gradient, use_dropout, true, dropout_probability - ); + Log::trace("getting analytic gradient for input/output: %d, n_series: %d, parameters.size: %d, inputs.size(): %d, outputs.size(): %d, log filename: '%s'\n", i, n_series, parameters.size(), inputs.size(), outputs.size(), log_filename.c_str()); + rnn->get_analytic_gradient(parameters, inputs[i], outputs[i], mse, analytic_gradient, use_dropout, true, dropout_probability); Log::trace("got analytic gradient.\n"); norm = weight_update_method->get_norm(analytic_gradient); } Log::trace("initialized previous values.\n"); - // TODO: need to get validation mse on the RNN not the genome + //TODO: need to get validation mse on the RNN not the genome double validation_mse = get_mse(parameters, validation_inputs, validation_outputs); best_validation_mse = validation_mse; best_validation_mae = get_mae(parameters, validation_inputs, validation_outputs); @@ -1054,11 +1061,11 @@ void RNN_Genome::backpropagate_stochastic( Log::trace("got initial mses.\n"); Log::info("initial validation_mse: %lf, best validation mse: %lf\n", validation_mse, best_validation_mse); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { Log::trace("parameters[%d]: %lf\n", i, parameters[i]); } - ofstream* output_log = create_log_file(); + ofstream *output_log = create_log_file(); for (int32_t iteration = 0; iteration < bp_iterations; iteration++) { vector shuffle_order; @@ -1067,17 +1074,14 @@ void RNN_Genome::backpropagate_stochastic( } fisher_yates_shuffle(generator, shuffle_order); double avg_norm = 0.0; - for (int32_t k = 0; k < (int32_t) shuffle_order.size(); k++) { + for (int32_t k = 0; k < (int32_t)shuffle_order.size(); k++) { int32_t random_selection = shuffle_order[k]; prev_gradient = analytic_gradient; - rnn->get_analytic_gradient( - parameters, inputs[random_selection], outputs[random_selection], mse, analytic_gradient, use_dropout, - true, dropout_probability - ); + rnn->get_analytic_gradient(parameters, inputs[random_selection], outputs[random_selection], mse, analytic_gradient, use_dropout, true, dropout_probability); norm = weight_update_method->get_norm(analytic_gradient); avg_norm += norm; weight_update_method->norm_gradients(analytic_gradient, norm); - weight_update_method->update_weights(parameters, velocity, prev_velocity, analytic_gradient, iteration); + weight_update_method->update_weights(parameters, velocity, prev_velocity, analytic_gradient, iteration, this->learning_rate); } this->set_weights(parameters); double training_mse = get_mse(parameters, inputs, outputs); @@ -1090,14 +1094,10 @@ void RNN_Genome::backpropagate_stochastic( } if (output_log != NULL) { std::chrono::time_point currentClock = std::chrono::system_clock::now(); - long milliseconds = - std::chrono::duration_cast(currentClock - startClock).count(); + long milliseconds = std::chrono::duration_cast(currentClock - startClock).count(); update_log_file(output_log, iteration, milliseconds, training_mse, validation_mse, avg_norm); } - Log::info( - "iteration %4d, mse: %5.10lf, v_mse: %5.10lf, bv_mse: %5.10lf, avg_norm: %5.10lf\n", iteration, - training_mse, validation_mse, best_validation_mse, avg_norm - ); + Log::trace("iteration %4d, mse: %5.10lf, v_mse: %5.10lf, bv_mse: %5.10lf, avg_norm: %5.10lf\n", iteration, training_mse, validation_mse, best_validation_mse, avg_norm); } delete rnn; this->set_weights(best_parameters); @@ -1107,7 +1107,7 @@ void RNN_Genome::backpropagate_stochastic( } ofstream* RNN_Genome::create_log_file() { - ofstream* output_log = NULL; + ofstream *output_log = NULL; if (log_filename != "") { Log::trace("creating new log stream for '%s'\n", log_filename.c_str()); output_log = new ofstream(log_filename); @@ -1125,12 +1125,9 @@ ofstream* RNN_Genome::create_log_file() { return output_log; } -void RNN_Genome::update_log_file( - ofstream* output_log, int32_t iteration, long milliseconds, double training_mse, double validation_mse, - double avg_norm -) { - // make sure the output log is good - if (!output_log->good()) { +void RNN_Genome::update_log_file(ofstream *output_log, int32_t iteration, long milliseconds, double training_mse, double validation_mse, double avg_norm) { + //make sure the output log is good + if ( !output_log->good() ) { output_log->close(); delete output_log; output_log = new ofstream(log_filename, std::ios_base::app); @@ -1140,21 +1137,23 @@ void RNN_Genome::update_log_file( exit(1); } } - (*output_log) << iteration << "," << milliseconds << "," << training_mse << "," << validation_mse << "," - << best_validation_mse << "," << best_validation_mae << "," << avg_norm << endl; + (*output_log) << iteration + << "," << milliseconds + << "," << training_mse + << "," << validation_mse + << "," << best_validation_mse + << "," << best_validation_mae + << "," << avg_norm << endl; } -double RNN_Genome::get_softmax( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs -) { - RNN* rnn = get_rnn(); +double RNN_Genome::get_softmax(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs) { + RNN *rnn = get_rnn(); rnn->set_weights(parameters); double softmax = 0.0; double avg_softmax = 0.0; - for (int32_t i = 0; i < (int32_t) inputs.size(); i++) { + for (int32_t i = 0; i < (int32_t)inputs.size(); i++) { softmax = rnn->prediction_softmax(inputs[i], outputs[i], use_dropout, false, dropout_probability); avg_softmax += softmax; @@ -1169,17 +1168,14 @@ double RNN_Genome::get_softmax( return avg_softmax; } -double RNN_Genome::get_mse( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs -) { - RNN* rnn = get_rnn(); +double RNN_Genome::get_mse(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs) { + RNN *rnn = get_rnn(); rnn->set_weights(parameters); double mse = 0.0; double avg_mse = 0.0; - for (int32_t i = 0; i < (int32_t) inputs.size(); i++) { + for (int32_t i = 0; i < (int32_t)inputs.size(); i++) { mse = rnn->prediction_mse(inputs[i], outputs[i], use_dropout, false, dropout_probability); avg_mse += mse; @@ -1194,17 +1190,14 @@ double RNN_Genome::get_mse( return avg_mse; } -double RNN_Genome::get_mae( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs -) { - RNN* rnn = get_rnn(); +double RNN_Genome::get_mae(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs) { + RNN *rnn = get_rnn(); rnn->set_weights(parameters); double mae; double avg_mae = 0.0; - for (int32_t i = 0; i < (int32_t) inputs.size(); i++) { + for (int32_t i = 0; i < (int32_t)inputs.size(); i++) { mae = rnn->prediction_mae(inputs[i], outputs[i], use_dropout, false, dropout_probability); avg_mae += mae; @@ -1219,17 +1212,14 @@ double RNN_Genome::get_mae( return avg_mae; } -vector > RNN_Genome::get_predictions( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs -) { - RNN* rnn = get_rnn(); +vector< vector > RNN_Genome::get_predictions(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs) { + RNN *rnn = get_rnn(); rnn->set_weights(parameters); - vector > all_results; + vector< vector > all_results; - // one input vector per testing file - for (int32_t i = 0; i < (int32_t) inputs.size(); i++) { + //one input vector per testing file + for (int32_t i = 0; i < (int32_t)inputs.size(); i++) { all_results.push_back(rnn->get_predictions(inputs[i], outputs[i], use_dropout, dropout_probability)); } @@ -1238,15 +1228,12 @@ vector > RNN_Genome::get_predictions( return all_results; } -void RNN_Genome::write_predictions( - string output_directory, const vector& input_filenames, const vector& parameters, - const vector > >& inputs, const vector > >& outputs, - TimeSeriesSets* time_series_sets -) { - RNN* rnn = get_rnn(); + +void RNN_Genome::write_predictions(string output_directory, const vector &input_filenames, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, TimeSeriesSets *time_series_sets) { + RNN *rnn = get_rnn(); rnn->set_weights(parameters); - for (int32_t i = 0; i < (int32_t) inputs.size(); i++) { + for (int32_t i = 0; i < (int32_t)inputs.size(); i++) { string filename = input_filenames[i]; Log::info("input filename[%5d]: '%s'\n", i, filename.c_str()); @@ -1254,23 +1241,20 @@ void RNN_Genome::write_predictions( string extension = filename.substr(last_dot_pos); string prefix = filename.substr(0, last_dot_pos); + string output_filename = prefix + "_predictions" + extension; output_filename = output_directory + "/" + output_filename.substr(output_filename.find_last_of("/") + 1); Log::info("output filename: '%s'\n", output_filename.c_str()); - rnn->write_predictions( - output_filename, input_parameter_names, output_parameter_names, inputs[i], outputs[i], time_series_sets, - use_dropout, dropout_probability - ); + rnn->write_predictions(output_filename, input_parameter_names, output_parameter_names, inputs[i], outputs[i], time_series_sets, use_dropout, dropout_probability); } delete rnn; } -// void RNN_Genome::write_predictions(string output_directory, const vector &input_filenames, const -// vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > -// > &outputs, Corpus *word_series_sets) { + +// void RNN_Genome::write_predictions(string output_directory, const vector &input_filenames, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, Corpus *word_series_sets) { // RNN *rnn = get_rnn(); // rnn->set_weights(parameters); @@ -1285,55 +1269,43 @@ void RNN_Genome::write_predictions( // string extension = filename.substr(last_dot_pos); // string prefix = filename.substr(0, last_dot_pos); + // string output_filename = prefix + "_predictions" + extension; // output_filename = output_directory + "/" + output_filename.substr(output_filename.find_last_of("/") + 1); // Log::info("output filename: '%s'\n", output_filename.c_str()); -// rnn->write_predictions(output_filename, input_parameter_names, output_parameter_names, inputs[i], outputs[i], -// word_series_sets, use_dropout, dropout_probability); +// rnn->write_predictions(output_filename, input_parameter_names, output_parameter_names, inputs[i], outputs[i], word_series_sets, use_dropout, dropout_probability); // } // delete rnn; // } bool RNN_Genome::has_node_with_innovation(int32_t innovation_number) const { - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->get_innovation_number() == innovation_number) { - return true; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->get_innovation_number() == innovation_number) return true; } return false; } bool RNN_Genome::equals(RNN_Genome* other) { - if (nodes.size() != other->nodes.size()) { - return false; - } - if (edges.size() != other->edges.size()) { - return false; - } - if (recurrent_edges.size() != other->recurrent_edges.size()) { - return false; - } - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (!nodes[i]->equals(other->nodes[i])) { - return false; - } + if (nodes.size() != other->nodes.size()) return false; + if (edges.size() != other->edges.size()) return false; + if (recurrent_edges.size() != other->recurrent_edges.size()) return false; + + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (!nodes[i]->equals(other->nodes[i])) return false; } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (!edges[i]->equals(other->edges[i])) { - return false; - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (!edges[i]->equals(other->edges[i])) return false; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (!recurrent_edges[i]->equals(other->recurrent_edges[i])) { - return false; - } + + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (!recurrent_edges[i]->equals(other->recurrent_edges[i])) return false; } return true; @@ -1343,13 +1315,13 @@ void RNN_Genome::assign_reachability() { Log::trace("assigning reachability!\n"); Log::trace("%6d nodes, %6d edges, %6d recurrent edges\n", nodes.size(), edges.size(), recurrent_edges.size()); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { nodes[i]->forward_reachable = false; nodes[i]->backward_reachable = false; nodes[i]->total_inputs = 0; nodes[i]->total_outputs = 0; - // set enabled input nodes as reachable + //set enabled input nodes as reachable if (nodes[i]->layer_type == INPUT_LAYER && nodes[i]->enabled) { nodes[i]->forward_reachable = true; nodes[i]->total_inputs = 1; @@ -1363,36 +1335,35 @@ void RNN_Genome::assign_reachability() { } } - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { edges[i]->forward_reachable = false; edges[i]->backward_reachable = false; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { recurrent_edges[i]->forward_reachable = false; recurrent_edges[i]->backward_reachable = false; } - // do forward reachability + //do forward reachability vector nodes_to_visit; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->layer_type == INPUT_LAYER && nodes[i]->enabled) { nodes_to_visit.push_back(nodes[i]); } } while (nodes_to_visit.size() > 0) { - RNN_Node_Interface* current = nodes_to_visit.back(); + RNN_Node_Interface *current = nodes_to_visit.back(); nodes_to_visit.pop_back(); - // if the node is not enabled, we don't need to do anything - if (!current->enabled) { - continue; - } + //if the node is not enabled, we don't need to do anything + if (!current->enabled) continue; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->input_innovation_number == current->innovation_number && edges[i]->enabled) { - // this is an edge coming out of this node + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->input_innovation_number == current->innovation_number && + edges[i]->enabled) { + //this is an edge coming out of this node if (edges[i]->output_node->enabled) { edges[i]->forward_reachable = true; @@ -1409,14 +1380,12 @@ void RNN_Genome::assign_reachability() { } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->forward_reachable) { - continue; - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->forward_reachable) continue; - if (recurrent_edges[i]->input_innovation_number == current->innovation_number - && recurrent_edges[i]->enabled) { - // this is an recurrent_edge coming out of this node + if (recurrent_edges[i]->input_innovation_number == current->innovation_number && + recurrent_edges[i]->enabled) { + //this is an recurrent_edge coming out of this node if (recurrent_edges[i]->output_node->enabled) { recurrent_edges[i]->forward_reachable = true; @@ -1424,7 +1393,7 @@ void RNN_Genome::assign_reachability() { if (recurrent_edges[i]->output_node->forward_reachable == false) { recurrent_edges[i]->output_node->forward_reachable = true; - // handle the edge case when a recurrent edge loops back on itself + //handle the edge case when a recurrent edge loops back on itself nodes_to_visit.push_back(recurrent_edges[i]->output_node); } } @@ -1432,26 +1401,25 @@ void RNN_Genome::assign_reachability() { } } - // do backward reachability + //do backward reachability nodes_to_visit.clear(); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->layer_type == OUTPUT_LAYER && nodes[i]->enabled) { nodes_to_visit.push_back(nodes[i]); } } while (nodes_to_visit.size() > 0) { - RNN_Node_Interface* current = nodes_to_visit.back(); + RNN_Node_Interface *current = nodes_to_visit.back(); nodes_to_visit.pop_back(); - // if the node is not enabled, we don't need to do anything - if (!current->enabled) { - continue; - } + //if the node is not enabled, we don't need to do anything + if (!current->enabled) continue; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->output_innovation_number == current->innovation_number && edges[i]->enabled) { - // this is an edge coming out of this node + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->output_innovation_number == current->innovation_number && + edges[i]->enabled) { + //this is an edge coming out of this node if (edges[i]->input_node->enabled) { edges[i]->backward_reachable = true; @@ -1463,10 +1431,10 @@ void RNN_Genome::assign_reachability() { } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->output_innovation_number == current->innovation_number - && recurrent_edges[i]->enabled) { - // this is an recurrent_edge coming out of this node + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->output_innovation_number == current->innovation_number && + recurrent_edges[i]->enabled) { + //this is an recurrent_edge coming out of this node if (recurrent_edges[i]->input_node->enabled) { recurrent_edges[i]->backward_reachable = true; @@ -1479,15 +1447,15 @@ void RNN_Genome::assign_reachability() { } } - // set inputs/outputs - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + //set inputs/outputs + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->is_reachable()) { edges[i]->input_node->total_outputs++; edges[i]->output_node->total_inputs++; } } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->is_reachable()) { recurrent_edges[i]->input_node->total_outputs++; recurrent_edges[i]->output_node->total_inputs++; @@ -1496,72 +1464,62 @@ void RNN_Genome::assign_reachability() { if (Log::at_level(Log::TRACE)) { Log::trace("node reachabiltity:\n"); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - RNN_Node_Interface* n = nodes[i]; - Log::trace( - "node %5d, e: %d, fr: %d, br: %d, ti: %5d, to: %5d\n", n->innovation_number, n->enabled, - n->forward_reachable, n->backward_reachable, n->total_inputs, n->total_outputs - ); + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + RNN_Node_Interface *n = nodes[i]; + Log::trace("node %5d, e: %d, fr: %d, br: %d, ti: %5d, to: %5d\n", n->innovation_number, n->enabled, n->forward_reachable, n->backward_reachable, n->total_inputs, n->total_outputs); } Log::trace("edge reachabiltity:\n"); - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - RNN_Edge* e = edges[i]; - Log::trace( - "edge %5d, e: %d, fr: %d, br: %d\n", e->innovation_number, e->enabled, e->forward_reachable, - e->backward_reachable - ); + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + RNN_Edge *e = edges[i]; + Log::trace("edge %5d, e: %d, fr: %d, br: %d\n", e->innovation_number, e->enabled, e->forward_reachable, e->backward_reachable); } Log::trace("recurrent edge reachabiltity:\n"); - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - RNN_Recurrent_Edge* e = recurrent_edges[i]; - Log::trace( - "recurrent edge %5d, e: %d, fr: %d, br: %d\n", e->innovation_number, e->enabled, e->forward_reachable, - e->backward_reachable - ); + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + RNN_Recurrent_Edge *e = recurrent_edges[i]; + Log::trace("recurrent edge %5d, e: %d, fr: %d, br: %d\n", e->innovation_number, e->enabled, e->forward_reachable, e->backward_reachable); } } - // calculate structural hash + //calculate structural hash long node_hash = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->is_reachable() && nodes[i]->is_enabled()) { node_hash += nodes[i]->get_innovation_number(); } } long edge_hash = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->is_reachable() && edges[i]->is_enabled()) { edge_hash += edges[i]->get_innovation_number(); } } long recurrent_edge_hash = 0; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->is_reachable() && recurrent_edges[i]->is_enabled()) { recurrent_edge_hash += recurrent_edges[i]->get_innovation_number(); } } structural_hash = to_string(node_hash) + "_" + to_string(edge_hash) + "_" + to_string(recurrent_edge_hash); - // Log::info("genome had structural hash: '%s'\n", structural_hash.c_str()); + //Log::info("genome had structural hash: '%s'\n", structural_hash.c_str()); } + bool RNN_Genome::outputs_unreachable() { assign_reachability(); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type == OUTPUT_LAYER && !nodes[i]->is_reachable()) { - return true; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type == OUTPUT_LAYER && !nodes[i]->is_reachable()) return true; } return false; } -void RNN_Genome::get_mu_sigma(const vector& p, double& mu, double& sigma) { +void RNN_Genome::get_mu_sigma(const vector &p, double &mu, double &sigma) { if (p.size() == 0) { mu = 0.0; sigma = 0.25; @@ -1572,7 +1530,7 @@ void RNN_Genome::get_mu_sigma(const vector& p, double& mu, double& sigma mu = 0.0; sigma = 0.0; - for (int32_t i = 0; i < (int32_t) p.size(); i++) { + for (int32_t i = 0; i < (int32_t)p.size(); i++) { /* if (p[i] < -10 || p[i] > 10) { Log::fatal("ERROR in get_mu_sigma, parameter[%d] was out of bounds: %lf\n", i, p[i]); @@ -1584,18 +1542,14 @@ void RNN_Genome::get_mu_sigma(const vector& p, double& mu, double& sigma } */ - if (p[i] < -10) { - mu += -10.0; - } else if (p[i] > 10) { - mu += 10.0; - } else { - mu += p[i]; - } + if (p[i] < -10) mu += -10.0; + else if (p[i] > 10) mu += 10.0; + else mu += p[i]; } mu /= p.size(); double temp; - for (int32_t i = 0; i < (int32_t) p.size(); i++) { + for (int32_t i = 0; i < (int32_t)p.size(); i++) { temp = (mu - p[i]) * (mu - p[i]); sigma += temp; } @@ -1605,7 +1559,7 @@ void RNN_Genome::get_mu_sigma(const vector& p, double& mu, double& sigma Log::debug("\tmu: %lf, sigma: %lf, parameters.size(): %d\n", mu, sigma, p.size()); if (std::isnan(mu) || std::isinf(mu) || std::isnan(sigma) || std::isinf(sigma)) { Log::fatal("mu or sigma was not a number, all parameters:\n"); - for (int32_t i = 0; i < (int32_t) p.size(); i++) { + for (int32_t i = 0; i < (int32_t)p.size(); i++) { Log::fatal("\t%lf\n", p[i]); } exit(1); @@ -1613,17 +1567,16 @@ void RNN_Genome::get_mu_sigma(const vector& p, double& mu, double& sigma if (mu < -11.0 || mu > 11.0 || sigma < -30.0 || sigma > 30.0) { Log::fatal("mu or sigma exceeded possible bounds (11 or 30), all parameters:\n"); - for (int32_t i = 0; i < (int32_t) p.size(); i++) { + for (int32_t i = 0; i < (int32_t)p.size(); i++) { Log::fatal("\t%lf\n", p[i]); } exit(1); } } -RNN_Node_Interface* RNN_Genome::create_node( - double mu, double sigma, int32_t node_type, int32_t& node_innovation_count, double depth -) { - RNN_Node_Interface* n = NULL; + +RNN_Node_Interface* RNN_Genome::create_node(double mu, double sigma, int32_t node_type, int32_t &node_innovation_count, double depth) { + RNN_Node_Interface *n = NULL; WeightType mutated_component_weight = weight_rules->get_mutated_components_weight_method(); WeightType weight_initialize = weight_rules->get_weight_initialize_method(); @@ -1634,11 +1587,11 @@ RNN_Node_Interface* RNN_Genome::create_node( n = new Delta_Node(++node_innovation_count, HIDDEN_LAYER, depth); } else if (node_type == GRU_NODE) { n = new GRU_Node(++node_innovation_count, HIDDEN_LAYER, depth); - } else if (node_type == ENARC_NODE) { + } else if (node_type == ENARC_NODE) { n = new ENARC_Node(++node_innovation_count, HIDDEN_LAYER, depth); - } else if (node_type == ENAS_DAG_NODE) { + } else if (node_type == ENAS_DAG_NODE) { n = new ENAS_DAG_Node(++node_innovation_count, HIDDEN_LAYER, depth); - } else if (node_type == RANDOM_DAG_NODE) { + } else if (node_type == RANDOM_DAG_NODE) { n = new RANDOM_DAG_Node(++node_innovation_count, HIDDEN_LAYER, depth); } else if (node_type == MGU_NODE) { n = new MGU_Node(++node_innovation_count, HIDDEN_LAYER, depth); @@ -1655,25 +1608,18 @@ RNN_Node_Interface* RNN_Genome::create_node( Log::debug("new component weight is lamarckian, setting new node weight to lamarckian \n"); n->initialize_lamarckian(generator, normal_distribution, mu, sigma); } else if (mutated_component_weight == weight_initialize) { - Log::debug( - "new component weight is %s, setting new node's weight randomly with %s method \n", - WEIGHT_TYPES_STRING[mutated_component_weight].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::debug("new component weight is %s, setting new node's weight randomly with %s method \n", WEIGHT_TYPES_STRING[mutated_component_weight].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); initialize_node_randomly(n); } else { - Log::fatal( - "new component weight is not set correctly, weight initialize: %s, new component weight: %s. \n", - WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::fatal("new component weight is not set correctly, weight initialize: %s, new component weight: %s. \n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); exit(1); } + return n; } -bool RNN_Genome::attempt_edge_insert( - RNN_Node_Interface* n1, RNN_Node_Interface* n2, double mu, double sigma, int32_t& edge_innovation_count -) { +bool RNN_Genome::attempt_edge_insert(RNN_Node_Interface *n1, RNN_Node_Interface *n2, double mu, double sigma, int32_t &edge_innovation_count) { Log::trace("\tadding edge between nodes %d and %d\n", n1->innovation_number, n2->innovation_number); WeightType mutated_component_weight = weight_rules->get_mutated_components_weight_method(); WeightType weight_initialize = weight_rules->get_weight_initialize_method(); @@ -1684,19 +1630,20 @@ bool RNN_Genome::attempt_edge_insert( } if (n2->depth < n1->depth) { - // swap the nodes so that the lower one is first - RNN_Node_Interface* temp = n2; + //swap the nodes so that the lower one is first + RNN_Node_Interface *temp = n2; n2 = n1; n1 = temp; Log::trace("\tswaping nodes, because n2->depth < n1->depth\n"); } - // check to see if an edge between the two nodes already exists - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->input_innovation_number == n1->innovation_number - && edges[i]->output_innovation_number == n2->innovation_number) { + + //check to see if an edge between the two nodes already exists + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->input_innovation_number == n1->innovation_number && + edges[i]->output_innovation_number == n2->innovation_number) { if (!edges[i]->enabled) { - // edge was disabled so we can enable it + //edge was disabled so we can enable it Log::trace("\tedge already exists but was disabled, enabling it.\n"); edges[i]->enabled = true; // edges[i]->input_node->fan_out++; @@ -1704,13 +1651,13 @@ bool RNN_Genome::attempt_edge_insert( return true; } else { Log::trace("\tedge already exists, not adding.\n"); - // edge was already enabled, so there will not be a change + //edge was already enabled, so there will not be a change return false; } } } - RNN_Edge* e = new RNN_Edge(++edge_innovation_count, n1, n2); + RNN_Edge *e = new RNN_Edge(++edge_innovation_count, n1, n2); if (mutated_component_weight == weight_initialize) { Log::debug("setting new edge weight with %s method \n", WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); if (weight_initialize == WeightType::XAVIER) { @@ -1725,64 +1672,50 @@ bool RNN_Genome::attempt_edge_insert( } else { Log::fatal("weight initialization method %d is not set correctly \n", weight_initialize); } - } else if (mutated_component_weight == WeightType::LAMARCKIAN) { + } else if (mutated_component_weight == WeightType::LAMARCKIAN){ Log::debug("setting new edge weight with Lamarckian method \n"); e->weight = bound(normal_distribution.random(generator, mu, sigma)); } else { - Log::fatal( - "new component weight method is not set correctly, weight initialize: %s, new component weight: %s\n", - WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::fatal("new component weight method is not set correctly, weight initialize: %s, new component weight: %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); } - Log::trace( - "\tadding edge between nodes %d and %d, new edge weight: %lf\n", e->input_innovation_number, - e->output_innovation_number, e->weight - ); - edges.insert(upper_bound(edges.begin(), edges.end(), e, sort_RNN_Edges_by_depth()), e); + Log::trace("\tadding edge between nodes %d and %d, new edge weight: %lf\n", e->input_innovation_number, e->output_innovation_number, e->weight); + edges.insert( upper_bound(edges.begin(), edges.end(), e, sort_RNN_Edges_by_depth()), e); return true; } -bool RNN_Genome::attempt_recurrent_edge_insert( - RNN_Node_Interface* n1, RNN_Node_Interface* n2, double mu, double sigma, uniform_int_distribution dist, - int32_t& edge_innovation_count -) { +bool RNN_Genome::attempt_recurrent_edge_insert(RNN_Node_Interface *n1, RNN_Node_Interface *n2, double mu, double sigma, uniform_int_distribution dist, int32_t &edge_innovation_count) { Log::trace("\tadding recurrent edge between nodes %d and %d\n", n1->innovation_number, n2->innovation_number); WeightType mutated_component_weight = weight_rules->get_mutated_components_weight_method(); WeightType weight_initialize = weight_rules->get_weight_initialize_method(); - // int32_t recurrent_depth = 1 + (rng_0_1(generator) * (max_recurrent_depth - 1)); + //int32_t recurrent_depth = 1 + (rng_0_1(generator) * (max_recurrent_depth - 1)); int32_t recurrent_depth = dist(generator); - // check to see if an edge between the two nodes already exists - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->input_innovation_number == n1->innovation_number - && recurrent_edges[i]->output_innovation_number == n2->innovation_number - && recurrent_edges[i]->recurrent_depth == recurrent_depth) { + //check to see if an edge between the two nodes already exists + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->input_innovation_number == n1->innovation_number && + recurrent_edges[i]->output_innovation_number == n2->innovation_number + && recurrent_edges[i]->recurrent_depth == recurrent_depth) { + if (!recurrent_edges[i]->enabled) { - // edge was disabled so we can enable it + //edge was disabled so we can enable it Log::trace("\trecurrent edge already exists but was disabled, enabling it.\n"); recurrent_edges[i]->enabled = true; // recurrent_edges[i]->input_node->fan_out++; // recurrent_edges[i]->output_node->fan_in++; return true; } else { - Log::trace( - "\tenabled recurrent edge already existed between selected nodes %d and %d at recurrent depth: " - "%d\n", - n1->innovation_number, n2->innovation_number, recurrent_depth - ); - // edge was already enabled, so there will not be a change + Log::trace("\tenabled recurrent edge already existed between selected nodes %d and %d at recurrent depth: %d\n", n1->innovation_number, n2->innovation_number, recurrent_depth); + //edge was already enabled, so there will not be a change return false; } } } - RNN_Recurrent_Edge* e = new RNN_Recurrent_Edge(++edge_innovation_count, recurrent_depth, n1, n2); + RNN_Recurrent_Edge *e = new RNN_Recurrent_Edge(++edge_innovation_count, recurrent_depth, n1, n2); if (mutated_component_weight == weight_initialize) { - Log::debug( - "setting new recurrent edge weight with %s method \n", WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::debug("setting new recurrent edge weight with %s method \n", WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); if (weight_initialize == WeightType::XAVIER) { Log::debug("setting new recurrent edge weight to Xavier \n"); e->weight = get_xavier_weight(n2); @@ -1795,60 +1728,48 @@ bool RNN_Genome::attempt_recurrent_edge_insert( } else { Log::fatal("Weight initialization method %d is not set correctly \n", weight_initialize); } - } else if (mutated_component_weight == WeightType::LAMARCKIAN) { + } else if (mutated_component_weight == WeightType::LAMARCKIAN){ Log::debug("setting new recurrent edge weight with Lamarckian method \n"); e->weight = bound(normal_distribution.random(generator, mu, sigma)); } else { - Log::fatal( - "new component weight method is not set correctly, weight initialize: %s, new component weight: %s\n", - WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str() - ); + Log::fatal("new component weight method is not set correctly, weight initialize: %s, new component weight: %s\n", WEIGHT_TYPES_STRING[weight_initialize].c_str(), WEIGHT_TYPES_STRING[mutated_component_weight].c_str()); } - Log::trace( - "\tadding recurrent edge with innovation number %d between nodes %d and %d, new edge weight: %d\n", - e->innovation_number, e->input_innovation_number, e->output_innovation_number, e->weight - ); + Log::trace("\tadding recurrent edge with innovation number %d between nodes %d and %d, new edge weight: %d\n", e->innovation_number, e->input_innovation_number, e->output_innovation_number, e->weight); - recurrent_edges.insert( - upper_bound(recurrent_edges.begin(), recurrent_edges.end(), e, sort_RNN_Recurrent_Edges_by_depth()), e - ); + recurrent_edges.insert( upper_bound(recurrent_edges.begin(), recurrent_edges.end(), e, sort_RNN_Recurrent_Edges_by_depth()), e); return true; } -void RNN_Genome::generate_recurrent_edges( - RNN_Node_Interface* node, double mu, double sigma, uniform_int_distribution dist, - int32_t& edge_innovation_count -) { +void RNN_Genome::generate_recurrent_edges(RNN_Node_Interface *node, double mu, double sigma, uniform_int_distribution dist, int32_t &edge_innovation_count) { + if (node->node_type == JORDAN_NODE) { - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->input_innovation_number == node->innovation_number && edges[i]->enabled) { attempt_recurrent_edge_insert(edges[i]->output_node, node, mu, sigma, dist, edge_innovation_count); } } } else if (node->node_type == ELMAN_NODE) { - // elman nodes have a circular reference to themselves + //elman nodes have a circular reference to themselves attempt_recurrent_edge_insert(node, node, mu, sigma, dist, edge_innovation_count); } } -bool RNN_Genome::add_edge(double mu, double sigma, int32_t& edge_innovation_count) { +bool RNN_Genome::add_edge(double mu, double sigma, int32_t &edge_innovation_count) { Log::trace("\tattempting to add edge!\n"); vector reachable_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->is_reachable()) { - reachable_nodes.push_back(nodes[i]); - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->is_reachable()) reachable_nodes.push_back(nodes[i]); } Log::trace("\treachable_nodes.size(): %d\n", reachable_nodes.size()); int32_t position = rng_0_1(generator) * reachable_nodes.size(); - RNN_Node_Interface* n1 = reachable_nodes[position]; + RNN_Node_Interface *n1 = reachable_nodes[position]; Log::trace("\tselected first node %d with depth %d\n", n1->innovation_number, n1->depth); - // printf("pos: %d, size: %d\n", position, reachable_nodes.size()); + //printf("pos: %d, size: %d\n", position, reachable_nodes.size()); - for (int32_t i = 0; i < (int32_t) reachable_nodes.size();) { + for (int32_t i = 0; i < (int32_t)reachable_nodes.size();) { auto it = reachable_nodes[i]; if (it->depth == n1->depth) { reachable_nodes.erase(reachable_nodes.begin() + i); @@ -1869,21 +1790,20 @@ bool RNN_Genome::add_edge(double mu, double sigma, int32_t& edge_innovation_coun Log::trace("\treachable_nodes.size(): %d\n", reachable_nodes.size()); + position = rng_0_1(generator) * reachable_nodes.size(); - RNN_Node_Interface* n2 = reachable_nodes[position]; + RNN_Node_Interface *n2 = reachable_nodes[position]; Log::trace("\tselected second node %d with depth %d\n", n2->innovation_number, n2->depth); return attempt_edge_insert(n1, n2, mu, sigma, edge_innovation_count); } -bool RNN_Genome::add_recurrent_edge( - double mu, double sigma, uniform_int_distribution dist, int32_t& edge_innovation_count -) { +bool RNN_Genome::add_recurrent_edge(double mu, double sigma, uniform_int_distribution dist, int32_t &edge_innovation_count) { Log::trace("\tattempting to add recurrent edge!\n"); vector possible_input_nodes; vector possible_output_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->is_reachable()) { possible_input_nodes.push_back(nodes[i]); @@ -1896,77 +1816,65 @@ bool RNN_Genome::add_recurrent_edge( Log::trace("\tpossible_input_nodes.size(): %d\n", possible_input_nodes.size()); Log::trace("\tpossible_output_nodes.size(): %d\n", possible_output_nodes.size()); - if (possible_input_nodes.size() == 0) { - return false; - } - if (possible_output_nodes.size() == 0) { - return false; - } + if (possible_input_nodes.size() == 0) return false; + if (possible_output_nodes.size() == 0) return false; int32_t p1 = rng_0_1(generator) * possible_input_nodes.size(); int32_t p2 = rng_0_1(generator) * possible_output_nodes.size(); - // no need to swap the nodes as recurrent connections can go backwards + //no need to swap the nodes as recurrent connections can go backwards - RNN_Node_Interface* n1 = possible_input_nodes[p1]; + RNN_Node_Interface *n1 = possible_input_nodes[p1]; Log::trace("\tselected first node %d with depth %d\n", n1->innovation_number, n1->depth); - RNN_Node_Interface* n2 = possible_output_nodes[p2]; + RNN_Node_Interface *n2 = possible_output_nodes[p2]; Log::trace("\tselected second node %d with depth %d\n", n2->innovation_number, n2->depth); return attempt_recurrent_edge_insert(n1, n2, mu, sigma, dist, edge_innovation_count); } -// TODO: should probably change these to enable/disable path + +//TODO: should probably change these to enable/disable path bool RNN_Genome::disable_edge() { - // TODO: edge should be reachable + //TODO: edge should be reachable vector enabled_edges; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->enabled) { - enabled_edges.push_back(edges[i]); - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->enabled) enabled_edges.push_back(edges[i]); } vector enabled_recurrent_edges; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->enabled) { - enabled_recurrent_edges.push_back(recurrent_edges[i]); - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->enabled) enabled_recurrent_edges.push_back(recurrent_edges[i]); } if ((enabled_edges.size() + enabled_recurrent_edges.size()) == 0) { return false; } + int32_t position = (enabled_edges.size() + enabled_recurrent_edges.size()) * rng_0_1(generator); - if (position < (int32_t) enabled_edges.size()) { + if (position < (int32_t)enabled_edges.size()) { enabled_edges[position]->enabled = false; - // innovation_list.erase(std::remove(innovation_list.begin(), innovation_list.end(), - // enabled_edges[position]->get_innovation_number()), innovation_list.end()); + // innovation_list.erase(std::remove(innovation_list.begin(), innovation_list.end(), enabled_edges[position]->get_innovation_number()), innovation_list.end()); return true; } else { position -= enabled_edges.size(); enabled_recurrent_edges[position]->enabled = false; - // innovation_list.erase(std::remove(innovation_list.begin(), innovation_list.end(), - // enabled_edges[position]->get_innovation_number()), innovation_list.end()); + // innovation_list.erase(std::remove(innovation_list.begin(), innovation_list.end(), enabled_edges[position]->get_innovation_number()), innovation_list.end()); return true; } } bool RNN_Genome::enable_edge() { - // TODO: edge should be reachable + //TODO: edge should be reachable vector disabled_edges; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (!edges[i]->enabled) { - disabled_edges.push_back(edges[i]); - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (!edges[i]->enabled) disabled_edges.push_back(edges[i]); } vector disabled_recurrent_edges; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (!recurrent_edges[i]->enabled) { - disabled_recurrent_edges.push_back(recurrent_edges[i]); - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (!recurrent_edges[i]->enabled) disabled_recurrent_edges.push_back(recurrent_edges[i]); } if ((disabled_edges.size() + disabled_recurrent_edges.size()) == 0) { @@ -1975,7 +1883,7 @@ bool RNN_Genome::enable_edge() { int32_t position = (disabled_edges.size() + disabled_recurrent_edges.size()) * rng_0_1(generator); - if (position < (int32_t) disabled_edges.size()) { + if (position < (int32_t)disabled_edges.size()) { disabled_edges[position]->enabled = true; // innovation_list.push_back(disabled_edges[position]->get_innovation_number); return true; @@ -1987,48 +1895,42 @@ bool RNN_Genome::enable_edge() { } } -bool RNN_Genome::split_edge( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t& edge_innovation_count, - int32_t& node_innovation_count -) { + +bool RNN_Genome::split_edge(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count) { Log::trace("\tattempting to split an edge!\n"); vector enabled_edges; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->enabled) { - enabled_edges.push_back(edges[i]); - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->enabled) enabled_edges.push_back(edges[i]); } vector enabled_recurrent_edges; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->enabled) { - enabled_recurrent_edges.push_back(recurrent_edges[i]); - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->enabled) enabled_recurrent_edges.push_back(recurrent_edges[i]); } int32_t position = rng_0_1(generator) * (enabled_edges.size() + enabled_recurrent_edges.size()); bool was_forward_edge = false; - RNN_Node_Interface* n1 = NULL; - RNN_Node_Interface* n2 = NULL; - if (position < (int32_t) enabled_edges.size()) { - RNN_Edge* edge = enabled_edges[position]; + RNN_Node_Interface *n1 = NULL; + RNN_Node_Interface *n2 = NULL; + if (position < (int32_t)enabled_edges.size()) { + RNN_Edge *edge = enabled_edges[position]; n1 = edge->input_node; n2 = edge->output_node; edge->enabled = false; was_forward_edge = true; } else { position -= enabled_edges.size(); - RNN_Recurrent_Edge* recurrent_edge = enabled_recurrent_edges[position]; + RNN_Recurrent_Edge *recurrent_edge = enabled_recurrent_edges[position]; n1 = recurrent_edge->input_node; n2 = recurrent_edge->output_node; recurrent_edge->enabled = false; } double new_depth = (n1->get_depth() + n2->get_depth()) / 2.0; - RNN_Node_Interface* new_node = create_node(mu, sigma, node_type, node_innovation_count, new_depth); + RNN_Node_Interface *new_node = create_node(mu, sigma, node_type, node_innovation_count, new_depth); - nodes.insert(upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); + nodes.insert( upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); if (was_forward_edge) { attempt_edge_insert(n1, new_node, mu, sigma, edge_innovation_count); @@ -2038,19 +1940,14 @@ bool RNN_Genome::split_edge( attempt_recurrent_edge_insert(new_node, n2, mu, sigma, dist, edge_innovation_count); } - if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); - } + if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); // node_initialize(new_node); return true; } -bool RNN_Genome::connect_new_input_node( - double mu, double sigma, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool not_all_hidden -) { +bool RNN_Genome::connect_new_input_node(double mu, double sigma, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool not_all_hidden) { Log::trace("\tattempting to connect a new input node (%d) for transfer learning!\n", new_node->innovation_number); vector possible_outputs; @@ -2061,10 +1958,9 @@ bool RNN_Genome::connect_new_input_node( for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { //can connect to output or hidden nodes - if (nodes[i]->get_layer_type() == OUTPUT_LAYER || (nodes[i]->get_layer_type() == HIDDEN_LAYER && - nodes[i]->is_reachable())) { Log::info("\tpotential connection node[%d], depth: %lf, total_inputs: %d, - total_outputs: %d\n", nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_total_inputs(), - nodes[i]->get_total_outputs()); possible_outputs.push_back(nodes[i]); + if (nodes[i]->get_layer_type() == OUTPUT_LAYER || (nodes[i]->get_layer_type() == HIDDEN_LAYER && nodes[i]->is_reachable())) { + Log::info("\tpotential connection node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_total_inputs(), nodes[i]->get_total_outputs()); + possible_outputs.push_back(nodes[i]); } if (nodes[i]->enabled) { @@ -2097,20 +1993,21 @@ bool RNN_Genome::connect_new_input_node( Log::info("\tadd new input node, max_outputs: %d\n", max_outputs); */ - possible_outputs = pick_possible_nodes(INPUT_LAYER, not_all_hidden, "input"); + possible_outputs = pick_possible_nodes(INPUT_LAYER, not_all_hidden, "input") ; int32_t enabled_edges = get_enabled_edge_count(); int32_t enabled_recurrent_edges = get_enabled_recurrent_edge_count(); - double recurrent_probability = - (double) enabled_recurrent_edges / (double) (enabled_recurrent_edges + enabled_edges); - // recurrent_probability = fmax(0.2, recurrent_probability); + double recurrent_probability = (double)enabled_recurrent_edges / (double)(enabled_recurrent_edges + enabled_edges); + //recurrent_probability = fmax(0.2, recurrent_probability); Log::trace("\tadd new node for transfer recurrent probability: %lf\n", recurrent_probability); - for (int32_t i = 0; i < (int32_t) possible_outputs.size(); i++) { - // TODO: remove after running tests without recurrent edges - // recurrent_probability = 0; + + + for (int32_t i = 0; i < (int32_t)possible_outputs.size(); i++) { + //TODO: remove after running tests without recurrent edges + //recurrent_probability = 0; if (rng_0_1(generator) < recurrent_probability) { attempt_recurrent_edge_insert(new_node, possible_outputs[i], mu, sigma, dist, edge_innovation_count); @@ -2129,16 +2026,11 @@ vector RNN_Genome::pick_possible_nodes(int32_t layer_type, double avg_nodes = 0.0; vector possible_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - // can connect to node or hidden nodes - if (nodes[i]->get_layer_type() == layer_type - || (nodes[i]->get_layer_type() == HIDDEN_LAYER && nodes[i]->is_reachable())) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + //can connect to node or hidden nodes + if (nodes[i]->get_layer_type() == layer_type || (nodes[i]->get_layer_type() == HIDDEN_LAYER && nodes[i]->is_reachable())) { possible_nodes.push_back(nodes[i]); - Log::trace( - "\tpotential connection node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", - nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_total_inputs(), - nodes[i]->get_total_outputs() - ); + Log::trace("\tpotential connection node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_total_inputs(), nodes[i]->get_total_outputs()); } if (nodes[i]->enabled) { @@ -2152,7 +2044,7 @@ vector RNN_Genome::pick_possible_nodes(int32_t layer_type, double _sigma = 0.0; double temp; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->enabled) { temp = (avg_nodes - nodes[i]->total_inputs); temp = temp * temp; @@ -2165,7 +2057,7 @@ vector RNN_Genome::pick_possible_nodes(int32_t layer_type, int32_t max_nodes = fmax(1, 2.0 + normal_distribution.random(generator, avg_nodes, _sigma)); - while ((int32_t) possible_nodes.size() > max_nodes) { + while ((int32_t)possible_nodes.size() > max_nodes) { int32_t position = rng_0_1(generator) * possible_nodes.size(); possible_nodes.erase(possible_nodes.begin() + position); } @@ -2177,10 +2069,7 @@ vector RNN_Genome::pick_possible_nodes(int32_t layer_type, //------------------------------------------------ -bool RNN_Genome::connect_new_output_node( - double mu, double sigma, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool not_all_hidden -) { +bool RNN_Genome::connect_new_output_node(double mu, double sigma, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool not_all_hidden) { Log::trace("\tattempting to connect a new output node for transfer learning!\n"); vector possible_inputs; @@ -2191,10 +2080,9 @@ bool RNN_Genome::connect_new_output_node( for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { //can connect to input or hidden nodes - if (nodes[i]->get_layer_type() == INPUT_LAYER || (nodes[i]->get_layer_type() == HIDDEN_LAYER && - nodes[i]->is_reachable())) { possible_inputs.push_back(nodes[i]); Log::info("\tpotential connection node[%d], depth: - %lf, total_inputs: %d, total_outputs: %d\n", nodes[i]->get_innovation_number(), nodes[i]->get_depth(), - nodes[i]->get_total_inputs(), nodes[i]->get_total_outputs()); + if (nodes[i]->get_layer_type() == INPUT_LAYER || (nodes[i]->get_layer_type() == HIDDEN_LAYER && nodes[i]->is_reachable())) { + possible_inputs.push_back(nodes[i]); + Log::info("\tpotential connection node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", nodes[i]->get_innovation_number(), nodes[i]->get_depth(), nodes[i]->get_total_inputs(), nodes[i]->get_total_outputs()); } if (nodes[i]->enabled) { @@ -2226,20 +2114,21 @@ bool RNN_Genome::connect_new_output_node( Log::info("\tadd new output node, max_inputs: %d\n", max_inputs); */ - possible_inputs = pick_possible_nodes(INPUT_LAYER, not_all_hidden, "output"); + possible_inputs = pick_possible_nodes(INPUT_LAYER, not_all_hidden, "output") ; int32_t enabled_edges = get_enabled_edge_count(); int32_t enabled_recurrent_edges = get_enabled_recurrent_edge_count(); - double recurrent_probability = - (double) enabled_recurrent_edges / (double) (enabled_recurrent_edges + enabled_edges); - // recurrent_probability = fmax(0.2, recurrent_probability); + double recurrent_probability = (double)enabled_recurrent_edges / (double)(enabled_recurrent_edges + enabled_edges); + //recurrent_probability = fmax(0.2, recurrent_probability); Log::trace("\tadd new node for transfer recurrent probability: %lf\n", recurrent_probability); - for (int32_t i = 0; i < (int32_t) possible_inputs.size(); i++) { - // TODO: remove after running tests without recurrent edges - // recurrent_probability = 0; + + + for (int32_t i = 0; i < (int32_t)possible_inputs.size(); i++) { + //TODO: remove after running tests without recurrent edges + //recurrent_probability = 0; if (rng_0_1(generator) < recurrent_probability) { attempt_recurrent_edge_insert(possible_inputs[i], new_node, mu, sigma, dist, edge_innovation_count); @@ -2251,26 +2140,25 @@ bool RNN_Genome::connect_new_output_node( return true; } -// INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING -bool RNN_Genome::connect_node_to_hid_nodes( - double mu, double sig, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool from_input -) { + + +//INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING +bool RNN_Genome::connect_node_to_hid_nodes( double mu, double sig, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool from_input ) { + vector candidate_nodes; - int32_t enabled_count = 0; - double avg_candidates = 0.0; + int32_t enabled_count = 0; + double avg_candidates = 0.0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->get_layer_type() == HIDDEN_LAYER && nodes[i]->is_reachable()) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->get_layer_type()==HIDDEN_LAYER && nodes[i]->is_reachable()){ if (nodes[i]->enabled) { candidate_nodes.push_back(nodes[i]); enabled_count++; - if (from_input) { + if (from_input) avg_candidates += nodes[i]->total_inputs; - } else { + else avg_candidates += nodes[i]->total_outputs; - } } } } @@ -2280,22 +2168,21 @@ bool RNN_Genome::connect_node_to_hid_nodes( double sigma = 0.0; double temp; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->enabled && nodes[i]->get_layer_type() == HIDDEN_LAYER) { - if (from_input) { + + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if ( nodes[i]->enabled && nodes[i]->get_layer_type()==HIDDEN_LAYER ) { + if (from_input) temp = (avg_candidates - nodes[i]->total_inputs); - } else { + else temp = (avg_candidates - nodes[i]->total_outputs); - } temp = temp * temp; sigma += temp; } } - if (enabled_count != 1) { + if (enabled_count!=1) sigma /= (enabled_count - 1); - } else { - sigma /= 1; - } + else + sigma /= 1 ; sigma = sqrt(sigma); int32_t max_candidates = fmax(1, 2.0 + normal_distribution.random(generator, avg_candidates, sigma)); @@ -2303,18 +2190,17 @@ bool RNN_Genome::connect_node_to_hid_nodes( int32_t enabled_edges = get_enabled_edge_count(); int32_t enabled_recurrent_edges = get_enabled_recurrent_edge_count(); - double recurrent_probability = - (double) enabled_recurrent_edges / (double) (enabled_recurrent_edges + enabled_edges); + double recurrent_probability = (double)enabled_recurrent_edges / (double)(enabled_recurrent_edges + enabled_edges); - while ((int32_t) candidate_nodes.size() > max_candidates) { + while ((int32_t)candidate_nodes.size() > max_candidates) { int32_t position = rng_0_1(generator) * candidate_nodes.size(); candidate_nodes.erase(candidate_nodes.begin() + position); } - for (auto node : candidate_nodes) { + for (auto node: candidate_nodes) { if (rng_0_1(generator) < recurrent_probability) { int32_t recurrent_depth = dist(generator); - RNN_Recurrent_Edge* e; + RNN_Recurrent_Edge *e; if (from_input) { e = new RNN_Recurrent_Edge(++edge_innovation_count, recurrent_depth, new_node, node); // innovation_list.push_back(edge_innovation_count); @@ -2326,33 +2212,27 @@ bool RNN_Genome::connect_node_to_hid_nodes( } e->weight = bound(normal_distribution.random(generator, mu, sigma)); - Log::debug( - "\tadding recurrent edge between nodes %d and %d, new edge weight: %d\n", e->input_innovation_number, - e->output_innovation_number, e->weight - ); - recurrent_edges.insert( - upper_bound(recurrent_edges.begin(), recurrent_edges.end(), e, sort_RNN_Recurrent_Edges_by_depth()), e - ); + Log::debug("\tadding recurrent edge between nodes %d and %d, new edge weight: %d\n", e->input_innovation_number, e->output_innovation_number, e->weight); + recurrent_edges.insert( upper_bound(recurrent_edges.begin(), recurrent_edges.end(), e, sort_RNN_Recurrent_Edges_by_depth()), e); initial_parameters.push_back(e->weight); best_parameters.push_back(e->weight); // attempt_recurrent_edge_insert(new_node, node, mu, sigma, dist, edge_innovation_count); - } else { - RNN_Edge* e; - if (from_input) { + } + else { + RNN_Edge *e; + if (from_input){ e = new RNN_Edge(++edge_innovation_count, new_node, node); // innovation_list.push_back(edge_innovation_count); - } else { + } + else{ e = new RNN_Edge(++edge_innovation_count, node, new_node); // innovation_list.push_back(edge_innovation_count); } e->weight = bound(normal_distribution.random(generator, mu, sigma)); - Log::trace( - "\tadding edge between nodes %d and %d, new edge weight: %lf\n", e->input_innovation_number, - e->output_innovation_number, e->weight - ); - edges.insert(upper_bound(edges.begin(), edges.end(), e, sort_RNN_Edges_by_depth()), e); + Log::trace("\tadding edge between nodes %d and %d, new edge weight: %lf\n", e->input_innovation_number, e->output_innovation_number, e->weight); + edges.insert( upper_bound(edges.begin(), edges.end(), e, sort_RNN_Edges_by_depth()), e); initial_parameters.push_back(e->weight); best_parameters.push_back(e->weight); @@ -2365,10 +2245,7 @@ bool RNN_Genome::connect_node_to_hid_nodes( /* ################# ################# ################# */ -bool RNN_Genome::add_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t& edge_innovation_count, - int32_t& node_innovation_count -) { +bool RNN_Genome::add_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count) { Log::trace("\tattempting to add a node!\n"); double split_depth = rng_0_1(generator); @@ -2379,12 +2256,9 @@ bool RNN_Genome::add_node( double avg_inputs = 0.0; double avg_outputs = 0.0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->depth < split_depth && nodes[i]->is_reachable()) { - possible_inputs.push_back(nodes[i]); - } else if (nodes[i]->is_reachable()) { - possible_outputs.push_back(nodes[i]); - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->depth < split_depth && nodes[i]->is_reachable()) possible_inputs.push_back(nodes[i]); + else if (nodes[i]->is_reachable()) possible_outputs.push_back(nodes[i]); if (nodes[i]->enabled) { enabled_count++; @@ -2399,7 +2273,7 @@ bool RNN_Genome::add_node( double input_sigma = 0.0; double output_sigma = 0.0; double temp; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->enabled) { temp = (avg_inputs - nodes[i]->total_inputs); temp = temp * temp; @@ -2424,28 +2298,27 @@ bool RNN_Genome::add_node( int32_t enabled_edges = get_enabled_edge_count(); int32_t enabled_recurrent_edges = get_enabled_recurrent_edge_count(); - double recurrent_probability = - (double) enabled_recurrent_edges / (double) (enabled_recurrent_edges + enabled_edges); - // recurrent_probability = fmax(0.2, recurrent_probability); + double recurrent_probability = (double)enabled_recurrent_edges / (double)(enabled_recurrent_edges + enabled_edges); + //recurrent_probability = fmax(0.2, recurrent_probability); Log::trace("\tadd node recurrent probability: %lf\n", recurrent_probability); - while ((int32_t) possible_inputs.size() > max_inputs) { + while ((int32_t)possible_inputs.size() > max_inputs) { int32_t position = rng_0_1(generator) * possible_inputs.size(); possible_inputs.erase(possible_inputs.begin() + position); } - while ((int32_t) possible_outputs.size() > max_outputs) { + while ((int32_t)possible_outputs.size() > max_outputs) { int32_t position = rng_0_1(generator) * possible_outputs.size(); possible_outputs.erase(possible_outputs.begin() + position); } - RNN_Node_Interface* new_node = create_node(mu, sigma, node_type, node_innovation_count, split_depth); - nodes.insert(upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); + RNN_Node_Interface *new_node = create_node(mu, sigma, node_type, node_innovation_count, split_depth); + nodes.insert( upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); - for (int32_t i = 0; i < (int32_t) possible_inputs.size(); i++) { - // TODO: remove after running tests without recurrent edges - // recurrent_probability = 0; + for (int32_t i = 0; i < (int32_t)possible_inputs.size(); i++) { + //TODO: remove after running tests without recurrent edges + //recurrent_probability = 0; if (rng_0_1(generator) < recurrent_probability) { attempt_recurrent_edge_insert(possible_inputs[i], new_node, mu, sigma, dist, edge_innovation_count); @@ -2454,9 +2327,9 @@ bool RNN_Genome::add_node( } } - for (int32_t i = 0; i < (int32_t) possible_outputs.size(); i++) { - // TODO: remove after running tests without recurrent edges - // recurrent_probability = 0; + for (int32_t i = 0; i < (int32_t)possible_outputs.size(); i++) { + //TODO: remove after running tests without recurrent edges + //recurrent_probability = 0; if (rng_0_1(generator) < recurrent_probability) { attempt_recurrent_edge_insert(new_node, possible_outputs[i], mu, sigma, dist, edge_innovation_count); @@ -2465,9 +2338,7 @@ bool RNN_Genome::add_node( } } - if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); - } + if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); // node_initialize(new_node); @@ -2477,22 +2348,15 @@ bool RNN_Genome::add_node( bool RNN_Genome::enable_node() { Log::trace("\tattempting to enable a node!\n"); vector possible_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (!nodes[i]->enabled) { - possible_nodes.push_back(nodes[i]); - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (!nodes[i]->enabled) possible_nodes.push_back(nodes[i]); } - if (possible_nodes.size() == 0) { - return false; - } + if (possible_nodes.size() == 0) return false; int32_t position = rng_0_1(generator) * possible_nodes.size(); possible_nodes[position]->enabled = true; - Log::trace( - "\tenabling node %d at depth %lf\n", possible_nodes[position]->innovation_number, - possible_nodes[position]->depth - ); + Log::trace("\tenabling node %d at depth %lf\n", possible_nodes[position]->innovation_number, possible_nodes[position]->depth); return true; } @@ -2500,49 +2364,38 @@ bool RNN_Genome::enable_node() { bool RNN_Genome::disable_node() { Log::trace("\tattempting to disable a node!\n"); vector possible_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != OUTPUT_LAYER && nodes[i]->enabled) { - possible_nodes.push_back(nodes[i]); - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != OUTPUT_LAYER && nodes[i]->enabled) possible_nodes.push_back(nodes[i]); } - if (possible_nodes.size() == 0) { - return false; - } + if (possible_nodes.size() == 0) return false; int32_t position = rng_0_1(generator) * possible_nodes.size(); possible_nodes[position]->enabled = false; - Log::trace( - "\tdisabling node %d at depth %lf\n", possible_nodes[position]->innovation_number, - possible_nodes[position]->depth - ); + Log::trace("\tdisabling node %d at depth %lf\n", possible_nodes[position]->innovation_number, possible_nodes[position]->depth); return true; } -bool RNN_Genome::split_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t& edge_innovation_count, - int32_t& node_innovation_count -) { +bool RNN_Genome::split_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count) { Log::trace("\tattempting to split a node!\n"); vector possible_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != INPUT_LAYER && nodes[i]->layer_type != OUTPUT_LAYER && nodes[i]->is_reachable()) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != INPUT_LAYER && nodes[i]->layer_type != OUTPUT_LAYER && + nodes[i]->is_reachable()) { possible_nodes.push_back(nodes[i]); } } - if (possible_nodes.size() == 0) { - return false; - } + if (possible_nodes.size() == 0) return false; int32_t position = rng_0_1(generator) * possible_nodes.size(); - RNN_Node_Interface* selected_node = possible_nodes[position]; + RNN_Node_Interface *selected_node = possible_nodes[position]; Log::trace("\tselected node: %d at depth %lf\n", selected_node->innovation_number, selected_node->depth); vector input_edges; vector output_edges; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->output_innovation_number == selected_node->innovation_number) { input_edges.push_back(edges[i]); } @@ -2555,43 +2408,32 @@ bool RNN_Genome::split_node( vector recurrent_edges_1; vector recurrent_edges_2; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->output_innovation_number == selected_node->innovation_number - || recurrent_edges[i]->input_innovation_number == selected_node->innovation_number) { - if (rng_0_1(generator) < 0.5) { - recurrent_edges_1.push_back(recurrent_edges[i]); - } - if (rng_0_1(generator) < 0.5) { - recurrent_edges_2.push_back(recurrent_edges[i]); - } + || recurrent_edges[i]->input_innovation_number == selected_node->innovation_number) { + + if (rng_0_1(generator) < 0.5) recurrent_edges_1.push_back(recurrent_edges[i]); + if (rng_0_1(generator) < 0.5) recurrent_edges_2.push_back(recurrent_edges[i]); } } - Log::trace( - "\t\trecurrent_edges_1.size(): %d, recurrent_edges_2.size(): %d, input_edges.size(): %d, output_edges.size(): " - "%d\n", - recurrent_edges_1.size(), recurrent_edges_2.size(), input_edges.size(), output_edges.size() - ); + Log::trace("\t\trecurrent_edges_1.size(): %d, recurrent_edges_2.size(): %d, input_edges.size(): %d, output_edges.size(): %d\n", recurrent_edges_1.size(), recurrent_edges_2.size(), input_edges.size(), output_edges.size()); if (input_edges.size() == 0 || output_edges.size() == 0) { Log::warning("\tthe input or output edges size was 0 for the selected node, we cannot split it\n"); - // write_graphviz("error_genome.gv"); - // exit(1); + //write_graphviz("error_genome.gv"); + //exit(1); return false; } vector input_edges_1; vector input_edges_2; - for (int32_t i = 0; i < (int32_t) input_edges.size(); i++) { - if (rng_0_1(generator) < 0.5) { - input_edges_1.push_back(input_edges[i]); - } - if (rng_0_1(generator) < 0.5) { - input_edges_2.push_back(input_edges[i]); - } + for (int32_t i = 0; i < (int32_t)input_edges.size(); i++) { + if (rng_0_1(generator) < 0.5) input_edges_1.push_back(input_edges[i]); + if (rng_0_1(generator) < 0.5) input_edges_2.push_back(input_edges[i]); } - // make sure there is at least one input edge + //make sure there is at least one input edge if (input_edges_1.size() == 0 && input_edges.size() > 0) { int32_t position = rng_0_1(generator) * input_edges.size(); input_edges_1.push_back(input_edges[position]); @@ -2605,16 +2447,12 @@ bool RNN_Genome::split_node( vector output_edges_1; vector output_edges_2; - for (int32_t i = 0; i < (int32_t) output_edges.size(); i++) { - if (rng_0_1(generator) < 0.5) { - output_edges_1.push_back(output_edges[i]); - } - if (rng_0_1(generator) < 0.5) { - output_edges_2.push_back(output_edges[i]); - } + for (int32_t i = 0; i < (int32_t)output_edges.size(); i++) { + if (rng_0_1(generator) < 0.5) output_edges_1.push_back(output_edges[i]); + if (rng_0_1(generator) < 0.5) output_edges_2.push_back(output_edges[i]); } - // make sure there is at least one output edge + //make sure there is at least one output edge if (output_edges_1.size() == 0 && output_edges.size() > 0) { int32_t position = rng_0_1(generator) * output_edges.size(); output_edges_1.push_back(output_edges[position]); @@ -2625,26 +2463,26 @@ bool RNN_Genome::split_node( output_edges_2.push_back(output_edges[position]); } - // create the two new nodes + //create the two new nodes double n1_avg_input = 0.0, n1_avg_output = 0.0; double n2_avg_input = 0.0, n2_avg_output = 0.0; - for (int32_t i = 0; i < (int32_t) input_edges_1.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_edges_1.size(); i++) { n1_avg_input += input_edges_1[i]->input_node->depth; } n1_avg_input /= input_edges_1.size(); - for (int32_t i = 0; i < (int32_t) output_edges_1.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_edges_1.size(); i++) { n1_avg_output += output_edges_1[i]->output_node->depth; } n1_avg_output /= output_edges_1.size(); - for (int32_t i = 0; i < (int32_t) input_edges_2.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_edges_2.size(); i++) { n2_avg_input += input_edges_2[i]->input_node->depth; } n2_avg_input /= input_edges_2.size(); - for (int32_t i = 0; i < (int32_t) output_edges_2.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_edges_2.size(); i++) { n2_avg_output += output_edges_2[i]->output_node->depth; } n2_avg_output /= output_edges_2.size(); @@ -2652,89 +2490,71 @@ bool RNN_Genome::split_node( double new_depth_1 = (n1_avg_input + n1_avg_output) / 2.0; double new_depth_2 = (n2_avg_input + n2_avg_output) / 2.0; - RNN_Node_Interface* new_node_1 = create_node(mu, sigma, node_type, node_innovation_count, new_depth_1); - RNN_Node_Interface* new_node_2 = create_node(mu, sigma, node_type, node_innovation_count, new_depth_2); + RNN_Node_Interface *new_node_1 = create_node(mu, sigma, node_type, node_innovation_count, new_depth_1); + RNN_Node_Interface *new_node_2 = create_node(mu, sigma, node_type, node_innovation_count, new_depth_2); - // create the new edges - for (int32_t i = 0; i < (int32_t) input_edges_1.size(); i++) { + //create the new edges + for (int32_t i = 0; i < (int32_t)input_edges_1.size(); i++) { attempt_edge_insert(input_edges_1[i]->input_node, new_node_1, mu, sigma, edge_innovation_count); } - for (int32_t i = 0; i < (int32_t) output_edges_1.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_edges_1.size(); i++) { attempt_edge_insert(new_node_1, output_edges_1[i]->output_node, mu, sigma, edge_innovation_count); } - for (int32_t i = 0; i < (int32_t) input_edges_2.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_edges_2.size(); i++) { attempt_edge_insert(input_edges_2[i]->input_node, new_node_2, mu, sigma, edge_innovation_count); } - for (int32_t i = 0; i < (int32_t) output_edges_2.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_edges_2.size(); i++) { attempt_edge_insert(new_node_2, output_edges_2[i]->output_node, mu, sigma, edge_innovation_count); } Log::debug("\tattempting recurrent edge inserts for split node\n"); - for (int32_t i = 0; i < (int32_t) recurrent_edges_1.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges_1.size(); i++) { if (recurrent_edges_1[i]->input_innovation_number == selected_node->innovation_number) { - attempt_recurrent_edge_insert( - new_node_1, recurrent_edges_1[i]->output_node, mu, sigma, dist, edge_innovation_count - ); + attempt_recurrent_edge_insert(new_node_1, recurrent_edges_1[i]->output_node, mu, sigma, dist, edge_innovation_count); } else if (recurrent_edges_1[i]->output_innovation_number == selected_node->innovation_number) { - attempt_recurrent_edge_insert( - recurrent_edges_1[i]->input_node, new_node_1, mu, sigma, dist, edge_innovation_count - ); + attempt_recurrent_edge_insert(recurrent_edges_1[i]->input_node, new_node_1, mu, sigma, dist, edge_innovation_count); } else { - Log::fatal( - "\trecurrent edge list for split had an edge which was not connected to the selected node! This should " - "never happen.\n" - ); + Log::fatal("\trecurrent edge list for split had an edge which was not connected to the selected node! This should never happen.\n"); exit(1); } - // disable the old recurrent edges + //disable the old recurrent edges recurrent_edges_1[i]->enabled = false; } - for (int32_t i = 0; i < (int32_t) recurrent_edges_2.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges_2.size(); i++) { if (recurrent_edges_2[i]->input_innovation_number == selected_node->innovation_number) { - attempt_recurrent_edge_insert( - new_node_2, recurrent_edges_2[i]->output_node, mu, sigma, dist, edge_innovation_count - ); + attempt_recurrent_edge_insert(new_node_2, recurrent_edges_2[i]->output_node, mu, sigma, dist, edge_innovation_count); } else if (recurrent_edges_2[i]->output_innovation_number == selected_node->innovation_number) { - attempt_recurrent_edge_insert( - recurrent_edges_2[i]->input_node, new_node_2, mu, sigma, dist, edge_innovation_count - ); + attempt_recurrent_edge_insert(recurrent_edges_2[i]->input_node, new_node_2, mu, sigma, dist, edge_innovation_count); } else { - Log::fatal( - "\trecurrent edge list for split had an edge which was not connected to the selected node! This should " - "never happen.\n" - ); + Log::fatal("\trecurrent edge list for split had an edge which was not connected to the selected node! This should never happen.\n"); exit(1); } - // disable the old recurrent edges + //disable the old recurrent edges recurrent_edges_2[i]->enabled = false; } - nodes.insert(upper_bound(nodes.begin(), nodes.end(), new_node_1, sort_RNN_Nodes_by_depth()), new_node_1); - nodes.insert(upper_bound(nodes.begin(), nodes.end(), new_node_2, sort_RNN_Nodes_by_depth()), new_node_2); + nodes.insert( upper_bound(nodes.begin(), nodes.end(), new_node_1, sort_RNN_Nodes_by_depth()), new_node_1); + nodes.insert( upper_bound(nodes.begin(), nodes.end(), new_node_2, sort_RNN_Nodes_by_depth()), new_node_2); - // disable the selected node and it's edges - for (int32_t i = 0; i < (int32_t) input_edges.size(); i++) { + //disable the selected node and it's edges + for (int32_t i = 0; i < (int32_t)input_edges.size(); i++) { input_edges[i]->enabled = false; } - for (int32_t i = 0; i < (int32_t) output_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_edges.size(); i++) { output_edges[i]->enabled = false; } selected_node->enabled = false; - if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - generate_recurrent_edges(new_node_1, mu, sigma, dist, edge_innovation_count); - } + if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) generate_recurrent_edges(new_node_1, mu, sigma, dist, edge_innovation_count); - if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - generate_recurrent_edges(new_node_2, mu, sigma, dist, edge_innovation_count); - } + if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) generate_recurrent_edges(new_node_2, mu, sigma, dist, edge_innovation_count); // node_initialize(new_node_1); // node_initialize(new_node_2); @@ -2742,49 +2562,45 @@ bool RNN_Genome::split_node( return true; } -bool RNN_Genome::merge_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t& edge_innovation_count, - int32_t& node_innovation_count -) { +bool RNN_Genome::merge_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count) { Log::trace("\tattempting to merge a node!\n"); vector possible_nodes; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != INPUT_LAYER && nodes[i]->layer_type != OUTPUT_LAYER) { - possible_nodes.push_back(nodes[i]); - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != INPUT_LAYER && nodes[i]->layer_type != OUTPUT_LAYER) possible_nodes.push_back(nodes[i]); } - if (possible_nodes.size() < 2) { - return false; - } + if (possible_nodes.size() < 2) return false; while (possible_nodes.size() > 2) { int32_t position = rng_0_1(generator) * possible_nodes.size(); possible_nodes.erase(possible_nodes.begin() + position); } - RNN_Node_Interface* n1 = possible_nodes[0]; - RNN_Node_Interface* n2 = possible_nodes[1]; + RNN_Node_Interface *n1 = possible_nodes[0]; + RNN_Node_Interface *n2 = possible_nodes[1]; n1->enabled = false; n2->enabled = false; double new_depth = (n1->depth + n2->depth) / 2.0; - RNN_Node_Interface* new_node = create_node(mu, sigma, node_type, node_innovation_count, new_depth); - nodes.insert(upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); + RNN_Node_Interface *new_node = create_node(mu, sigma, node_type, node_innovation_count, new_depth); + nodes.insert( upper_bound(nodes.begin(), nodes.end(), new_node, sort_RNN_Nodes_by_depth()), new_node); vector merged_edges; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - RNN_Edge* e = edges[i]; - - if (e->input_innovation_number == n1->innovation_number || e->input_innovation_number == n2->innovation_number - || e->output_innovation_number == n1->innovation_number - || e->output_innovation_number == n2->innovation_number) { - // if the edge is between the two merged nodes just disasble it - if ((e->input_innovation_number == n1->innovation_number - && e->output_innovation_number == n2->innovation_number) - || (e->input_innovation_number == n2->innovation_number - && e->output_innovation_number == n1->innovation_number)) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + RNN_Edge *e = edges[i]; + + if (e->input_innovation_number == n1->innovation_number || + e->input_innovation_number == n2->innovation_number || + e->output_innovation_number == n1->innovation_number || + e->output_innovation_number == n2->innovation_number) { + + //if the edge is between the two merged nodes just disasble it + if ((e->input_innovation_number == n1->innovation_number && + e->output_innovation_number == n2->innovation_number) + || + (e->input_innovation_number == n2->innovation_number && + e->output_innovation_number == n1->innovation_number)) { e->enabled = false; } @@ -2795,21 +2611,21 @@ bool RNN_Genome::merge_node( } } - for (int32_t i = 0; i < (int32_t) merged_edges.size(); i++) { - RNN_Edge* e = merged_edges[i]; + for (int32_t i = 0; i < (int32_t)merged_edges.size(); i++) { + RNN_Edge *e = merged_edges[i]; - RNN_Node_Interface* input_node = NULL; - RNN_Node_Interface* output_node = NULL; + RNN_Node_Interface *input_node = NULL; + RNN_Node_Interface *output_node = NULL; - if (e->input_innovation_number == n1->innovation_number - || e->input_innovation_number == n2->innovation_number) { + if (e->input_innovation_number == n1->innovation_number || + e->input_innovation_number == n2->innovation_number) { input_node = new_node; } else { input_node = e->input_node; } - if (e->output_innovation_number == n1->innovation_number - || e->output_innovation_number == n2->innovation_number) { + if (e->output_innovation_number == n1->innovation_number || + e->output_innovation_number == n2->innovation_number) { output_node = new_node; } else { output_node = e->output_node; @@ -2820,9 +2636,9 @@ bool RNN_Genome::merge_node( continue; } - // swap the edges becasue the input node is deeper than the output node + //swap the edges becasue the input node is deeper than the output node if (input_node->depth > output_node->depth) { - RNN_Node_Interface* tmp = input_node; + RNN_Node_Interface *tmp = input_node; input_node = output_node; output_node = tmp; } @@ -2831,12 +2647,14 @@ bool RNN_Genome::merge_node( } vector merged_recurrent_edges; - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - RNN_Recurrent_Edge* e = recurrent_edges[i]; + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + RNN_Recurrent_Edge *e = recurrent_edges[i]; + + if (e->input_innovation_number == n1->innovation_number || + e->input_innovation_number == n2->innovation_number || + e->output_innovation_number == n1->innovation_number || + e->output_innovation_number == n2->innovation_number) { - if (e->input_innovation_number == n1->innovation_number || e->input_innovation_number == n2->innovation_number - || e->output_innovation_number == n1->innovation_number - || e->output_innovation_number == n2->innovation_number) { if (e->enabled) { e->enabled = false; merged_recurrent_edges.push_back(e); @@ -2844,22 +2662,22 @@ bool RNN_Genome::merge_node( } } - // add recurrent edges to merged node - for (int32_t i = 0; i < (int32_t) merged_recurrent_edges.size(); i++) { - RNN_Recurrent_Edge* e = merged_recurrent_edges[i]; + //add recurrent edges to merged node + for (int32_t i = 0; i < (int32_t)merged_recurrent_edges.size(); i++) { + RNN_Recurrent_Edge *e = merged_recurrent_edges[i]; - RNN_Node_Interface* input_node = NULL; - RNN_Node_Interface* output_node = NULL; + RNN_Node_Interface *input_node = NULL; + RNN_Node_Interface *output_node = NULL; - if (e->input_innovation_number == n1->innovation_number - || e->input_innovation_number == n2->innovation_number) { + if (e->input_innovation_number == n1->innovation_number || + e->input_innovation_number == n2->innovation_number) { input_node = new_node; } else { input_node = e->input_node; } - if (e->output_innovation_number == n1->innovation_number - || e->output_innovation_number == n2->innovation_number) { + if (e->output_innovation_number == n1->innovation_number || + e->output_innovation_number == n2->innovation_number) { output_node = new_node; } else { output_node = e->output_node; @@ -2868,9 +2686,7 @@ bool RNN_Genome::merge_node( attempt_recurrent_edge_insert(input_node, output_node, mu, sigma, dist, edge_innovation_count); } - if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); - } + if (node_type == JORDAN_NODE || node_type == ELMAN_NODE) generate_recurrent_edges(new_node, mu, sigma, dist, edge_innovation_count); // node_initialize(new_node); @@ -2884,7 +2700,7 @@ string RNN_Genome::get_color(double weight, bool is_recurrent) { ostringstream oss; if (!is_recurrent) { - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { if (edges[i]->weight > max) { max = edges[i]->weight; } else if (edges[i]->weight < min) { @@ -2893,7 +2709,7 @@ string RNN_Genome::get_color(double weight, bool is_recurrent) { } } else { - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { if (recurrent_edges[i]->weight > max) { max = recurrent_edges[i]->weight; } else if (recurrent_edges[i]->weight < min) { @@ -2912,12 +2728,14 @@ string RNN_Genome::get_color(double weight, bool is_recurrent) { Log::debug("weight: %lf, converted to value: %lf\n", weight, value); - oss << hex << setw(2) << setfill('0') << color.red << hex << setw(2) << setfill('0') << color.green << hex - << setw(2) << setfill('0') << color.blue; + oss << hex << setw(2) << setfill('0') << color.red + << hex << setw(2) << setfill('0') << color.green + << hex << setw(2) << setfill('0') << color.blue; return oss.str(); } + void RNN_Genome::write_graphviz(string filename) { ofstream outfile(filename); @@ -2931,16 +2749,13 @@ void RNN_Genome::write_graphviz(string filename) { int32_t input_name_index = 0; outfile << "\t{" << endl; outfile << "\t\trank = source;" << endl; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != INPUT_LAYER) { - continue; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != INPUT_LAYER) continue; input_name_index++; - if (nodes[i]->total_outputs == 0) { - continue; - } - outfile << "\t\tnode" << nodes[i]->innovation_number << " [shape=box,color=green,label=\"input " - << nodes[i]->innovation_number << "\\ndepth " << nodes[i]->depth; + if (nodes[i]->total_outputs == 0) continue; + outfile << "\t\tnode" << nodes[i]->innovation_number + << " [shape=box,color=green,label=\"input " << nodes[i]->innovation_number + << "\\ndepth " << nodes[i]->depth; if (input_parameter_names.size() != 0) { outfile << "\\n" << input_parameter_names[input_name_index - 1]; @@ -2953,25 +2768,20 @@ void RNN_Genome::write_graphviz(string filename) { int32_t output_count = 0; int32_t input_count = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type == OUTPUT_LAYER) { - output_count++; - } - if (nodes[i]->layer_type == INPUT_LAYER) { - input_count++; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type == OUTPUT_LAYER) output_count++; + if (nodes[i]->layer_type == INPUT_LAYER) input_count++; } int32_t output_name_index = 0; outfile << "\t{" << endl; outfile << "\t\trank = sink;" << endl; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != OUTPUT_LAYER) { - continue; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != OUTPUT_LAYER) continue; output_name_index++; - outfile << "\t\tnode" << nodes[i]->get_innovation_number() << " [shape=box,color=blue,label=\"output " - << nodes[i]->innovation_number << "\\ndepth " << nodes[i]->depth; + outfile << "\t\tnode" << nodes[i]->get_innovation_number() + << " [shape=box,color=blue,label=\"output " << nodes[i]->innovation_number + << "\\ndepth " << nodes[i]->depth; if (output_parameter_names.size() != 0) { outfile << "\\n" << output_parameter_names[output_name_index - 1]; @@ -2985,13 +2795,9 @@ void RNN_Genome::write_graphviz(string filename) { bool printed_first = false; if (input_count > 1) { - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != INPUT_LAYER) { - continue; - } - if (nodes[i]->total_outputs == 0) { - continue; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != INPUT_LAYER) continue; + if (nodes[i]->total_outputs == 0) continue; if (!printed_first) { printed_first = true; @@ -3007,10 +2813,8 @@ void RNN_Genome::write_graphviz(string filename) { if (output_count > 1) { printed_first = false; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != OUTPUT_LAYER) { - continue; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != OUTPUT_LAYER) continue; if (!printed_first) { printed_first = true; @@ -3023,55 +2827,41 @@ void RNN_Genome::write_graphviz(string filename) { outfile << endl; } - // draw the hidden nodes - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->layer_type != HIDDEN_LAYER) { - continue; - } - if (!nodes[i]->is_reachable()) { - continue; - } + //draw the hidden nodes + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->layer_type != HIDDEN_LAYER) continue; + if (!nodes[i]->is_reachable()) continue; string color = "black"; - string node_type = NODE_TYPES[nodes[i]->node_type]; + string node_type = NODE_TYPES[ nodes[i]->node_type ]; - outfile << "\t\tnode" << nodes[i]->get_innovation_number() << " [shape=box,color=" << color << ",label=\"" - << node_type << " node #" << nodes[i]->get_innovation_number() << "\\ndepth " << nodes[i]->depth - << "\"];" << endl; + outfile << "\t\tnode" << nodes[i]->get_innovation_number() << " [shape=box,color=" << color << ",label=\"" << node_type << " node #" << nodes[i]->get_innovation_number() << "\\ndepth " << nodes[i]->depth << "\"];" << endl; } outfile << endl; - // draw the enabled edges - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (!edges[i]->is_reachable()) { - continue; - } + //draw the enabled edges + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (!edges[i]->is_reachable()) continue; - outfile << "\tnode" << edges[i]->get_input_node()->get_innovation_number() << " -> node" - << edges[i]->get_output_node()->get_innovation_number() << " [color=\"#" - << get_color(edges[i]->weight, false) << "\"]; /* weight: " << edges[i]->weight << " */" << endl; + outfile << "\tnode" << edges[i]->get_input_node()->get_innovation_number() << " -> node" << edges[i]->get_output_node()->get_innovation_number() << " [color=\"#" << get_color(edges[i]->weight, false) << "\"]; /* weight: " << edges[i]->weight << " */" << endl; } outfile << endl; - // draw the enabled recurrent edges - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (!recurrent_edges[i]->is_reachable()) { - continue; - } + //draw the enabled recurrent edges + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (!recurrent_edges[i]->is_reachable()) continue; - outfile << "\tnode" << recurrent_edges[i]->get_input_node()->get_innovation_number() << " -> node" - << recurrent_edges[i]->get_output_node()->get_innovation_number() << " [color=\"#" - << get_color(recurrent_edges[i]->weight, true) - << "\",style=dotted]; /* weight: " << recurrent_edges[i]->weight - << ", recurrent_depth: " << recurrent_edges[i]->recurrent_depth << " */" << endl; + outfile << "\tnode" << recurrent_edges[i]->get_input_node()->get_innovation_number() << " -> node" << recurrent_edges[i]->get_output_node()->get_innovation_number() << " [color=\"#" << get_color(recurrent_edges[i]->weight, true) << "\",style=dotted]; /* weight: " << recurrent_edges[i]->weight << ", recurrent_depth: " << recurrent_edges[i]->recurrent_depth << " */" << endl; } outfile << endl; + outfile << "}" << endl; outfile.close(); + } -void read_map(istream& in, map& m) { +void read_map(istream &in, map &m) { int32_t map_size; in >> map_size; for (int32_t i = 0; i < map_size; i++) { @@ -3084,7 +2874,7 @@ void read_map(istream& in, map& m) { } } -void write_map(ostream& out, map& m) { +void write_map(ostream &out, map &m) { out << m.size(); for (auto iterator = m.begin(); iterator != m.end(); iterator++) { @@ -3093,7 +2883,7 @@ void write_map(ostream& out, map& m) { } } -void read_map(istream& in, map& m) { +void read_map(istream &in, map &m) { int32_t map_size; in >> map_size; for (int32_t i = 0; i < map_size; i++) { @@ -3106,33 +2896,36 @@ void read_map(istream& in, map& m) { } } -void write_map(ostream& out, map& m) { +void write_map(ostream &out, map &m) { out << m.size(); for (auto iterator = m.begin(); iterator != m.end(); iterator++) { - out << " " << iterator->first; - out << " " << iterator->second; + + out << " "<< iterator->first; + out << " "<< iterator->second; } } -void write_binary_string(ostream& out, string s, string name) { - int32_t n = (int32_t) s.size(); + + +void write_binary_string(ostream &out, string s, string name) { + int32_t n = (int32_t)s.size(); Log::debug("writing %d %s characters '%s'\n", n, name.c_str(), s.c_str()); - out.write((char*) &n, sizeof(int32_t)); + out.write((char*)&n, sizeof(int32_t)); if (n > 0) { - out.write((char*) &s[0], sizeof(char) * s.size()); + out.write((char*)&s[0], sizeof(char) * s.size()); } } -void read_binary_string(istream& in, string& s, string name) { +void read_binary_string(istream &in, string &s, string name) { int32_t n; - in.read((char*) &n, sizeof(int32_t)); + in.read((char*)&n, sizeof(int32_t)); Log::debug("reading %d %s characters.\n", n, name.c_str()); if (n > 0) { char* s_v = new char[n]; - in.read((char*) s_v, sizeof(char) * n); + in.read((char*)s_v, sizeof(char) * n); s.assign(s_v, s_v + n); - delete[] s_v; + delete [] s_v; } else { s.assign(""); } @@ -3140,6 +2933,7 @@ void read_binary_string(istream& in, string& s, string name) { Log::debug("read %d %s characters '%s'\n", n, name.c_str(), s.c_str()); } + RNN_Genome::RNN_Genome(string binary_filename) { ifstream bin_infile(binary_filename, ios::in | ios::binary); @@ -3152,15 +2946,15 @@ RNN_Genome::RNN_Genome(string binary_filename) { bin_infile.close(); } -RNN_Genome::RNN_Genome(char* array, int32_t length) { +RNN_Genome::RNN_Genome(char *array, int32_t length) { read_from_array(array, length); } -RNN_Genome::RNN_Genome(istream& bin_infile) { +RNN_Genome::RNN_Genome(istream &bin_infile) { read_from_stream(bin_infile); } -void RNN_Genome::read_from_array(char* array, int32_t length) { +void RNN_Genome::read_from_array(char *array, int32_t length) { string array_str; for (int32_t i = 0; i < length; i++) { array_str.push_back(array[i]); @@ -3170,88 +2964,23 @@ void RNN_Genome::read_from_array(char* array, int32_t length) { read_from_stream(iss); } -RNN_Node_Interface* RNN_Genome::read_node_from_stream(istream& bin_istream) { - int32_t innovation_number, layer_type, node_type; - double depth; - bool enabled; - - bin_istream.read((char*) &innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &layer_type, sizeof(int32_t)); - bin_istream.read((char*) &node_type, sizeof(int32_t)); - bin_istream.read((char*) &depth, sizeof(double)); - bin_istream.read((char*) &enabled, sizeof(bool)); - - string parameter_name; - read_binary_string(bin_istream, parameter_name, "parameter_name"); - Log::debug( - "NODE: %d %d %d %lf %d '%s'\n", innovation_number, layer_type, node_type, depth, enabled, parameter_name.c_str() - ); - - RNN_Node_Interface* node = nullptr; - if (node_type == LSTM_NODE) { - node = new LSTM_Node(innovation_number, layer_type, depth); - } else if (node_type == DELTA_NODE) { - node = new Delta_Node(innovation_number, layer_type, depth); - } else if (node_type == GRU_NODE) { - node = new GRU_Node(innovation_number, layer_type, depth); - } else if (node_type == ENARC_NODE) { - node = new ENARC_Node(innovation_number, layer_type, depth); - } else if (node_type == ENAS_DAG_NODE) { - node = new ENAS_DAG_Node(innovation_number, layer_type, depth); - } else if (node_type == RANDOM_DAG_NODE) { - node = new RANDOM_DAG_Node(innovation_number, layer_type, depth); - } else if (node_type == MGU_NODE) { - node = new MGU_Node(innovation_number, layer_type, depth); - } else if (node_type == UGRNN_NODE) { - node = new UGRNN_Node(innovation_number, layer_type, depth); - } else if (node_type == SIMPLE_NODE || node_type == JORDAN_NODE || node_type == ELMAN_NODE) { - if (layer_type == HIDDEN_LAYER) { - node = new RNN_Node(innovation_number, layer_type, depth, node_type); - } else { - node = new RNN_Node(innovation_number, layer_type, depth, node_type, parameter_name); - } - } else if (node_type == DNAS_NODE) { - int32_t n_nodes; - bin_istream.read((char*) &n_nodes, sizeof(int32_t)); - - int32_t counter; - bin_istream.read((char*) &counter, sizeof(int32_t)); - vector pi(n_nodes, 0.0); - bin_istream.read((char*) &pi[0], sizeof(double) * n_nodes); - - vector nodes(n_nodes, nullptr); - for (int i = 0; i < n_nodes; i++) { - nodes[i] = RNN_Genome::read_node_from_stream(bin_istream); - } - - DNASNode* dnas_node = new DNASNode(move(nodes), innovation_number, node_type, depth, counter); - dnas_node->set_pi(pi); - node = (RNN_Node_Interface*) dnas_node; - } else { - Log::fatal("Error reading node from stream, unknown node_type: %d\n", node_type); - exit(1); - } - - node->enabled = enabled; - return node; -} -void RNN_Genome::read_from_stream(istream& bin_istream) { +void RNN_Genome::read_from_stream(istream &bin_istream) { Log::debug("READING GENOME FROM STREAM\n"); - bin_istream.read((char*) &generation_id, sizeof(int32_t)); - bin_istream.read((char*) &group_id, sizeof(int32_t)); - bin_istream.read((char*) &bp_iterations, sizeof(int32_t)); + bin_istream.read((char*)&generation_id, sizeof(int32_t)); + bin_istream.read((char*)&group_id, sizeof(int32_t)); + bin_istream.read((char*)&bp_iterations, sizeof(int32_t)); - bin_istream.read((char*) &use_dropout, sizeof(bool)); - bin_istream.read((char*) &dropout_probability, sizeof(double)); + bin_istream.read((char*)&use_dropout, sizeof(bool)); + bin_istream.read((char*)&dropout_probability, sizeof(double)); WeightType weight_initialize = WeightType::NONE; WeightType weight_inheritance = WeightType::NONE; WeightType mutated_component_weight = WeightType::NONE; - bin_istream.read((char*) &weight_initialize, sizeof(int32_t)); - bin_istream.read((char*) &weight_inheritance, sizeof(int32_t)); - bin_istream.read((char*) &mutated_component_weight, sizeof(int32_t)); + bin_istream.read((char*)&weight_initialize, sizeof(int32_t)); + bin_istream.read((char*)&weight_inheritance, sizeof(int32_t)); + bin_istream.read((char*)&mutated_component_weight, sizeof(int32_t)); weight_rules = new WeightRules(); weight_rules->set_weight_initialize_method(weight_initialize); @@ -3282,35 +3011,37 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { rng_0_1 = uniform_real_distribution(0.0, 1.0); // Formerly: // istringstream rng_0_1_iss(rng_0_1_str); - // rng_0_1_iss >> rng_0_1; + //rng_0_1_iss >> rng_0_1; + string generated_by_map_str; read_binary_string(bin_istream, generated_by_map_str, "generated_by_map"); istringstream generated_by_map_iss(generated_by_map_str); read_map(generated_by_map_iss, generated_by_map); - bin_istream.read((char*) &best_validation_mse, sizeof(double)); - bin_istream.read((char*) &best_validation_mae, sizeof(double)); + bin_istream.read((char*)&best_validation_mse, sizeof(double)); + bin_istream.read((char*)&best_validation_mae, sizeof(double)); int32_t n_initial_parameters; - bin_istream.read((char*) &n_initial_parameters, sizeof(int32_t)); + bin_istream.read((char*)&n_initial_parameters, sizeof(int32_t)); Log::debug("reading %d initial parameters.\n", n_initial_parameters); double* initial_parameters_v = new double[n_initial_parameters]; - bin_istream.read((char*) initial_parameters_v, sizeof(double) * n_initial_parameters); + bin_istream.read((char*)initial_parameters_v, sizeof(double) * n_initial_parameters); initial_parameters.assign(initial_parameters_v, initial_parameters_v + n_initial_parameters); - delete[] initial_parameters_v; + delete [] initial_parameters_v; int32_t n_best_parameters; - bin_istream.read((char*) &n_best_parameters, sizeof(int32_t)); + bin_istream.read((char*)&n_best_parameters, sizeof(int32_t)); Log::debug("reading %d best parameters.\n", n_best_parameters); double* best_parameters_v = new double[n_best_parameters]; - bin_istream.read((char*) best_parameters_v, sizeof(double) * n_best_parameters); + bin_istream.read((char*)best_parameters_v, sizeof(double) * n_best_parameters); best_parameters.assign(best_parameters_v, best_parameters_v + n_best_parameters); - delete[] best_parameters_v; + delete [] best_parameters_v; + input_parameter_names.clear(); int32_t n_input_parameter_names; - bin_istream.read((char*) &n_input_parameter_names, sizeof(int32_t)); + bin_istream.read((char*)&n_input_parameter_names, sizeof(int32_t)); Log::debug("reading %d input parameter names.\n", n_input_parameter_names); for (int32_t i = 0; i < n_input_parameter_names; i++) { string input_parameter_name; @@ -3320,7 +3051,7 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { output_parameter_names.clear(); int32_t n_output_parameter_names; - bin_istream.read((char*) &n_output_parameter_names, sizeof(int32_t)); + bin_istream.read((char*)&n_output_parameter_names, sizeof(int32_t)); Log::debug("reading %d output parameter names.\n", n_output_parameter_names); for (int32_t i = 0; i < n_output_parameter_names; i++) { string output_parameter_name; @@ -3328,17 +3059,66 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { output_parameter_names.push_back(output_parameter_name); } + + int32_t n_nodes; - bin_istream.read((char*) &n_nodes, sizeof(int32_t)); + bin_istream.read((char*)&n_nodes, sizeof(int32_t)); Log::debug("reading %d nodes.\n", n_nodes); nodes.clear(); for (int32_t i = 0; i < n_nodes; i++) { - nodes.push_back(RNN_Genome::read_node_from_stream(bin_istream)); + int32_t innovation_number; + int32_t layer_type; + int32_t node_type; + double depth; + bool enabled; + + bin_istream.read((char*)&innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&layer_type, sizeof(int32_t)); + bin_istream.read((char*)&node_type, sizeof(int32_t)); + bin_istream.read((char*)&depth, sizeof(double)); + bin_istream.read((char*)&enabled, sizeof(bool)); + + string parameter_name; + read_binary_string(bin_istream, parameter_name, "parameter_name"); + + Log::debug("NODE: %d %d %d %lf %d '%s'\n", innovation_number, layer_type, node_type, depth, enabled, parameter_name.c_str()); + + RNN_Node_Interface *node; + if (node_type == LSTM_NODE) { + node = new LSTM_Node(innovation_number, layer_type, depth); + } else if (node_type == DELTA_NODE) { + node = new Delta_Node(innovation_number, layer_type, depth); + } else if (node_type == GRU_NODE) { + node = new GRU_Node(innovation_number, layer_type, depth); + } else if (node_type == ENARC_NODE) { + node = new ENARC_Node(innovation_number, layer_type, depth); + } else if (node_type == ENAS_DAG_NODE) { + node = new ENAS_DAG_Node(innovation_number, layer_type, depth); + } else if (node_type == RANDOM_DAG_NODE) { + node = new RANDOM_DAG_Node(innovation_number, layer_type, depth); + } else if (node_type == MGU_NODE) { + node = new MGU_Node(innovation_number, layer_type, depth); + } else if (node_type == UGRNN_NODE) { + node = new UGRNN_Node(innovation_number, layer_type, depth); + } else if (node_type == SIMPLE_NODE || node_type == JORDAN_NODE || node_type == ELMAN_NODE) { + if (layer_type == HIDDEN_LAYER) { + node = new RNN_Node(innovation_number, layer_type, depth, node_type); + } else { + node = new RNN_Node(innovation_number, layer_type, depth, node_type, parameter_name); + } + } else { + Log::fatal("Error reading node from stream, unknown node_type: %d\n", node_type); + exit(1); + } + + node->enabled = enabled; + nodes.push_back(node); } + int32_t n_edges; - bin_istream.read((char*) &n_edges, sizeof(int32_t)); + bin_istream.read((char*)&n_edges, sizeof(int32_t)); Log::debug("reading %d edges.\n", n_edges); edges.clear(); @@ -3348,23 +3128,22 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { int32_t output_innovation_number; bool enabled; - bin_istream.read((char*) &innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &input_innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &output_innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &enabled, sizeof(bool)); + bin_istream.read((char*)&innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&input_innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&output_innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&enabled, sizeof(bool)); - Log::debug( - "EDGE: %d %d %d %d\n", innovation_number, input_innovation_number, output_innovation_number, enabled - ); + Log::debug("EDGE: %d %d %d %d\n", innovation_number, input_innovation_number, output_innovation_number, enabled); - RNN_Edge* edge = new RNN_Edge(innovation_number, input_innovation_number, output_innovation_number, nodes); + RNN_Edge *edge = new RNN_Edge(innovation_number, input_innovation_number, output_innovation_number, nodes); // innovation_list.push_back(innovation_number); edge->enabled = enabled; edges.push_back(edge); } + int32_t n_recurrent_edges; - bin_istream.read((char*) &n_recurrent_edges, sizeof(int32_t)); + bin_istream.read((char*)&n_recurrent_edges, sizeof(int32_t)); Log::debug("reading %d recurrent_edges.\n", n_recurrent_edges); recurrent_edges.clear(); @@ -3375,20 +3154,15 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { int32_t output_innovation_number; bool enabled; - bin_istream.read((char*) &innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &recurrent_depth, sizeof(int32_t)); - bin_istream.read((char*) &input_innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &output_innovation_number, sizeof(int32_t)); - bin_istream.read((char*) &enabled, sizeof(bool)); + bin_istream.read((char*)&innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&recurrent_depth, sizeof(int32_t)); + bin_istream.read((char*)&input_innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&output_innovation_number, sizeof(int32_t)); + bin_istream.read((char*)&enabled, sizeof(bool)); - Log::debug( - "RECURRENT EDGE: %d %d %d %d %d\n", innovation_number, recurrent_depth, input_innovation_number, - output_innovation_number, enabled - ); + Log::debug("RECURRENT EDGE: %d %d %d %d %d\n", innovation_number, recurrent_depth, input_innovation_number, output_innovation_number, enabled); - RNN_Recurrent_Edge* recurrent_edge = new RNN_Recurrent_Edge( - innovation_number, recurrent_depth, input_innovation_number, output_innovation_number, nodes - ); + RNN_Recurrent_Edge *recurrent_edge = new RNN_Recurrent_Edge(innovation_number, recurrent_depth, input_innovation_number, output_innovation_number, nodes); // innovation_list.push_back(innovation_number); recurrent_edge->enabled = enabled; recurrent_edges.push_back(recurrent_edge); @@ -3419,13 +3193,13 @@ void RNN_Genome::read_from_stream(istream& bin_istream) { assign_reachability(); } -void RNN_Genome::write_to_array(char** bytes, int32_t& length) { +void RNN_Genome::write_to_array(char **bytes, int32_t &length) { ostringstream oss; write_to_stream(oss); string bytes_str = oss.str(); length = bytes_str.size(); - (*bytes) = (char*) malloc(length * sizeof(char)); + (*bytes) = (char*)malloc(length * sizeof(char)); for (int32_t i = 0; i < length; i++) { (*bytes)[i] = bytes_str[i]; } @@ -3437,21 +3211,22 @@ void RNN_Genome::write_to_file(string bin_filename) { bin_outfile.close(); } -void RNN_Genome::write_to_stream(ostream& bin_ostream) { + +void RNN_Genome::write_to_stream(ostream &bin_ostream) { Log::debug("WRITING GENOME TO STREAM\n"); - bin_ostream.write((char*) &generation_id, sizeof(int32_t)); - bin_ostream.write((char*) &group_id, sizeof(int32_t)); - bin_ostream.write((char*) &bp_iterations, sizeof(int32_t)); + bin_ostream.write((char*)&generation_id, sizeof(int32_t)); + bin_ostream.write((char*)&group_id, sizeof(int32_t)); + bin_ostream.write((char*)&bp_iterations, sizeof(int32_t)); - bin_ostream.write((char*) &use_dropout, sizeof(bool)); - bin_ostream.write((char*) &dropout_probability, sizeof(double)); + bin_ostream.write((char*)&use_dropout, sizeof(bool)); + bin_ostream.write((char*)&dropout_probability, sizeof(double)); WeightType weight_initialize = weight_rules->get_weight_initialize_method(); WeightType weight_inheritance = weight_rules->get_weight_inheritance_method(); WeightType mutated_component_weight = weight_rules->get_mutated_components_weight_method(); - bin_ostream.write((char*) &weight_initialize, sizeof(int32_t)); - bin_ostream.write((char*) &weight_inheritance, sizeof(int32_t)); - bin_ostream.write((char*) &mutated_component_weight, sizeof(int32_t)); + bin_ostream.write((char*)&weight_initialize, sizeof(int32_t)); + bin_ostream.write((char*)&weight_inheritance, sizeof(int32_t)); + bin_ostream.write((char*)&mutated_component_weight, sizeof(int32_t)); Log::debug("generation_id: %d\n", generation_id); Log::debug("bp_iterations: %d\n", bp_iterations); @@ -3480,67 +3255,58 @@ void RNN_Genome::write_to_stream(ostream& bin_ostream) { string generated_by_map_str = generated_by_map_oss.str(); write_binary_string(bin_ostream, generated_by_map_str, "generated_by_map"); - bin_ostream.write((char*) &best_validation_mse, sizeof(double)); - bin_ostream.write((char*) &best_validation_mae, sizeof(double)); + bin_ostream.write((char*)&best_validation_mse, sizeof(double)); + bin_ostream.write((char*)&best_validation_mae, sizeof(double)); - int32_t n_initial_parameters = (int32_t) initial_parameters.size(); + int32_t n_initial_parameters = (int32_t)initial_parameters.size(); Log::debug("writing %d initial parameters.\n", n_initial_parameters); - bin_ostream.write((char*) &n_initial_parameters, sizeof(int32_t)); - bin_ostream.write((char*) &initial_parameters[0], sizeof(double) * initial_parameters.size()); + bin_ostream.write((char*)&n_initial_parameters, sizeof(int32_t)); + bin_ostream.write((char*)&initial_parameters[0], sizeof(double) * initial_parameters.size()); - int32_t n_best_parameters = (int32_t) best_parameters.size(); - bin_ostream.write((char*) &n_best_parameters, sizeof(int32_t)); - if (n_best_parameters) { - bin_ostream.write((char*) &best_parameters[0], sizeof(double) * best_parameters.size()); - } + int32_t n_best_parameters = (int32_t)best_parameters.size(); + bin_ostream.write((char*)&n_best_parameters, sizeof(int32_t)); + if (n_best_parameters) + bin_ostream.write((char*)&best_parameters[0], sizeof(double) * best_parameters.size()); - int32_t n_input_parameter_names = (int32_t) input_parameter_names.size(); - bin_ostream.write((char*) &n_input_parameter_names, sizeof(int32_t)); - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { + + int32_t n_input_parameter_names = (int32_t)input_parameter_names.size(); + bin_ostream.write((char*)&n_input_parameter_names, sizeof(int32_t)); + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { write_binary_string(bin_ostream, input_parameter_names[i], "input_parameter_names[" + std::to_string(i) + "]"); } - int32_t n_output_parameter_names = (int32_t) output_parameter_names.size(); - bin_ostream.write((char*) &n_output_parameter_names, sizeof(int32_t)); - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { - write_binary_string( - bin_ostream, output_parameter_names[i], "output_parameter_names[" + std::to_string(i) + "]" - ); + int32_t n_output_parameter_names = (int32_t)output_parameter_names.size(); + bin_ostream.write((char*)&n_output_parameter_names, sizeof(int32_t)); + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { + write_binary_string(bin_ostream, output_parameter_names[i], "output_parameter_names[" + std::to_string(i) + "]"); } - int32_t n_nodes = (int32_t) nodes.size(); - bin_ostream.write((char*) &n_nodes, sizeof(int32_t)); + int32_t n_nodes = (int32_t)nodes.size(); + bin_ostream.write((char*)&n_nodes, sizeof(int32_t)); Log::debug("writing %d nodes.\n", n_nodes); - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - Log::debug( - "NODE: %d %d %d %lf '%s'\n", nodes[i]->innovation_number, nodes[i]->layer_type, nodes[i]->node_type, - nodes[i]->depth, nodes[i]->parameter_name.c_str() - ); + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + Log::debug("NODE: %d %d %d %lf '%s'\n", nodes[i]->innovation_number, nodes[i]->layer_type, nodes[i]->node_type, nodes[i]->depth, nodes[i]->parameter_name.c_str()); nodes[i]->write_to_stream(bin_ostream); } - int32_t n_edges = (int32_t) edges.size(); - bin_ostream.write((char*) &n_edges, sizeof(int32_t)); + + int32_t n_edges = (int32_t)edges.size(); + bin_ostream.write((char*)&n_edges, sizeof(int32_t)); Log::debug("writing %d edges.\n", n_edges); - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - Log::debug( - "EDGE: %d %d %d\n", edges[i]->innovation_number, edges[i]->input_innovation_number, - edges[i]->output_innovation_number - ); + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + Log::debug("EDGE: %d %d %d\n", edges[i]->innovation_number, edges[i]->input_innovation_number, edges[i]->output_innovation_number); edges[i]->write_to_stream(bin_ostream); } - int32_t n_recurrent_edges = (int32_t) recurrent_edges.size(); - bin_ostream.write((char*) &n_recurrent_edges, sizeof(int32_t)); + + int32_t n_recurrent_edges = (int32_t)recurrent_edges.size(); + bin_ostream.write((char*)&n_recurrent_edges, sizeof(int32_t)); Log::debug("writing %d recurrent edges.\n", n_recurrent_edges); - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - Log::debug( - "RECURRENT EDGE: %d %d %d %d\n", recurrent_edges[i]->innovation_number, recurrent_edges[i]->recurrent_depth, - recurrent_edges[i]->input_innovation_number, recurrent_edges[i]->output_innovation_number - ); + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + Log::debug("RECURRENT EDGE: %d %d %d %d\n", recurrent_edges[i]->innovation_number, recurrent_edges[i]->recurrent_depth, recurrent_edges[i]->input_innovation_number, recurrent_edges[i]->output_innovation_number); recurrent_edges[i]->write_to_stream(bin_ostream); } @@ -3568,37 +3334,31 @@ void RNN_Genome::write_to_stream(ostream& bin_ostream) { write_binary_string(bin_ostream, normalize_std_devs_str, "normalize_std_devs"); } -void RNN_Genome::update_innovation_counts(int32_t& node_innovation_count, int32_t& edge_innovation_count) { +void RNN_Genome::update_innovation_counts(int32_t &node_innovation_count, int32_t &edge_innovation_count) { int32_t max_node_innovation_count = -1; - for (int32_t i = 0; i < (int32_t) this->nodes.size(); i += 1) { - RNN_Node_Interface* node = this->nodes[i]; + for (int32_t i = 0; i < (int32_t)this->nodes.size(); i += 1) { + RNN_Node_Interface *node = this->nodes[i]; max_node_innovation_count = std::max(max_node_innovation_count, node->innovation_number); } int32_t max_edge_innovation_count = -1; - for (int32_t i = 0; i < (int32_t) this->edges.size(); i += 1) { - RNN_Edge* edge = this->edges[i]; + for (int32_t i = 0; i < (int32_t)this->edges.size(); i += 1) { + RNN_Edge *edge = this->edges[i]; max_edge_innovation_count = std::max(max_edge_innovation_count, edge->innovation_number); } - for (int32_t i = 0; i < (int32_t) this->recurrent_edges.size(); i += 1) { - RNN_Recurrent_Edge* redge = this->recurrent_edges[i]; + for (int32_t i = 0; i < (int32_t)this->recurrent_edges.size(); i += 1) { + RNN_Recurrent_Edge *redge = this->recurrent_edges[i]; max_edge_innovation_count = std::max(max_edge_innovation_count, redge->innovation_number); } if (max_node_innovation_count == -1) { // Fatal log message - Log::fatal( - "Seed genome had max node innovation number of -1 - this should never happen (unless the genome is empty " - ":)" - ); + Log::fatal("Seed genome had max node innovation number of -1 - this should never happen (unless the genome is empty :)"); } if (max_edge_innovation_count == -1) { // Fatal log message - Log::fatal( - "Seed genome had max node innovation number of -1 - this should never happen (and the genome isn't empty " - "since max_node_innovation_count > -1)" - ); + Log::fatal("Seed genome had max node innovation number of -1 - this should never happen (and the genome isn't empty since max_node_innovation_count > -1)"); } // One more than the highest we've seen should be good enough. @@ -3608,7 +3368,7 @@ void RNN_Genome::update_innovation_counts(int32_t& node_innovation_count, int32_ // return sorted innovation list vector RNN_Genome::get_innovation_list() { vector innovations; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { + for (int32_t i = 0; i < (int32_t)edges.size(); i++){ int32_t innovation = edges[i]->get_innovation_number(); auto it = std::upper_bound(innovations.begin(), innovations.end(), innovation); innovations.insert(it, innovation); @@ -3616,6 +3376,7 @@ vector RNN_Genome::get_innovation_list() { return innovations; } + string RNN_Genome::get_structural_hash() const { return structural_hash; } @@ -3623,10 +3384,8 @@ string RNN_Genome::get_structural_hash() const { int32_t RNN_Genome::get_max_node_innovation_count() { int32_t max = 0; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { - if (nodes[i]->innovation_number > max) { - max = nodes[i]->innovation_number; - } + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { + if (nodes[i]->innovation_number > max) max = nodes[i]->innovation_number; } return max; @@ -3635,32 +3394,26 @@ int32_t RNN_Genome::get_max_node_innovation_count() { int32_t RNN_Genome::get_max_edge_innovation_count() { int32_t max = 0; - for (int32_t i = 0; i < (int32_t) edges.size(); i++) { - if (edges[i]->innovation_number > max) { - max = edges[i]->innovation_number; - } + for (int32_t i = 0; i < (int32_t)edges.size(); i++) { + if (edges[i]->innovation_number > max) max = edges[i]->innovation_number; } - for (int32_t i = 0; i < (int32_t) recurrent_edges.size(); i++) { - if (recurrent_edges[i]->innovation_number > max) { - max = recurrent_edges[i]->innovation_number; - } + for (int32_t i = 0; i < (int32_t)recurrent_edges.size(); i++) { + if (recurrent_edges[i]->innovation_number > max) max = recurrent_edges[i]->innovation_number; } return max; } -void RNN_Genome::transfer_to( - const vector& new_input_parameter_names, const vector& new_output_parameter_names, - string transfer_learning_version, bool epigenetic_weights, int32_t min_recurrent_depth, int32_t max_recurrent_depth -) { + +void RNN_Genome::transfer_to(const vector &new_input_parameter_names, const vector &new_output_parameter_names, string transfer_learning_version, bool epigenetic_weights, int32_t min_recurrent_depth, int32_t max_recurrent_depth) { Log::info("DOING TRANSFER OF GENOME!\n"); double mu, sigma; set_weights(best_parameters); get_mu_sigma(best_parameters, mu, sigma); Log::info("before transfer, mu: %lf, sigma: %lf\n", mu, sigma); - // make sure we don't duplicate new node/edge innovation numbers + //make sure we don't duplicate new node/edge innovation numbers int32_t node_innovation_count = get_max_node_innovation_count() + 1; int32_t edge_innovation_count = get_max_edge_innovation_count() + 1; @@ -3668,13 +3421,13 @@ void RNN_Genome::transfer_to( vector input_nodes; vector output_nodes; - // work backwards so we don't skip removing anything - for (int32_t i = (int32_t) nodes.size() - 1; i >= 0; i--) { + //work backwards so we don't skip removing anything + for (int32_t i = (int32_t)nodes.size() - 1; i >= 0; i--) { Log::info("checking node: %d\n", i); - // add all the input and output nodes to the input_nodes and output_nodes vectors, - // and remove them from the node vector for the time being - RNN_Node_Interface* node = nodes[i]; + //add all the input and output nodes to the input_nodes and output_nodes vectors, + //and remove them from the node vector for the time being + RNN_Node_Interface *node = nodes[i]; if (node->layer_type == INPUT_LAYER) { input_nodes.push_back(node); Log::info("erasing node: %d of %d\n", i, nodes.size()); @@ -3690,28 +3443,29 @@ void RNN_Genome::transfer_to( } Log::info("original input parameter names:\n"); - for (int32_t i = 0; i < (int32_t) input_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)input_parameter_names.size(); i++) { Log::info_no_header(" %s", input_parameter_names[i].c_str()); } Log::info_no_header("\n"); Log::info("new input parameter names:\n"); - for (int32_t i = 0; i < (int32_t) new_input_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_input_parameter_names.size(); i++) { Log::info_no_header(" %s", new_input_parameter_names[i].c_str()); } Log::info_no_header("\n"); - // first figure out which input nodes we're keeping, and add new input - // nodes as needed + + //first figure out which input nodes we're keeping, and add new input + //nodes as needed vector new_input_nodes; - vector new_inputs; // this will track if new input node was new (true) or added from the genome (false) + vector new_inputs; //this will track if new input node was new (true) or added from the genome (false) - for (int32_t i = 0; i < (int32_t) new_input_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_input_parameter_names.size(); i++) { int32_t parameter_position = -1; - // iterate through the input parameter names to find the input - // node related to this new input paramter name, if it is - // not found we need to make a new node for it - for (int32_t j = 0; j < (int32_t) input_nodes.size(); j++) { + //iterate through the input parameter names to find the input + //node related to this new input paramter name, if it is + //not found we need to make a new node for it + for (int32_t j = 0; j < (int32_t)input_nodes.size(); j++) { if (input_nodes[j]->parameter_name.compare(new_input_parameter_names[i]) == 0) { parameter_position = j; break; @@ -3720,44 +3474,35 @@ void RNN_Genome::transfer_to( if (parameter_position >= 0) { Log::info("keeping input node for parameter '%s'\n", new_input_parameter_names[i].c_str()); - // this input node already existed in the genome + //this input node already existed in the genome new_input_nodes.push_back(input_nodes[parameter_position]); new_inputs.push_back(false); - // erase this parameter from the input nodes and input parameter names so we don't - // re-use it + //erase this parameter from the input nodes and input parameter names so we don't + //re-use it input_nodes.erase(input_nodes.begin() + parameter_position); } else { Log::info("creating new input node for parameter '%s'\n", new_input_parameter_names[i].c_str()); - // create a new input node for this parameter + //create a new input node for this parameter new_inputs.push_back(true); - RNN_Node* node = new RNN_Node( - ++node_innovation_count, INPUT_LAYER, 0.0 /*input nodes should be depth 0*/, SIMPLE_NODE, - new_input_parameter_names[i] - ); + RNN_Node *node = new RNN_Node(++node_innovation_count, INPUT_LAYER, 0.0 /*input nodes should be depth 0*/, SIMPLE_NODE, new_input_parameter_names[i]); new_input_nodes.push_back(node); } } Log::info("new input node parameter names (should be the same as new input parameter names):\n"); - for (int32_t i = 0; i < (int32_t) new_input_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_input_nodes.size(); i++) { Log::info("\t%s (new: %s)\n", new_input_nodes[i]->parameter_name.c_str(), new_inputs[i] ? "true" : "false"); } - // delete all the input nodes that were not kept in the transfer process - for (int32_t i = (int32_t) input_nodes.size() - 1; i >= 0; i--) { - Log::info( - "deleting outgoing edges for input node[%d] with parameter name: '%s' and innovation number %d\n", i, - input_nodes[i]->parameter_name.c_str(), input_nodes[i]->innovation_number - ); + //delete all the input nodes that were not kept in the transfer process + for (int32_t i = (int32_t)input_nodes.size() - 1; i >= 0; i--) { + Log::info("deleting outgoing edges for input node[%d] with parameter name: '%s' and innovation number %d\n", i, input_nodes[i]->parameter_name.c_str(), input_nodes[i]->innovation_number); - // first delete any outgoing edges from the input node to be deleted - for (int32_t j = (int32_t) edges.size() - 1; j >= 0; j--) { + //first delete any outgoing edges from the input node to be deleted + for (int32_t j = (int32_t)edges.size() - 1; j >= 0; j--) { if (edges[j]->input_innovation_number == input_nodes[i]->innovation_number) { - Log::info( - "deleting edges[%d] with innovation number: %d and input_innovation_number %d\n", j, - edges[j]->innovation_number, edges[j]->input_innovation_number - ); + Log::info("deleting edges[%d] with innovation number: %d and input_innovation_number %d\n", j, edges[j]->innovation_number, edges[j]->input_innovation_number); delete edges[j]; edges.erase(edges.begin() + j); } @@ -3765,16 +3510,11 @@ void RNN_Genome::transfer_to( Log::info("deleting recurrent edges\n"); - // do the same for any outgoing recurrent edges - for (int32_t j = (int32_t) recurrent_edges.size() - 1; j >= 0; j--) { - // recurrent edges shouldn't go into input nodes, but check to see if it has a connection either way to the - // node being deleted - if (recurrent_edges[j]->input_innovation_number == input_nodes[i]->innovation_number - || recurrent_edges[j]->output_innovation_number == input_nodes[i]->innovation_number) { - Log::info( - "deleting recurrent_edges[%d] with innovation number: %d and input_innovation_number %d\n", j, - recurrent_edges[j]->innovation_number, recurrent_edges[j]->input_innovation_number - ); + //do the same for any outgoing recurrent edges + for (int32_t j = (int32_t)recurrent_edges.size() - 1; j >= 0; j--) { + //recurrent edges shouldn't go into input nodes, but check to see if it has a connection either way to the node being deleted + if (recurrent_edges[j]->input_innovation_number == input_nodes[i]->innovation_number || recurrent_edges[j]->output_innovation_number == input_nodes[i]->innovation_number) { + Log::info("deleting recurrent_edges[%d] with innovation number: %d and input_innovation_number %d\n", j, recurrent_edges[j]->innovation_number, recurrent_edges[j]->input_innovation_number); delete recurrent_edges[j]; recurrent_edges.erase(recurrent_edges.begin() + j); } @@ -3784,34 +3524,34 @@ void RNN_Genome::transfer_to( input_nodes.erase(input_nodes.begin() + i); } + Log::info("original output parameter names:\n"); - for (int32_t i = 0; i < (int32_t) output_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)output_parameter_names.size(); i++) { Log::info_no_header(" %s", output_parameter_names[i].c_str()); } Log::info_no_header("\n"); Log::info("new output parameter names:\n"); - for (int32_t i = 0; i < (int32_t) new_output_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_output_parameter_names.size(); i++) { Log::info_no_header(" %s", new_output_parameter_names[i].c_str()); } Log::info_no_header("\n"); - // first figure out which output nodes we're keeping, and add new output - // nodes as needed + + //first figure out which output nodes we're keeping, and add new output + //nodes as needed vector new_output_nodes; - vector new_outputs; // this will track if new output node was new (true) or added from the genome (false) + vector new_outputs; //this will track if new output node was new (true) or added from the genome (false) - for (int32_t i = 0; i < (int32_t) new_output_parameter_names.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_output_parameter_names.size(); i++) { Log::info("finding output node with parameter name: '%s\n", new_output_parameter_names[i].c_str()); int32_t parameter_position = -1; - // iterate through the output parameter names to find the output - // node related to this new output paramter name, if it is - // not found we need to make a new node for it - for (int32_t j = 0; j < (int32_t) output_nodes.size(); j++) { - Log::info( - "\tchecking output_nodes[%d]->parameter_name: '%s'\n", j, output_nodes[j]->parameter_name.c_str() - ); + //iterate through the output parameter names to find the output + //node related to this new output paramter name, if it is + //not found we need to make a new node for it + for (int32_t j = 0; j < (int32_t)output_nodes.size(); j++) { + Log::info("\tchecking output_nodes[%d]->parameter_name: '%s'\n", j, output_nodes[j]->parameter_name.c_str()); if (output_nodes[j]->parameter_name.compare(new_output_parameter_names[i]) == 0) { Log::info("\t\tMATCH!\n"); parameter_position = j; @@ -3821,44 +3561,35 @@ void RNN_Genome::transfer_to( if (parameter_position >= 0) { Log::info("keeping output node for parameter '%s'\n", new_output_parameter_names[i].c_str()); - // this output node already existed in the genome + //this output node already existed in the genome new_output_nodes.push_back(output_nodes[parameter_position]); new_outputs.push_back(false); - // erase this parameter from the output nodes and output parameter names so we don't - // re-use it + //erase this parameter from the output nodes and output parameter names so we don't + //re-use it output_nodes.erase(output_nodes.begin() + parameter_position); } else { Log::info("creating new output node for parameter '%s'\n", new_output_parameter_names[i].c_str()); - // create a new output node for this parameter + //create a new output node for this parameter new_outputs.push_back(true); - RNN_Node* node = new RNN_Node( - ++node_innovation_count, OUTPUT_LAYER, 1.0 /*output nodes should be depth 1*/, SIMPLE_NODE, - new_output_parameter_names[i] - ); + RNN_Node *node = new RNN_Node(++node_innovation_count, OUTPUT_LAYER, 1.0 /*output nodes should be depth 1*/, SIMPLE_NODE, new_output_parameter_names[i]); new_output_nodes.push_back(node); } } Log::info("new output node parameter names (should be the same as new output parameter names):\n"); - for (int32_t i = 0; i < (int32_t) new_output_nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)new_output_nodes.size(); i++) { Log::info("\t%s (new: %s)\n", new_output_nodes[i]->parameter_name.c_str(), new_outputs[i] ? "true" : "false"); } - // delete all the output nodes that were not kept in the transfer process - for (int32_t i = (int32_t) output_nodes.size() - 1; i >= 0; i--) { - Log::info( - "deleting incoming edges for output node[%d] with parameter name: '%s' and innovation number %d\n", i, - output_nodes[i]->parameter_name.c_str(), output_nodes[i]->innovation_number - ); + //delete all the output nodes that were not kept in the transfer process + for (int32_t i = (int32_t)output_nodes.size() - 1; i >= 0; i--) { + Log::info("deleting incoming edges for output node[%d] with parameter name: '%s' and innovation number %d\n", i, output_nodes[i]->parameter_name.c_str(), output_nodes[i]->innovation_number); - // first delete any incoming edges to the output node to be deleted - for (int32_t j = (int32_t) edges.size() - 1; j >= 0; j--) { + //first delete any incoming edges to the output node to be deleted + for (int32_t j = (int32_t)edges.size() - 1; j >= 0; j--) { if (edges[j]->output_innovation_number == output_nodes[i]->innovation_number) { - Log::info( - "deleting edges[%d] with innovation number: %d and output_innovation_number %d\n", j, - edges[j]->innovation_number, edges[j]->output_innovation_number - ); + Log::info("deleting edges[%d] with innovation number: %d and output_innovation_number %d\n", j, edges[j]->innovation_number, edges[j]->output_innovation_number); delete edges[j]; edges.erase(edges.begin() + j); } @@ -3866,16 +3597,11 @@ void RNN_Genome::transfer_to( Log::info("doing recurrent edges\n"); - // do the same for any outgoing recurrent edges - for (int32_t j = (int32_t) recurrent_edges.size() - 1; j >= 0; j--) { - // output nodes can be the input to a recurrent edge so we need to delete those recurrent edges too if the - // output node is being deleted - if (recurrent_edges[j]->output_innovation_number == output_nodes[i]->innovation_number - || recurrent_edges[j]->input_innovation_number == output_nodes[i]->innovation_number) { - Log::info( - "deleting recurrent_edges[%d] with innovation number: %d and output_innovation_number %d\n", j, - recurrent_edges[j]->innovation_number, recurrent_edges[j]->output_innovation_number - ); + //do the same for any outgoing recurrent edges + for (int32_t j = (int32_t)recurrent_edges.size() - 1; j >= 0; j--) { + //output nodes can be the input to a recurrent edge so we need to delete those recurrent edges too if the output node is being deleted + if (recurrent_edges[j]->output_innovation_number == output_nodes[i]->innovation_number || recurrent_edges[j]->input_innovation_number == output_nodes[i]->innovation_number) { + Log::info("deleting recurrent_edges[%d] with innovation number: %d and output_innovation_number %d\n", j, recurrent_edges[j]->innovation_number, recurrent_edges[j]->output_innovation_number); delete recurrent_edges[j]; recurrent_edges.erase(recurrent_edges.begin() + j); } @@ -3895,13 +3621,12 @@ void RNN_Genome::transfer_to( Log::info("starting transfer learning versions\n"); - if (transfer_learning_version.compare("v1") != 0 && transfer_learning_version.compare("v2") != 0 - && transfer_learning_version.compare("v3") != 0 && transfer_learning_version.compare("v1+v2") != 0 - && transfer_learning_version.compare("v1+v3") != 0) { - Log::fatal( - "ERROR: unknown transfer learning version specified, '%s', options are:\n", - transfer_learning_version.c_str() - ); + if (transfer_learning_version.compare("v1") != 0 && + transfer_learning_version.compare("v2") != 0 && + transfer_learning_version.compare("v3") != 0 && + transfer_learning_version.compare("v1+v2") != 0 && + transfer_learning_version.compare("v1+v3") != 0) { + Log::fatal("ERROR: unknown transfer learning version specified, '%s', options are:\n", transfer_learning_version.c_str()); Log::fatal("v1: connects all new inputs to all outputs and all new outputs to all inputs\n"); Log::fatal("v2: randomly connects all new inputs and outputs to hidden nodes\n"); Log::fatal("v3: connects all new inputs and outputs to hidden nodes\n"); @@ -3916,28 +3641,20 @@ void RNN_Genome::transfer_to( if (transfer_learning_version.compare("v1") == 0 || transfer_learning_version.compare("v1+v2") == 0) { Log::info("doing transfer v1\n"); - for (int32_t i = 0; i < (int32_t) new_input_nodes.size(); i++) { - if (!new_inputs[i]) { - continue; - } - Log::info( - "adding connections for new input node[%d] '%s'\n", i, new_input_nodes[i]->parameter_name.c_str() - ); + for (int32_t i = 0; i < (int32_t)new_input_nodes.size(); i++) { + if (!new_inputs[i]) continue; + Log::info("adding connections for new input node[%d] '%s'\n", i, new_input_nodes[i]->parameter_name.c_str()); - for (int32_t j = 0; j < (int32_t) new_output_nodes.size(); j++) { + for (int32_t j = 0; j < (int32_t)new_output_nodes.size(); j++) { attempt_edge_insert(new_input_nodes[i], new_output_nodes[j], mu, sigma, edge_innovation_count); } } - for (int32_t i = 0; i < (int32_t) new_output_nodes.size(); i++) { - if (!new_outputs[i]) { - continue; - } - Log::info( - "adding connections for new output node[%d] '%s'\n", i, new_output_nodes[i]->parameter_name.c_str() - ); + for (int32_t i = 0; i < (int32_t)new_output_nodes.size(); i++) { + if (!new_outputs[i]) continue; + Log::info("adding connections for new output node[%d] '%s'\n", i, new_output_nodes[i]->parameter_name.c_str()); - for (int32_t j = 0; j < (int32_t) new_input_nodes.size(); j++) { + for (int32_t j = 0; j < (int32_t)new_input_nodes.size(); j++) { attempt_edge_insert(new_input_nodes[j], new_output_nodes[i], mu, sigma, edge_innovation_count); } } @@ -3979,76 +3696,65 @@ void RNN_Genome::transfer_to( } Log::info("adding new_input_nodes and new_output_nodes to nodes\n"); - // add the new input and new output nodes back into the genome's node vector + //add the new input and new output nodes back into the genome's node vector nodes.insert(nodes.begin(), new_input_nodes.begin(), new_input_nodes.end()); nodes.insert(nodes.end(), new_output_nodes.begin(), new_output_nodes.end()); Log::info("assigning reachability\n"); - // need to recalculate the reachability of each node + //need to recalculate the reachability of each node assign_reachability(); sort_edges_by_depth(); sort_recurrent_edges_by_depth(); - // need to make sure that each input and each output has at least one connection + //need to make sure that each input and each output has at least one connection for (auto node : nodes) { - Log::info( - "node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", node->get_innovation_number(), - node->get_depth(), node->get_total_inputs(), node->get_total_outputs() - ); + Log::info("node[%d], depth: %lf, total_inputs: %d, total_outputs: %d\n", node->get_innovation_number(), node->get_depth(), node->get_total_inputs(), node->get_total_outputs()); if (node->get_layer_type() == INPUT_LAYER) { if (node->get_total_outputs() == 0) { Log::info("input node[%d] had no outputs, connecting it!\n", node->get_innovation_number()); - // if an input has no outgoing edges randomly connect it + //if an input has no outgoing edges randomly connect it connect_new_input_node(mu, sigma, node, rec_depth_dist, edge_innovation_count, true); } } else if (node->get_layer_type() == OUTPUT_LAYER) { if (node->get_total_inputs() == 0) { Log::info("output node[%d] had no inputs, connecting it!\n", node->get_innovation_number()); - // if an output has no incoming edges randomly connect it + //if an output has no incoming edges randomly connect it connect_new_output_node(mu, sigma, node, rec_depth_dist, edge_innovation_count, true); } } } Log::info("assigning reachability again\n"); - // update the reachabaility again + //update the reachabaility again assign_reachability(); Log::info("new_parameters.size() before get weights: %d\n", initial_parameters.size()); - // update the new and best parameter lengths because this will have added edges + //update the new and best parameter lengths because this will have added edges vector updated_genome_parameters; get_weights(updated_genome_parameters); if (!epigenetic_weights) { Log::info("resetting genome parameters to randomly betwen -0.5 and 0.5\n"); - for (int32_t i = 0; i < (int32_t) updated_genome_parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)updated_genome_parameters.size(); i++) { updated_genome_parameters[i] = rng_0_1(generator) - 0.5; } } else { Log::info("not resetting weights\n"); } - set_initial_parameters(updated_genome_parameters); - set_best_parameters(updated_genome_parameters); + set_initial_parameters( updated_genome_parameters ); + set_best_parameters( updated_genome_parameters ); best_validation_mse = EXAMM_MAX_DOUBLE; best_validation_mae = EXAMM_MAX_DOUBLE; get_mu_sigma(best_parameters, mu, sigma); Log::info("after transfer, mu: %lf, sigma: %lf\n", mu, sigma); - // make sure we don't duplicate new node/edge innovation numbers + //make sure we don't duplicate new node/edge innovation numbers Log::info("new_parameters.size() after get weights: %d\n", updated_genome_parameters.size()); Log::info("FINISHING PREPARING INITIAL GENOME\n"); } - -void RNN_Genome::set_stochastic(bool stochastic) { - for (RNN_Node_Interface* n : nodes) { - if (DNASNode* node = dynamic_cast(n); node != nullptr) { - node->set_stochastic(stochastic); - } - } -} diff --git a/rnn/rnn_genome.hxx b/rnn/rnn_genome.hxx index acba093c..314aaf17 100644 --- a/rnn/rnn_genome.hxx +++ b/rnn/rnn_genome.hxx @@ -2,371 +2,307 @@ #define RNN_BPTT_HXX #include -using std::ifstream; using std::istream; -using std::ofstream; +using std::ifstream; using std::ostream; +using std::ofstream; #include using std::map; #include using std::minstd_rand0; -using std::mt19937; -using std::uniform_int_distribution; using std::uniform_real_distribution; +using std::uniform_int_distribution; +using std::mt19937; #include using std::vector; -#include "common/random.hxx" #include "rnn.hxx" -#include "rnn_edge.hxx" #include "rnn_node_interface.hxx" +#include "rnn_edge.hxx" #include "rnn_recurrent_edge.hxx" -#include "time_series/time_series.hxx" + +#include "common/random.hxx" #include "weights/weight_rules.hxx" #include "weights/weight_update.hxx" +#include "time_series/time_series.hxx" // #include "word_series/word_series.hxx" -// mysql can't handle the max float value for some reason +//mysql can't handle the max float value for some reason #define EXAMM_MAX_DOUBLE 10000000 string parse_fitness(double fitness); class RNN_Genome { - private: - int32_t generation_id; - int32_t group_id; + private: + int32_t generation_id; + int32_t group_id; + + int32_t bp_iterations; + + //SHO SY + double learning_rate; + double initial_learning_rate; + double best_learning_rate; + uniform_real_distribution rng_lr; + uniform_real_distribution rng_ilr; + + bool use_dropout; + double dropout_probability; + + string structural_hash; + + string log_filename; + + WeightRules *weight_rules; + + map generated_by_map; + + vector initial_parameters; + + + double best_validation_mse; + double best_validation_mae; + vector best_parameters; + + minstd_rand0 generator; + + uniform_real_distribution rng; + uniform_real_distribution rng_0_1; + uniform_real_distribution rng_1_1; + uniform_int_distribution rng_int; + NormalDistribution normal_distribution; + + vector nodes; + vector edges; + vector recurrent_edges; + + vector input_parameter_names; + vector output_parameter_names; + + string normalize_type; + map normalize_mins; + map normalize_maxs; + map normalize_avgs; + map normalize_std_devs; + + // vector innovation_list; + + public: + void sort_nodes_by_depth(); + void sort_edges_by_depth(); + void sort_recurrent_edges_by_depth(); + + RNN_Genome(vector &_nodes, vector &_edges, vector &_recurrent_edges, WeightRules *weight_rules); + RNN_Genome(vector &_nodes, vector &_edges, vector &_recurrent_edges, int16_t seed, WeightRules *weight_rules); + + RNN_Genome* copy(); + + ~RNN_Genome(); + + static string print_statistics_header(); + string print_statistics(); + + void set_parameter_names(const vector &_input_parameter_names, const vector &_output_parameter_names); + + string generated_by_string(); + + string get_edge_count_str(bool recurrent); + string get_node_count_str(int32_t node_type); + + const map *get_generated_by_map(); + + double get_avg_recurrent_depth() const; + + int32_t get_enabled_edge_count(); + int32_t get_enabled_recurrent_edge_count(); + int32_t get_enabled_node_count(int32_t node_type); + int32_t get_node_count(int32_t node_type); + int32_t get_enabled_node_count(); + int32_t get_node_count(); + + double get_fitness() const; + double get_best_validation_softmax() const; + double get_best_validation_mse() const; + double get_best_validation_mae() const; + //SHO SY TODO:const removed + double get_learning_rate(); + double get_initial_learning_rate(); + double get_best_learning_rate(); + void set_learning_rate(double _learning_rate); + + + void set_normalize_bounds(string _normalize_type, const map &_normalize_mins, const map &_normalize_maxs, const map &_normalize_avgs, const map &_normalize_std_devs); + + string get_normalize_type() const; + map get_normalize_mins() const; + map get_normalize_maxs() const; + map get_normalize_avgs() const; + map get_normalize_std_devs() const; + + vector get_input_parameter_names() const; + vector get_output_parameter_names() const; + + int32_t get_group_id() const; + void set_group_id(int32_t _group_id); + + + void set_bp_iterations(int32_t _bp_iterations); + int32_t get_bp_iterations(); + + void disable_dropout(); + void enable_dropout(double _dropout_probability); + void set_log_filename(string _log_filename); + + void get_weights(vector ¶meters); + void set_weights(const vector ¶meters); + + int32_t get_number_weights(); + int32_t get_number_inputs(); + int32_t get_number_outputs(); + + double get_avg_edge_weight(); + void initialize_randomly(); + void initialize_xavier(RNN_Node_Interface* n); + void initialize_kaiming(RNN_Node_Interface* n); + void initialize_node_randomly(RNN_Node_Interface* n); + double get_xavier_weight(RNN_Node_Interface* output_node); + double get_kaiming_weight(RNN_Node_Interface* output_node); + double get_random_weight(); + + + void get_input_edges(int32_t node_innovation, vector< RNN_Edge*> &input_edges, vector< RNN_Recurrent_Edge*> &input_recurrent_edges); + int32_t get_fan_in(int32_t node_innovation); + int32_t get_fan_out(int32_t node_innovation); + + int32_t get_generation_id() const; + void set_generation_id(int32_t generation_id); + + void clear_generated_by(); + void update_generation_map(map &generation_map); + void set_generated_by(string type); + int32_t get_generated_by(string type); + + + RNN* get_rnn(); + vector get_best_parameters() const; + + void set_best_parameters( vector parameters); //INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING + void set_initial_parameters( vector parameters); //INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING + + void get_analytic_gradient(vector &rnns, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, double &mse, vector &analytic_gradient, bool training); + + void backpropagate(const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, const vector< vector< vector > > &validation_inputs, const vector< vector< vector > > &validation_outputs, WeightUpdate *weight_update_method); + + void backpropagate_stochastic(const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, const vector< vector< vector > > &validation_inputs, const vector< vector< vector > > &validation_outputs, WeightUpdate *weight_update_method); + + double get_softmax(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs); + double get_mse(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs); + double get_mae(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs); + - int32_t bp_iterations; + vector< vector > get_predictions(const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs); + void write_predictions(string output_directory, const vector &input_filenames, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, TimeSeriesSets *time_series_sets); + // void write_predictions(string output_directory, const vector &input_filenames, const vector ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, Corpus * word_series_sets); - bool use_dropout; - double dropout_probability; + void get_mu_sigma(const vector &p, double &mu, double &sigma); - string structural_hash; + bool sanity_check(); + void assign_reachability(); + bool outputs_unreachable(); - string log_filename; + RNN_Node_Interface* create_node(double mu, double sigma, int32_t node_type, int32_t &node_innovation_count, double depth); - WeightRules* weight_rules; + bool attempt_edge_insert(RNN_Node_Interface *n1, RNN_Node_Interface *n2, double mu, double sigma, int32_t &edge_innovation_count); + bool attempt_recurrent_edge_insert(RNN_Node_Interface *n1, RNN_Node_Interface *n2, double mu, double sigma, uniform_int_distribution dist, int32_t &edge_innovation_count); - map generated_by_map; + //after adding an Elman or Jordan node, generate the circular RNN edge for Elman and the + //edges from output to this node for Jordan. + void generate_recurrent_edges(RNN_Node_Interface *node, double mu, double sigma, uniform_int_distribution dist, int32_t &edge_innovation_count); - vector initial_parameters; + bool add_edge(double mu, double sigma, int32_t &edge_innovation_count); + bool add_recurrent_edge(double mu, double sigma, uniform_int_distribution rec_depth_dist, int32_t &edge_innovation_count); + bool disable_edge(); + bool enable_edge(); + bool split_edge(double mu, double sigma, int32_t node_type, uniform_int_distribution rec_depth_dist, int32_t &edge_innovation_count, int32_t &node_innovation_count); - double best_validation_mse; - double best_validation_mae; - vector best_parameters; - minstd_rand0 generator; + bool add_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count); - uniform_real_distribution rng; - uniform_real_distribution rng_0_1; - uniform_real_distribution rng_1_1; - uniform_int_distribution rng_int; - NormalDistribution normal_distribution; + bool enable_node(); + bool disable_node(); + bool split_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count); + bool merge_node(double mu, double sigma, int32_t node_type, uniform_int_distribution dist, int32_t &edge_innovation_count, int32_t &node_innovation_count); - vector nodes; - vector edges; - vector recurrent_edges; + /** + * Determines if the genome contains a node with the given innovation number + * + * @param the innovation number to fine + * + * @return true if the genome has a node with the provided innovation number, false otherwise. + */ + bool has_node_with_innovation(int32_t innovation_number) const; - vector input_parameter_names; - vector output_parameter_names; + bool equals(RNN_Genome *other); - string normalize_type; - map normalize_mins; - map normalize_maxs; - map normalize_avgs; - map normalize_std_devs; + string get_color(double weight, bool is_recurrent); + void write_graphviz(string filename); - public: - void sort_nodes_by_depth(); - void sort_edges_by_depth(); - void sort_recurrent_edges_by_depth(); + RNN_Genome(string binary_filename); + RNN_Genome(char* array, int32_t length); + RNN_Genome(istream &bin_infile); - RNN_Genome( - vector& _nodes, vector& _edges, vector& _recurrent_edges, - WeightRules* weight_rules - ); - RNN_Genome( - vector& _nodes, vector& _edges, vector& _recurrent_edges, - int16_t seed, WeightRules* weight_rules - ); + void read_from_array(char *array, int32_t length); + void read_from_stream(istream &bin_istream); - RNN_Genome* copy(); + void write_to_array(char **array, int32_t &length); + void write_to_file(string bin_filename); + void write_to_stream(ostream &bin_stream); - ~RNN_Genome(); + bool connect_new_input_node( double mu, double sig, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool not_all_hidden ); + bool connect_new_output_node( double mu, double sig, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool not_all_hidden ); + bool connect_node_to_hid_nodes( double mu, double sig, RNN_Node_Interface *new_node, uniform_int_distribution dist, int32_t &edge_innovation_count, bool from_input ); + vector pick_possible_nodes(int32_t layer_type, bool not_all_hidden, string node_type); - static string print_statistics_header(); - string print_statistics(); + void update_innovation_counts(int32_t &node_innovation_count, int32_t &edge_innovation_count); - static RNN_Node_Interface* read_node_from_stream(istream& bin_istream); + vector get_innovation_list(); + /** + * \return the structural hash (calculated when assign_reachaability is called) + */ + string get_structural_hash() const; - void set_parameter_names( - const vector& _input_parameter_names, const vector& _output_parameter_names - ); + /** + * \return the max innovation number of any node in the genome. + */ + int32_t get_max_node_innovation_count(); - string generated_by_string(); + /** + * \return the max innovation number of any edge or recurrent edge in the genome. + */ + int32_t get_max_edge_innovation_count(); - string get_edge_count_str(bool recurrent); - string get_node_count_str(int32_t node_type); + ofstream* create_log_file(); + void update_log_file(ofstream *output_log, int32_t iteration, long milliseconds, double training_mse, double validation_mse, double avg_norm); - const map* get_generated_by_map(); + void transfer_to(const vector &new_input_parameter_names, const vector &new_output_parameter_names, string transfer_learning_version, bool epigenetic_weights, int32_t min_recurrent_depth, int32_t max_recurrent_depth); - double get_avg_recurrent_depth() const; - - int32_t get_enabled_edge_count(); - int32_t get_enabled_recurrent_edge_count(); - int32_t get_enabled_node_count(int32_t node_type); - int32_t get_node_count(int32_t node_type); - int32_t get_enabled_node_count(); - int32_t get_node_count(); - - double get_fitness() const; - double get_best_validation_softmax() const; - double get_best_validation_mse() const; - double get_best_validation_mae() const; - - void set_normalize_bounds( - string _normalize_type, const map& _normalize_mins, const map& _normalize_maxs, - const map& _normalize_avgs, const map& _normalize_std_devs - ); - - string get_normalize_type() const; - map get_normalize_mins() const; - map get_normalize_maxs() const; - map get_normalize_avgs() const; - map get_normalize_std_devs() const; - - vector get_input_parameter_names() const; - vector get_output_parameter_names() const; - - int32_t get_group_id() const; - void set_group_id(int32_t _group_id); - - void set_bp_iterations(int32_t _bp_iterations); - int32_t get_bp_iterations(); - - // Turns on / off stochastic operations. If it is off, any stochastic values will be "frozen" in place. - void set_stochastic(bool stochastic); - void disable_dropout(); - void enable_dropout(double _dropout_probability); - void set_log_filename(string _log_filename); - - void get_weights(vector& parameters); - void set_weights(const vector& parameters); - - int32_t get_number_weights(); - int32_t get_number_inputs(); - int32_t get_number_outputs(); - - double get_avg_edge_weight(); - void initialize_randomly(); - void initialize_xavier(RNN_Node_Interface* n); - void initialize_kaiming(RNN_Node_Interface* n); - void initialize_node_randomly(RNN_Node_Interface* n); - double get_xavier_weight(RNN_Node_Interface* output_node); - double get_kaiming_weight(RNN_Node_Interface* output_node); - double get_random_weight(); - - void get_input_edges( - int32_t node_innovation, vector& input_edges, vector& input_recurrent_edges - ); - int32_t get_fan_in(int32_t node_innovation); - int32_t get_fan_out(int32_t node_innovation); - - int32_t get_generation_id() const; - void set_generation_id(int32_t generation_id); - - void clear_generated_by(); - void update_generation_map(map& generation_map); - void set_generated_by(string type); - int32_t get_generated_by(string type); - - RNN* get_rnn(); - vector get_best_parameters() const; - - void set_best_parameters(vector parameters); // INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING - void set_initial_parameters(vector parameters); // INFO: ADDED BY ABDELRAHMAN TO USE FOR TRANSFER LEARNING - - void get_analytic_gradient( - vector& rnns, const vector& parameters, const vector > >& inputs, - const vector > >& outputs, double& mse, vector& analytic_gradient, bool training - ); - - void backpropagate( - const vector > >& inputs, const vector > >& outputs, - const vector > >& validation_inputs, - const vector > >& validation_outputs, WeightUpdate* weight_update_method - ); - - void backpropagate_stochastic( - const vector > >& inputs, const vector > >& outputs, - const vector > >& validation_inputs, - const vector > >& validation_outputs, WeightUpdate* weight_update_method - ); - - double get_softmax( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs - ); - double get_mse( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs - ); - double get_mae( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs - ); - - vector > get_predictions( - const vector& parameters, const vector > >& inputs, - const vector > >& outputs - ); - void write_predictions( - string output_directory, const vector& input_filenames, const vector& parameters, - const vector > >& inputs, const vector > >& outputs, - TimeSeriesSets* time_series_sets - ); - // void write_predictions(string output_directory, const vector &input_filenames, const vector - // ¶meters, const vector< vector< vector > > &inputs, const vector< vector< vector > > &outputs, - // Corpus * word_series_sets); - - void get_mu_sigma(const vector& p, double& mu, double& sigma); - - bool sanity_check(); - void assign_reachability(); - bool outputs_unreachable(); - - RNN_Node_Interface* create_node( - double mu, double sigma, int32_t node_type, int32_t& node_innovation_count, double depth - ); - - bool attempt_edge_insert( - RNN_Node_Interface* n1, RNN_Node_Interface* n2, double mu, double sigma, int32_t& edge_innovation_count - ); - bool attempt_recurrent_edge_insert( - RNN_Node_Interface* n1, RNN_Node_Interface* n2, double mu, double sigma, uniform_int_distribution dist, - int32_t& edge_innovation_count - ); - - // after adding an Elman or Jordan node, generate the circular RNN edge for Elman and the - // edges from output to this node for Jordan. - void generate_recurrent_edges( - RNN_Node_Interface* node, double mu, double sigma, uniform_int_distribution dist, - int32_t& edge_innovation_count - ); - - bool add_edge(double mu, double sigma, int32_t& edge_innovation_count); - bool add_recurrent_edge( - double mu, double sigma, uniform_int_distribution rec_depth_dist, int32_t& edge_innovation_count - ); - bool disable_edge(); - bool enable_edge(); - bool split_edge( - double mu, double sigma, int32_t node_type, uniform_int_distribution rec_depth_dist, - int32_t& edge_innovation_count, int32_t& node_innovation_count - ); - - bool add_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, - int32_t& edge_innovation_count, int32_t& node_innovation_count - ); - - bool enable_node(); - bool disable_node(); - bool split_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, - int32_t& edge_innovation_count, int32_t& node_innovation_count - ); - bool merge_node( - double mu, double sigma, int32_t node_type, uniform_int_distribution dist, - int32_t& edge_innovation_count, int32_t& node_innovation_count - ); - - /** - * Determines if the genome contains a node with the given innovation number - * - * @param the innovation number to fine - * - * @return true if the genome has a node with the provided innovation number, false otherwise. - */ - bool has_node_with_innovation(int32_t innovation_number) const; - - bool equals(RNN_Genome* other); - - string get_color(double weight, bool is_recurrent); - void write_graphviz(string filename); - - RNN_Genome(string binary_filename); - RNN_Genome(char* array, int32_t length); - RNN_Genome(istream& bin_infile); - - void read_from_array(char* array, int32_t length); - void read_from_stream(istream& bin_istream); - - void write_to_array(char** array, int32_t& length); - void write_to_file(string bin_filename); - void write_to_stream(ostream& bin_stream); - - bool connect_new_input_node( - double mu, double sig, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool not_all_hidden - ); - bool connect_new_output_node( - double mu, double sig, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool not_all_hidden - ); - bool connect_node_to_hid_nodes( - double mu, double sig, RNN_Node_Interface* new_node, uniform_int_distribution dist, - int32_t& edge_innovation_count, bool from_input - ); - vector pick_possible_nodes(int32_t layer_type, bool not_all_hidden, string node_type); - - void update_innovation_counts(int32_t& node_innovation_count, int32_t& edge_innovation_count); - - vector get_innovation_list(); - /** - * \return the structural hash (calculated when assign_reachaability is called) - */ - string get_structural_hash() const; - - /** - * \return the max innovation number of any node in the genome. - */ - int32_t get_max_node_innovation_count(); - - /** - * \return the max innovation number of any edge or recurrent edge in the genome. - */ - int32_t get_max_edge_innovation_count(); - - ofstream* create_log_file(); - void update_log_file( - ofstream* output_log, int32_t iteration, long milliseconds, double training_mse, double validation_mse, - double avg_norm - ); - - void transfer_to( - const vector& new_input_parameter_names, const vector& new_output_parameter_names, - string transfer_learning_version, bool epigenetic_weights, int32_t min_recurrent_depth, - int32_t max_recurrent_depth - ); - - friend class EXAMM; - friend class IslandSpeciationStrategy; - friend class NeatSpeciationStrategy; - friend class RecDepthFrequencyTable; - friend class GenomeProperty; + friend class EXAMM; + friend class IslandSpeciationStrategy; + friend class NeatSpeciationStrategy; + friend class RecDepthFrequencyTable; + friend class GenomeProperty; }; struct sort_genomes_by_fitness { - bool operator()(RNN_Genome* g1, RNN_Genome* g2) { + bool operator()(RNN_Genome *g1, RNN_Genome *g2) { return g1->get_fitness() < g2->get_fitness(); } }; -void write_binary_string(ostream& out, string s, string name); -void read_binary_string(istream& in, string& s, string name); +void write_binary_string(ostream &out, string s, string name); +void read_binary_string(istream &in, string &s, string name); #endif diff --git a/rnn/rnn_node.cxx b/rnn/rnn_node.cxx index 075c11ed..6a5f0374 100644 --- a/rnn/rnn_node.cxx +++ b/rnn/rnn_node.cxx @@ -1,44 +1,47 @@ #include + #include using std::vector; -#include "common/log.hxx" #include "rnn_node.hxx" -RNN_Node::RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type) - : RNN_Node_Interface(_innovation_number, _layer_type, _depth), bias(0) { - // node type will be simple, jordan or elman +#include "common/log.hxx" + + +RNN_Node::RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type) : RNN_Node_Interface(_innovation_number, _layer_type, _depth), bias(0) { + + //node type will be simple, jordan or elman node_type = _node_type; Log::trace("created node: %d, layer type: %d, node type: %d\n", innovation_number, layer_type, node_type); } -RNN_Node::RNN_Node( - int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type, string _parameter_name -) - : RNN_Node_Interface(_innovation_number, _layer_type, _depth, _parameter_name), bias(0) { - // node type will be simple, jordan or elman + +RNN_Node::RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type, string _parameter_name) : RNN_Node_Interface(_innovation_number, _layer_type, _depth, _parameter_name), bias(0) { + + //node type will be simple, jordan or elman node_type = _node_type; Log::trace("created node: %d, layer type: %d, node type: %d\n", innovation_number, layer_type, node_type); } + RNN_Node::~RNN_Node() { } -void RNN_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void RNN_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { bias = bound(normal_distribution.random(generator, mu, sigma)); } -void RNN_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void RNN_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + bias = range * (rng_1_1(generator)); } -void RNN_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void RNN_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) { + bias = range * normal_distribution.random(generator, 0, 1); } -void RNN_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void RNN_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { bias = rng(generator); } @@ -47,29 +50,23 @@ void RNN_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on RNN_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on RNN_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - Log::debug("node %d - input value[%d]: %lf\n", innovation_number, time, input_values[time]); + //Log::trace("node %d - input value[%d]: %lf\n", innovation_number, time, input_values[time]); output_values[time] = tanh(input_values[time] + bias); ld_output[time] = tanh_derivative(output_values[time]); - // output_values[time] = sigmoid(input_values[time] + bias); - // ld_output[time] = sigmoid_derivative(output_values[time]); + //output_values[time] = sigmoid(input_values[time] + bias); + //ld_output[time] = sigmoid_derivative(output_values[time]); #ifdef NAN_CHECKS if (isnan(output_values[time]) || isinf(output_values[time])) { - Log::fatal( - "ERROR: output_value[%d] becaome %lf on RNN node: %d\n", time, output_values[time], innovation_number - ); + Log::fatal("ERROR: output_value[%d] becaome %lf on RNN node: %d\n", time, output_values[time], innovation_number); Log::fatal("\tinput_value[%dd]: %lf\n", time, input_values[time]); Log::Fatal("\tnode bias: %lf", bias); exit(1); @@ -78,25 +75,21 @@ void RNN_Node::input_fired(int32_t time, double incoming_output) { } void RNN_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on RNN_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on RNN_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } d_input[time] *= ld_output[time]; + d_bias += d_input[time]; } void RNN_Node::error_fired(int32_t time, double error) { outputs_fired[time]++; - // Log::trace("error fired at time: %d on node %d, d_input: %lf, ld_output %lf, error_values: %lf, output_values: - // %lf\n", time, innovation_number, d_input[time], ld_output[time], error_values[time], output_values[time]); + //Log::trace("error fired at time: %d on node %d, d_input: %lf, ld_output %lf, error_values: %lf, output_values: %lf\n", time, innovation_number, d_input[time], ld_output[time], error_values[time], output_values[time]); d_input[time] += error_values[time] * error; @@ -126,7 +119,7 @@ void RNN_Node::reset(int32_t _series_length) { d_bias = 0.0; } -void RNN_Node::get_gradients(vector& gradients) { +void RNN_Node::get_gradients(vector &gradients) { gradients.assign(1, d_bias); } @@ -134,43 +127,43 @@ int32_t RNN_Node::get_number_weights() const { return 1; } -void RNN_Node::get_weights(vector& parameters) const { +void RNN_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); - // no weights to set in a basic RNN node, only a bias + //no weights to set in a basic RNN node, only a bias int32_t offset = 0; get_weights(offset, parameters); } -void RNN_Node::set_weights(const vector& parameters) { - // no weights to set in a basic RNN node, only a bias +void RNN_Node::set_weights(const vector ¶meters) { + //no weights to set in a basic RNN node, only a bias int32_t offset = 0; set_weights(offset, parameters); } -void RNN_Node::get_weights(int32_t& offset, vector& parameters) const { - // no weights to set in a basic RNN node, only a bias +void RNN_Node::get_weights(int32_t &offset, vector ¶meters) const { + //no weights to set in a basic RNN node, only a bias parameters[offset++] = bias; } -void RNN_Node::set_weights(int32_t& offset, const vector& parameters) { - // no weights to set in a basic RNN node, only a bias +void RNN_Node::set_weights(int32_t &offset, const vector ¶meters) { + //no weights to set in a basic RNN node, only a bias bias = bound(parameters[offset++]); } RNN_Node_Interface* RNN_Node::copy() const { - RNN_Node* n = NULL; + RNN_Node *n = NULL; if (layer_type == HIDDEN_LAYER) { n = new RNN_Node(innovation_number, layer_type, depth, node_type); } else { n = new RNN_Node(innovation_number, layer_type, depth, node_type, parameter_name); } - // copy RNN_Node values + //copy RNN_Node values n->bias = bias; n->d_bias = d_bias; n->ld_output = ld_output; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -188,6 +181,6 @@ RNN_Node_Interface* RNN_Node::copy() const { return n; } -void RNN_Node::write_to_stream(ostream& out) { +void RNN_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } diff --git a/rnn/rnn_node.hxx b/rnn/rnn_node.hxx index 15aa9d5c..dc5b572d 100644 --- a/rnn/rnn_node.hxx +++ b/rnn/rnn_node.hxx @@ -7,50 +7,47 @@ using std::vector; #include "rnn_node_interface.hxx" class RNN_Node : public RNN_Node_Interface { - private: - double bias; - double d_bias; + private: + double bias; + double d_bias; - vector ld_output; + vector ld_output; - public: - // constructor for hidden nodes - RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type); + public: - // constructor for input and output nodes - RNN_Node( - int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type, string _parameter_name - ); - ~RNN_Node(); + //constructor for hidden nodes + RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + //constructor for input and output nodes + RNN_Node(int32_t _innovation_number, int32_t _layer_type, double _depth, int32_t _node_type, string _parameter_name); + ~RNN_Node(); - void input_fired(int32_t time, double incoming_output); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); + + void input_fired(int32_t time, double incoming_output); - void try_update_deltas(int32_t time); - void output_fired(int32_t time, double delta); - void error_fired(int32_t time, double error); + void try_update_deltas(int32_t time); + void output_fired(int32_t time, double delta); + void error_fired(int32_t time, double error); - int32_t get_number_weights() const; - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + int32_t get_number_weights() const ; + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void reset(int32_t _series_length); + void reset(int32_t _series_length); - void get_gradients(vector& gradients); + void get_gradients(vector &gradients); - RNN_Node_Interface* copy() const; + RNN_Node_Interface* copy() const; - void write_to_stream(ostream& out); + void write_to_stream(ostream &out); - friend class RNN_Edge; + friend class RNN_Edge; }; #endif diff --git a/rnn/rnn_node_interface.cxx b/rnn/rnn_node_interface.cxx index 2ad8d065..c5fc3c1d 100644 --- a/rnn/rnn_node_interface.cxx +++ b/rnn/rnn_node_interface.cxx @@ -1,27 +1,26 @@ #include + #include using std::ostream; #include using std::string; -#include +#include using std::max; -#include "common/log.hxx" -#include "rnn/rnn_genome.hxx" #include "rnn_node_interface.hxx" +#include "rnn/rnn_genome.hxx" + +#include "common/log.hxx" + extern const int32_t NUMBER_NODE_TYPES = 9; -extern const string NODE_TYPES[] = {"simple", "jordan", "elman", "UGRNN", "MGU", - "GRU", "delta", "LSTM", "ENARC", "ENAS_DAG"}; +extern const string NODE_TYPES[] = { "simple" , "jordan", "elman", "UGRNN", "MGU", "GRU", "delta", "LSTM" , "ENARC" , "ENAS_DAG" }; double bound(double value) { - if (value < -10.0) { - value = -10.0; - } else if (value > 10.0) { - value = 10.0; - } + if (value < -10.0) value = -10.0; + else if (value > 10.0) value = 10.0; return value; } @@ -44,12 +43,12 @@ double identity_derivative() { double tanh_derivative(double input) { return 1 - (input * input); - // return 1 - (tanh(input) * tanh(input)); + //return 1 - (tanh(input) * tanh(input)); } double swish(double value) { double exp_value = exp(-value); - return value * (1.0 / (1.0 + exp_value)); + return value*(1.0 / (1.0 + exp_value)); } double swish_derivative(double value, double input) { @@ -59,64 +58,57 @@ double swish_derivative(double value, double input) { double leakyReLU(double value) { double alpha = 0.01; - return fmax(alpha * value, value); + return fmax(alpha*value, value); } double leakyReLU_derivative(double input) { double alpha = 0.01; - if (input > 0) { - return 1; - } + if (input > 0) return 1; return alpha; } -RNN_Node_Interface::RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth) - : innovation_number(_innovation_number), layer_type(_layer_type), depth(_depth) { + + + +RNN_Node_Interface::RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth) : innovation_number(_innovation_number), layer_type(_layer_type), depth(_depth) { total_inputs = 0; enabled = true; forward_reachable = false; backward_reachable = false; - // outputs don't have an official output node but - // deltas are passed in via the output_fired method + //outputs don't have an official output node but + //deltas are passed in via the output_fired method if (layer_type != HIDDEN_LAYER) { - Log::fatal( - "ERROR: Attempted to create a new RNN_Node that was an input or output node without using the constructor " - "which specifies it's parameter name" - ); + Log::fatal("ERROR: Attempted to create a new RNN_Node that was an input or output node without using the constructor which specifies it's parameter name"); exit(1); } } -RNN_Node_Interface::RNN_Node_Interface( - int32_t _innovation_number, int32_t _layer_type, double _depth, string _parameter_name -) - : innovation_number(_innovation_number), layer_type(_layer_type), depth(_depth), parameter_name(_parameter_name) { +RNN_Node_Interface::RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth, string _parameter_name) : innovation_number(_innovation_number), layer_type(_layer_type), depth(_depth), parameter_name(_parameter_name) { total_inputs = 0; enabled = true; forward_reachable = false; backward_reachable = false; - + if (layer_type == HIDDEN_LAYER) { - Log::fatal( - "ERROR: assigned a parameter name '%s' to a hidden node! This should never happen.", parameter_name.c_str() - ); + Log::fatal("ERROR: assigned a parameter name '%s' to a hidden node! This should never happen.", parameter_name.c_str()); exit(1); } - // outputs don't have an official output node but - // deltas are passed in via the output_fired method + //outputs don't have an official output node but + //deltas are passed in via the output_fired method if (layer_type == OUTPUT_LAYER) { total_outputs = 1; } else { - // this is an input node + //this is an input node total_outputs = 0; total_inputs = 1; } } + RNN_Node_Interface::~RNN_Node_Interface() { } @@ -140,6 +132,8 @@ int32_t RNN_Node_Interface::get_total_outputs() const { return total_outputs; } + + double RNN_Node_Interface::get_depth() const { return depth; } @@ -152,19 +146,18 @@ bool RNN_Node_Interface::is_enabled() const { return enabled; } -bool RNN_Node_Interface::equals(RNN_Node_Interface* other) const { - if (innovation_number == other->innovation_number && enabled == other->enabled) { - return true; - } + +bool RNN_Node_Interface::equals(RNN_Node_Interface *other) const { + if (innovation_number == other->innovation_number && enabled == other->enabled) return true; return false; } -void RNN_Node_Interface::write_to_stream(ostream& out) { - out.write((char*) &innovation_number, sizeof(int32_t)); - out.write((char*) &layer_type, sizeof(int32_t)); - out.write((char*) &node_type, sizeof(int32_t)); - out.write((char*) &depth, sizeof(double)); - out.write((char*) &enabled, sizeof(bool)); +void RNN_Node_Interface::write_to_stream(ostream &out) { + out.write((char*)&innovation_number, sizeof(int32_t)); + out.write((char*)&layer_type, sizeof(int32_t)); + out.write((char*)&node_type, sizeof(int32_t)); + out.write((char*)&depth, sizeof(double)); + out.write((char*)&enabled, sizeof(bool)); write_binary_string(out, parameter_name, "parameter_name"); } diff --git a/rnn/rnn_node_interface.hxx b/rnn/rnn_node_interface.hxx index 26dc0f3c..50691bf3 100644 --- a/rnn/rnn_node_interface.hxx +++ b/rnn/rnn_node_interface.hxx @@ -2,6 +2,7 @@ #define EXAMM_RNN_NODE_INTERFACE_HXX #include + #include using std::ostream; @@ -19,25 +20,26 @@ using std::vector; class RNN; -#define INPUT_LAYER 0 +#define INPUT_LAYER 0 #define HIDDEN_LAYER 1 #define OUTPUT_LAYER 2 extern const int32_t NUMBER_NODE_TYPES; extern const string NODE_TYPES[]; -#define SIMPLE_NODE 0 -#define JORDAN_NODE 1 -#define ELMAN_NODE 2 -#define UGRNN_NODE 3 -#define MGU_NODE 4 -#define GRU_NODE 5 -#define DELTA_NODE 6 -#define LSTM_NODE 7 -#define ENARC_NODE 8 -#define ENAS_DAG_NODE 9 +#define SIMPLE_NODE 0 +#define JORDAN_NODE 1 +#define ELMAN_NODE 2 +#define UGRNN_NODE 3 +#define MGU_NODE 4 +#define GRU_NODE 5 +#define DELTA_NODE 6 +#define LSTM_NODE 7 +#define ENARC_NODE 8 +#define ENAS_DAG_NODE 9 #define RANDOM_DAG_NODE 10 -#define DNAS_NODE 11 + + double sigmoid(double value); double sigmoid_derivative(double value); @@ -49,105 +51,98 @@ double leakyReLU_derivative(double input); double identity(double value); double identity_derivative(); + double bound(double value); class RNN_Node_Interface { - public: - int32_t innovation_number; - int32_t layer_type; - int32_t node_type; - - double depth; - - // this is only used for input and output nodes to track - // which parameter they are assigned to - string parameter_name; - - bool enabled; - bool backward_reachable; - bool forward_reachable; - - int32_t series_length; - - vector input_values; - vector output_values; - vector error_values; - vector d_input; - - vector inputs_fired; - vector outputs_fired; - int32_t total_inputs; - int32_t total_outputs; - - public: - // this constructor is for hidden nodes - RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth); - - // this constructor is for input and output nodes (as they have an associated parameter name - RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth, string _parameter_name); - virtual ~RNN_Node_Interface(); - - virtual void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ) = 0; - virtual void initialize_xavier( - minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range - ) = 0; - virtual void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) = 0; - virtual void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) = 0; - - virtual void input_fired(int32_t time, double incoming_output) = 0; - virtual void output_fired(int32_t time, double delta) = 0; - virtual void error_fired(int32_t time, double error) = 0; - - virtual int32_t get_number_weights() const = 0; - - virtual void get_weights(vector& parameters) const = 0; - virtual void set_weights(const vector& parameters) = 0; - virtual void get_weights(int32_t& offset, vector& parameters) const = 0; - virtual void set_weights(int32_t& offset, const vector& parameters) = 0; - virtual void reset(int32_t _series_length) = 0; - - virtual void get_gradients(vector& gradients) = 0; - - virtual RNN_Node_Interface* copy() const = 0; - - void write_to_stream(ostream& out); - - int32_t get_node_type() const; - int32_t get_layer_type() const; - int32_t get_innovation_number() const; - int32_t get_total_inputs() const; - int32_t get_total_outputs() const; - - double get_depth() const; - bool equals(RNN_Node_Interface* other) const; - - bool is_reachable() const; - bool is_enabled() const; - - friend class RNN_Edge; - friend class RNN_Recurrent_Edge; - friend class DNASNode; - friend class RNN; - friend class RNN_Genome; - - friend void get_mse( - RNN* genome, const vector >& expected, double& mse, vector >& deltas - ); - friend void get_mae( - RNN* genome, const vector >& expected, double& mae, vector >& deltas - ); + protected: + int32_t innovation_number; + int32_t layer_type; + int32_t node_type; + + double depth; + + //this is only used for input and output nodes to track + //which parameter they are assigned to + string parameter_name; + + bool enabled; + bool backward_reachable; + bool forward_reachable; + + int32_t series_length; + + vector input_values; + vector output_values; + vector error_values; + vector d_input; + + vector inputs_fired; + vector outputs_fired; + int32_t total_inputs; + int32_t total_outputs; + public: + //this constructor is for hidden nodes + RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth); + + //this constructor is for input and output nodes (as they have an associated parameter name + RNN_Node_Interface(int32_t _innovation_number, int32_t _layer_type, double _depth, string _parameter_name); + virtual ~RNN_Node_Interface(); + + virtual void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) = 0; + virtual void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) = 0; + virtual void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range) = 0; + virtual void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) = 0; + + virtual void input_fired(int32_t time, double incoming_output) = 0; + virtual void output_fired(int32_t time, double delta) = 0; + virtual void error_fired(int32_t time, double error) = 0; + + virtual int32_t get_number_weights() const = 0; + + virtual void get_weights(vector ¶meters) const = 0; + virtual void set_weights(const vector ¶meters) = 0; + virtual void get_weights(int32_t &offset, vector ¶meters) const = 0; + virtual void set_weights(int32_t &offset, const vector ¶meters) = 0; + virtual void reset(int32_t _series_length) = 0; + + virtual void get_gradients(vector &gradients) = 0; + + virtual RNN_Node_Interface* copy() const = 0; + + void write_to_stream(ostream &out); + + int32_t get_node_type() const; + int32_t get_layer_type() const; + int32_t get_innovation_number() const; + int32_t get_total_inputs() const; + int32_t get_total_outputs() const; + + double get_depth() const; + bool equals(RNN_Node_Interface *other) const; + + bool is_reachable() const; + bool is_enabled() const; + + friend class RNN_Edge; + friend class RNN_Recurrent_Edge; + friend class RNN; + friend class RNN_Genome; + + friend void get_mse(RNN* genome, const vector< vector > &expected, double &mse, vector< vector > &deltas); + friend void get_mae(RNN* genome, const vector< vector > &expected, double &mae, vector< vector > &deltas); }; + struct sort_RNN_Nodes_by_innovation { - bool operator()(RNN_Node_Interface* n1, RNN_Node_Interface* n2) { + bool operator()(RNN_Node_Interface *n1, RNN_Node_Interface *n2) { return n1->get_innovation_number() < n2->get_innovation_number(); } }; + struct sort_RNN_Nodes_by_depth { - bool operator()(RNN_Node_Interface* n1, RNN_Node_Interface* n2) { + bool operator()(RNN_Node_Interface *n1, RNN_Node_Interface *n2) { return n1->get_depth() < n2->get_depth(); } }; diff --git a/rnn/rnn_recurrent_edge.cxx b/rnn/rnn_recurrent_edge.cxx index 78470cb3..2e8195db 100644 --- a/rnn/rnn_recurrent_edge.cxx +++ b/rnn/rnn_recurrent_edge.cxx @@ -2,15 +2,12 @@ #include "common/log.hxx" -RNN_Recurrent_Edge::RNN_Recurrent_Edge( - int32_t _innovation_number, int32_t _recurrent_depth, RNN_Node_Interface* _input_node, - RNN_Node_Interface* _output_node -) { +RNN_Recurrent_Edge::RNN_Recurrent_Edge(int32_t _innovation_number, int32_t _recurrent_depth, RNN_Node_Interface *_input_node, RNN_Node_Interface *_output_node) { innovation_number = _innovation_number; recurrent_depth = _recurrent_depth; if (recurrent_depth <= 0) { - Log::fatal("ERROR, trying to create a recurrent edge with recurrent depth <= 0\n"); + Log::fatal( "ERROR, trying to create a recurrent edge with recurrent depth <= 0\n"); Log::fatal("innovation number: %d\n", innovation_number); Log::fatal("input_node->innovation_number: %d\n", input_node->get_innovation_number()); Log::fatal("output_node->innovation_number: %d\n", output_node->get_innovation_number()); @@ -30,16 +27,10 @@ RNN_Recurrent_Edge::RNN_Recurrent_Edge( forward_reachable = true; backward_reachable = true; - Log::debug( - "\t\tcreated recurrent edge %d from %d to %d\n", innovation_number, input_innovation_number, - output_innovation_number - ); + Log::debug("\t\tcreated recurrent edge %d from %d to %d\n", innovation_number, input_innovation_number, output_innovation_number); } -RNN_Recurrent_Edge::RNN_Recurrent_Edge( - int32_t _innovation_number, int32_t _recurrent_depth, int32_t _input_innovation_number, - int32_t _output_innovation_number, const vector& nodes -) { +RNN_Recurrent_Edge::RNN_Recurrent_Edge(int32_t _innovation_number, int32_t _recurrent_depth, int32_t _input_innovation_number, int32_t _output_innovation_number, const vector &nodes) { innovation_number = _innovation_number; recurrent_depth = _recurrent_depth; @@ -47,7 +38,7 @@ RNN_Recurrent_Edge::RNN_Recurrent_Edge( output_innovation_number = _output_innovation_number; if (recurrent_depth <= 0) { - Log::fatal("ERROR, trying to create a recurrent edge with recurrent depth <= 0\n"); + Log::fatal( "ERROR, trying to create a recurrent edge with recurrent depth <= 0\n"); Log::fatal("innovation number: %d\n", innovation_number); Log::fatal("input_node->innovation_number: %d\n", input_node->get_innovation_number()); Log::fatal("output_node->innovation_number: %d\n", output_node->get_innovation_number()); @@ -56,13 +47,10 @@ RNN_Recurrent_Edge::RNN_Recurrent_Edge( input_node = NULL; output_node = NULL; - for (int32_t i = 0; i < (int32_t) nodes.size(); i++) { + for (int32_t i = 0; i < (int32_t)nodes.size(); i++) { if (nodes[i]->innovation_number == _input_innovation_number) { if (input_node != NULL) { - Log::fatal( - "ERROR in copying RNN_Recurrent_Edge, list of nodes has multiple nodes with same " - "input_innovation_number -- this should never happen.\n" - ); + Log::fatal("ERROR in copying RNN_Recurrent_Edge, list of nodes has multiple nodes with same input_innovation_number -- this should never happen.\n"); exit(1); } @@ -71,10 +59,7 @@ RNN_Recurrent_Edge::RNN_Recurrent_Edge( if (nodes[i]->innovation_number == _output_innovation_number) { if (output_node != NULL) { - Log::fatal( - "ERROR in copying RNN_Recurrent_Edge, list of nodes has multiple nodes with same " - "output_innovation_number -- this should never happen.\n" - ); + Log::fatal("ERROR in copying RNN_Recurrent_Edge, list of nodes has multiple nodes with same output_innovation_number -- this should never happen.\n"); exit(1); } @@ -83,26 +68,18 @@ RNN_Recurrent_Edge::RNN_Recurrent_Edge( } if (input_node == NULL) { - Log::fatal( - "ERROR initializing RNN_Edge, input node with innovation number; %d was not found!\n", - input_innovation_number - ); + Log::fatal("ERROR initializing RNN_Edge, input node with innovation number; %d was not found!\n", input_innovation_number); exit(1); } if (output_node == NULL) { - Log::fatal( - "ERROR initializing RNN_Edge, output node with innovation number; %d was not found!\n", - output_innovation_number - ); + Log::fatal("ERROR initializing RNN_Edge, output node with innovation number; %d was not found!\n", output_innovation_number); exit(1); } } RNN_Recurrent_Edge* RNN_Recurrent_Edge::copy(const vector new_nodes) { - RNN_Recurrent_Edge* e = new RNN_Recurrent_Edge( - innovation_number, recurrent_depth, input_innovation_number, output_innovation_number, new_nodes - ); + RNN_Recurrent_Edge* e = new RNN_Recurrent_Edge(innovation_number, recurrent_depth, input_innovation_number, output_innovation_number, new_nodes); e->recurrent_depth = recurrent_depth; @@ -119,6 +96,7 @@ RNN_Recurrent_Edge* RNN_Recurrent_Edge::copy(const vector n return e; } + int32_t RNN_Recurrent_Edge::get_innovation_number() const { return innovation_number; } @@ -131,6 +109,7 @@ int32_t RNN_Recurrent_Edge::get_output_innovation_number() const { return output_innovation_number; } + const RNN_Node_Interface* RNN_Recurrent_Edge::get_input_node() const { return input_node; } @@ -139,8 +118,10 @@ const RNN_Node_Interface* RNN_Recurrent_Edge::get_output_node() const { return output_node; } -// do a propagate to the network at time 0 so that the -// input fireds are correct + + +//do a propagate to the network at time 0 so that the +//input fireds are correct void RNN_Recurrent_Edge::first_propagate_forward() { for (int32_t i = 0; i < recurrent_depth; i++) { output_node->input_fired(i, 0.0); @@ -149,67 +130,53 @@ void RNN_Recurrent_Edge::first_propagate_forward() { void RNN_Recurrent_Edge::propagate_forward(int32_t time) { if (input_node->inputs_fired[time] != input_node->total_inputs) { - Log::fatal( - "ERROR! propagate forward called on recurrent edge %d where input_node->inputs_fired[%d] (%d) != " - "total_inputs (%d)\n", - innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs - ); + Log::fatal("ERROR! propagate forward called on recurrent edge %d where input_node->inputs_fired[%d] (%d) != total_inputs (%d)\n", innovation_number, time, input_node->inputs_fired[time], input_node->total_inputs); exit(1); } + double output = input_node->output_values[time] * weight; if (time < series_length - recurrent_depth) { - // Log::trace("propagating forward on recurrent edge %d from time %d to time %d from node %d to node %d\n", - // innovation_number, time, time + recurrent_depth, input_innovation_number, output_innovation_number); + //Log::trace("propagating forward on recurrent edge %d from time %d to time %d from node %d to node %d\n", innovation_number, time, time + recurrent_depth, input_innovation_number, output_innovation_number); outputs[time + recurrent_depth] = output; output_node->input_fired(time + recurrent_depth, output); } } -// do a propagate to the network at time (series_length - 1) so that the -// output fireds are correct +//do a propagate to the network at time (series_length - 1) so that the +//output fireds are correct void RNN_Recurrent_Edge::first_propagate_backward() { for (int32_t i = 0; i < recurrent_depth; i++) { - // Log::trace("FIRST propagating backward on recurrent edge %d to time %d from node %d to node %d\n", - // innovation_number, series_length - 1 - i, output_innovation_number, input_innovation_number); + //Log::trace("FIRST propagating backward on recurrent edge %d to time %d from node %d to node %d\n", innovation_number, series_length - 1 - i, output_innovation_number, input_innovation_number); input_node->output_fired(series_length - 1 - i, 0.0); } } void RNN_Recurrent_Edge::propagate_backward(int32_t time) { if (output_node->outputs_fired[time] != output_node->total_outputs) { - // if (output_node->innovation_number == input_node->innovation_number) { - // circular recurrent edge - - /* - if (output_node->outputs_fired[time] != (output_node->total_outputs - 1)) { - Log::fatal("ERROR! propagate backward called on recurrent edge %d where output_node->outputs_fired[%d] (%d) - != total_outputs (%d)\n", innovation_number, time, output_node->outputs_fired[time], - output_node->total_outputs); Log::fatal("input innovation number: %d, output innovation number: %d\n", - input_node->innovation_number, output_node->innovation_number); exit(1); - } - */ + //if (output_node->innovation_number == input_node->innovation_number) { + //circular recurrent edge + + /* + if (output_node->outputs_fired[time] != (output_node->total_outputs - 1)) { + Log::fatal("ERROR! propagate backward called on recurrent edge %d where output_node->outputs_fired[%d] (%d) != total_outputs (%d)\n", innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs); + Log::fatal("input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, output_node->innovation_number); + exit(1); + } + */ //} else { - Log::fatal( - "ERROR! propagate backward called on recurrent edge %d where output_node->outputs_fired[%d] (%d) != " - "total_outputs (%d)\n", - innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs - ); - Log::fatal( - "input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, - output_node->innovation_number - ); - exit(1); + Log::fatal("ERROR! propagate backward called on recurrent edge %d where output_node->outputs_fired[%d] (%d) != total_outputs (%d)\n", innovation_number, time, output_node->outputs_fired[time], output_node->total_outputs); + Log::fatal("input innovation number: %d, output innovation number: %d\n", input_node->innovation_number, output_node->innovation_number); + exit(1); //} } double delta = output_node->d_input[time]; if (time - recurrent_depth >= 0) { - // Log::trace("propagating backward on recurrent edge %d from time %d to time %d from node %d to node %d\n", - // innovation_number, time, time - recurrent_depth, output_innovation_number, input_innovation_number); + //Log::trace("propagating backward on recurrent edge %d from time %d to time %d from node %d to node %d\n", innovation_number, time, time - recurrent_depth, output_innovation_number, input_innovation_number); d_weight += delta * input_node->output_values[time - recurrent_depth]; deltas[time] = delta * weight; @@ -236,21 +203,20 @@ bool RNN_Recurrent_Edge::is_enabled() const { return enabled; } + bool RNN_Recurrent_Edge::is_reachable() const { return forward_reachable && backward_reachable; } -bool RNN_Recurrent_Edge::equals(RNN_Recurrent_Edge* other) const { - if (innovation_number == other->innovation_number && enabled == other->enabled) { - return true; - } +bool RNN_Recurrent_Edge::equals(RNN_Recurrent_Edge *other) const { + if (innovation_number == other->innovation_number && enabled == other->enabled) return true; return false; } -void RNN_Recurrent_Edge::write_to_stream(ostream& out) { - out.write((char*) &innovation_number, sizeof(int32_t)); - out.write((char*) &recurrent_depth, sizeof(int32_t)); - out.write((char*) &input_innovation_number, sizeof(int32_t)); - out.write((char*) &output_innovation_number, sizeof(int32_t)); - out.write((char*) &enabled, sizeof(bool)); +void RNN_Recurrent_Edge::write_to_stream(ostream &out) { + out.write((char*)&innovation_number, sizeof(int32_t)); + out.write((char*)&recurrent_depth, sizeof(int32_t)); + out.write((char*)&input_innovation_number, sizeof(int32_t)); + out.write((char*)&output_innovation_number, sizeof(int32_t)); + out.write((char*)&enabled, sizeof(bool)); } diff --git a/rnn/rnn_recurrent_edge.hxx b/rnn/rnn_recurrent_edge.hxx index 1520f0e4..b4beee15 100644 --- a/rnn/rnn_recurrent_edge.hxx +++ b/rnn/rnn_recurrent_edge.hxx @@ -6,80 +6,75 @@ class RNN; #include "rnn_node_interface.hxx" class RNN_Recurrent_Edge { - private: - int32_t innovation_number; - int32_t series_length; + private: + int32_t innovation_number; + int32_t series_length; - // how far in the past to get the value - int32_t recurrent_depth; + //how far in the past to get the value + int32_t recurrent_depth; - vector outputs; - vector deltas; + vector outputs; + vector deltas; - double weight; - double d_weight; + double weight; + double d_weight; - bool enabled; - bool forward_reachable; - bool backward_reachable; + bool enabled; + bool forward_reachable; + bool backward_reachable; - int32_t input_innovation_number; - int32_t output_innovation_number; + int32_t input_innovation_number; + int32_t output_innovation_number; - RNN_Node_Interface* input_node; - RNN_Node_Interface* output_node; + RNN_Node_Interface *input_node; + RNN_Node_Interface *output_node; - public: - RNN_Recurrent_Edge( - int32_t _innovation_number, int32_t _recurrent_depth, RNN_Node_Interface* _input_node, - RNN_Node_Interface* _output_node - ); + public: + RNN_Recurrent_Edge(int32_t _innovation_number, int32_t _recurrent_depth, RNN_Node_Interface *_input_node, RNN_Node_Interface *_output_node); - RNN_Recurrent_Edge( - int32_t _innovation_number, int32_t _recurrent_depth, int32_t _input_innovation_number, - int32_t _output_innovation_number, const vector& nodes - ); + RNN_Recurrent_Edge(int32_t _innovation_number, int32_t _recurrent_depth, int32_t _input_innovation_number, int32_t _output_innovation_number, const vector &nodes); - void reset(int32_t _series_length); + void reset(int32_t _series_length); - void first_propagate_forward(); - void first_propagate_backward(); - void propagate_forward(int32_t time); - void propagate_backward(int32_t time); + void first_propagate_forward(); + void first_propagate_backward(); + void propagate_forward(int32_t time); + void propagate_backward(int32_t time); - int32_t get_recurrent_depth() const; - double get_gradient(); - bool is_enabled() const; - bool is_reachable() const; + int32_t get_recurrent_depth() const; + double get_gradient(); + bool is_enabled() const; + bool is_reachable() const; - RNN_Recurrent_Edge* copy(const vector new_nodes); + RNN_Recurrent_Edge* copy(const vector new_nodes); - int32_t get_innovation_number() const; - int32_t get_input_innovation_number() const; - int32_t get_output_innovation_number() const; + int32_t get_innovation_number() const; + int32_t get_input_innovation_number() const; + int32_t get_output_innovation_number() const; - const RNN_Node_Interface* get_input_node() const; - const RNN_Node_Interface* get_output_node() const; + const RNN_Node_Interface* get_input_node() const; + const RNN_Node_Interface* get_output_node() const; - void write_to_stream(ostream& out); + void write_to_stream(ostream &out); - bool equals(RNN_Recurrent_Edge* other) const; + bool equals(RNN_Recurrent_Edge *other) const; - friend class RNN_Genome; - friend class RNN; - friend class EXAMM; - friend class RecDepthFrequencyTable; + friend class RNN_Genome; + friend class RNN; + friend class EXAMM; + friend class RecDepthFrequencyTable; }; + struct sort_RNN_Recurrent_Edges_by_depth { - bool operator()(RNN_Recurrent_Edge* n1, RNN_Recurrent_Edge* n2) { + bool operator()(RNN_Recurrent_Edge *n1, RNN_Recurrent_Edge *n2) { if (n1->get_input_node()->get_depth() < n2->get_input_node()->get_depth()) { return true; } else if (n1->get_input_node()->get_depth() == n2->get_input_node()->get_depth()) { - // make sure the order of the edges is *always* the same - // going through the edges in different orders may effect the output - // of backpropagation + //make sure the order of the edges is *always* the same + //going through the edges in different orders may effect the output + //of backpropagation if (n1->get_innovation_number() < n2->get_innovation_number()) { return true; } else { @@ -89,18 +84,18 @@ struct sort_RNN_Recurrent_Edges_by_depth { } else { return false; } - } + } }; struct sort_RNN_Recurrent_Edges_by_output_depth { - bool operator()(RNN_Recurrent_Edge* n1, RNN_Recurrent_Edge* n2) { + bool operator()(RNN_Recurrent_Edge *n1, RNN_Recurrent_Edge *n2) { if (n1->get_output_node()->get_depth() < n2->get_output_node()->get_depth()) { return true; } else if (n1->get_output_node()->get_depth() == n2->get_output_node()->get_depth()) { - // make sure the order of the edges is *always* the same - // going through the edges in different orders may effect the output - // of backpropagation + //make sure the order of the edges is *always* the same + //going through the edges in different orders may effect the output + //of backpropagation if (n1->get_innovation_number() < n2->get_innovation_number()) { return true; } else { @@ -110,13 +105,15 @@ struct sort_RNN_Recurrent_Edges_by_output_depth { } else { return false; } - } + } }; + struct sort_RNN_Recurrent_Edges_by_innovation { - bool operator()(RNN_Recurrent_Edge* n1, RNN_Recurrent_Edge* n2) { + bool operator()(RNN_Recurrent_Edge *n1, RNN_Recurrent_Edge *n2) { return n1->get_innovation_number() < n2->get_innovation_number(); - } + } }; + #endif diff --git a/rnn/ugrnn_node.cxx b/rnn/ugrnn_node.cxx index 0b9081fb..27b2c92d 100644 --- a/rnn/ugrnn_node.cxx +++ b/rnn/ugrnn_node.cxx @@ -1,4 +1,5 @@ #include + #include using std::ostream; @@ -15,25 +16,25 @@ using std::uniform_real_distribution; #include using std::vector; -#include "common/log.hxx" #include "common/random.hxx" -#include "mse.hxx" +#include "common/log.hxx" + #include "rnn_node_interface.hxx" +#include "mse.hxx" #include "ugrnn_node.hxx" + #define NUMBER_UGRNN_WEIGHTS 6 -UGRNN_Node::UGRNN_Node(int32_t _innovation_number, int32_t _type, double _depth) - : RNN_Node_Interface(_innovation_number, _type, _depth) { +UGRNN_Node::UGRNN_Node(int32_t _innovation_number, int32_t _type, double _depth) : RNN_Node_Interface(_innovation_number, _type, _depth) { node_type = UGRNN_NODE; } UGRNN_Node::~UGRNN_Node() { } -void UGRNN_Node::initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma -) { +void UGRNN_Node::initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma) { + cw = bound(normal_distribution.random(generator, mu, sigma)); ch = bound(normal_distribution.random(generator, mu, sigma)); c_bias = bound(normal_distribution.random(generator, mu, sigma)); @@ -43,7 +44,8 @@ void UGRNN_Node::initialize_lamarckian( g_bias = bound(normal_distribution.random(generator, mu, sigma)); } -void UGRNN_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng_1_1, double range) { +void UGRNN_Node::initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng_1_1, double range) { + cw = range * (rng_1_1(generator)); ch = range * (rng_1_1(generator)); c_bias = range * (rng_1_1(generator)); @@ -53,7 +55,7 @@ void UGRNN_Node::initialize_xavier(minstd_rand0& generator, uniform_real_distrib g_bias = range * (rng_1_1(generator)); } -void UGRNN_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range) { +void UGRNN_Node::initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range){ cw = range * normal_distribution.random(generator, 0, 1); ch = range * normal_distribution.random(generator, 0, 1); c_bias = range * normal_distribution.random(generator, 0, 1); @@ -63,7 +65,7 @@ void UGRNN_Node::initialize_kaiming(minstd_rand0& generator, NormalDistribution& g_bias = range * normal_distribution.random(generator, 0, 1); } -void UGRNN_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng) { +void UGRNN_Node::initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng) { cw = rng(generator); ch = rng(generator); c_bias = rng(generator); @@ -76,7 +78,7 @@ void UGRNN_Node::initialize_uniform_random(minstd_rand0& generator, uniform_real double UGRNN_Node::get_gradient(string gradient_name) { double gradient_sum = 0.0; - for (int32_t i = 0; i < series_length; i++) { + for (int32_t i = 0; i < series_length; i++ ) { if (gradient_name == "cw") { gradient_sum += d_cw[i]; } else if (gradient_name == "ch") { @@ -107,25 +109,19 @@ void UGRNN_Node::input_fired(int32_t time, double incoming_output) { input_values[time] += incoming_output; - if (inputs_fired[time] < total_inputs) { - return; - } else if (inputs_fired[time] > total_inputs) { - Log::fatal( - "ERROR: inputs_fired on UGRNN_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, - inputs_fired[time], total_inputs - ); + if (inputs_fired[time] < total_inputs) return; + else if (inputs_fired[time] > total_inputs) { + Log::fatal("ERROR: inputs_fired on UGRNN_Node %d at time %d is %d and total_inputs is %d\n", innovation_number, time, inputs_fired[time], total_inputs); exit(1); } - // update the reset gate bias so its centered around 1 - // g_bias += 1; + //update the reset gate bias so its centered around 1 + //g_bias += 1; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; double xcw = x * cw; double hch = h_prev * ch; @@ -142,40 +138,32 @@ void UGRNN_Node::input_fired(int32_t time, double incoming_output) { output_values[time] = (g[time] * h_prev) + ((1 - g[time]) * c[time]); - // reset alpha, beta1, beta2 so they don't mess with mean/stddev calculations for - // parameter generation - // g_bias -= 1.0; + //reset alpha, beta1, beta2 so they don't mess with mean/stddev calculations for + //parameter generation + //g_bias -= 1.0; } void UGRNN_Node::try_update_deltas(int32_t time) { - if (outputs_fired[time] < total_outputs) { - return; - } else if (outputs_fired[time] > total_outputs) { - Log::fatal( - "ERROR: outputs_fired on UGRNN_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, - outputs_fired[time], total_outputs - ); + if (outputs_fired[time] < total_outputs) return; + else if (outputs_fired[time] > total_outputs) { + Log::fatal("ERROR: outputs_fired on UGRNN_Node %d at time %d is %d and total_outputs is %d\n", innovation_number, time, outputs_fired[time], total_outputs); exit(1); } - // update the reset gate bias so its centered around 1 - // g_bias += 1.0; + //update the reset gate bias so its centered around 1 + //g_bias += 1.0; double error = error_values[time]; double x = input_values[time]; double h_prev = 0.0; - if (time > 0) { - h_prev = output_values[time - 1]; - } + if (time > 0) h_prev = output_values[time - 1]; - // backprop output gate + //backprop output gate double d_h = error; - if (time < (series_length - 1)) { - d_h += d_h_prev[time + 1]; - } - // get the error into the output (z), it's the error from ahead in the network - // as well as from the previous output of the cell + if (time < (series_length - 1)) d_h += d_h_prev[time + 1]; + //get the error into the output (z), it's the error from ahead in the network + //as well as from the previous output of the cell d_h_prev[time] = d_h * g[time]; @@ -196,8 +184,8 @@ void UGRNN_Node::try_update_deltas(int32_t time) { d_ch[time] = d_c * h_prev; d_h_prev[time] += d_c * ch; - // reset the reset gate bias to be around 0 - // g_bias -= 1.0; + //reset the reset gate bias to be around 0 + //g_bias -= 1.0; } void UGRNN_Node::error_fired(int32_t time, double error) { @@ -216,23 +204,25 @@ void UGRNN_Node::output_fired(int32_t time, double delta) { try_update_deltas(time); } + int32_t UGRNN_Node::get_number_weights() const { return NUMBER_UGRNN_WEIGHTS; } -void UGRNN_Node::get_weights(vector& parameters) const { +void UGRNN_Node::get_weights(vector ¶meters) const { parameters.resize(get_number_weights()); int32_t offset = 0; get_weights(offset, parameters); } -void UGRNN_Node::set_weights(const vector& parameters) { +void UGRNN_Node::set_weights(const vector ¶meters) { int32_t offset = 0; set_weights(offset, parameters); } -void UGRNN_Node::set_weights(int32_t& offset, const vector& parameters) { - // int32_t start_offset = offset; + +void UGRNN_Node::set_weights(int32_t &offset, const vector ¶meters) { + //int32_t start_offset = offset; cw = bound(parameters[offset++]); ch = bound(parameters[offset++]); @@ -242,12 +232,12 @@ void UGRNN_Node::set_weights(int32_t& offset, const vector& parameters) gh = bound(parameters[offset++]); g_bias = bound(parameters[offset++]); - // int32_t end_offset = offset; - // Log::debug("set weights from offset %d to %d on UGRNN_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::debug("set weights from offset %d to %d on UGRNN_Node %d\n", start_offset, end_offset, innovation_number); } -void UGRNN_Node::get_weights(int32_t& offset, vector& parameters) const { - // int32_t start_offset = offset; +void UGRNN_Node::get_weights(int32_t &offset, vector ¶meters) const { + //int32_t start_offset = offset; parameters[offset++] = cw; parameters[offset++] = ch; @@ -257,11 +247,12 @@ void UGRNN_Node::get_weights(int32_t& offset, vector& parameters) const parameters[offset++] = gh; parameters[offset++] = g_bias; - // int32_t end_offset = offset; - // Log::debug("got weights from offset %d to %d on UGRNN_Node %d\n", start_offset, end_offset, innovation_number); + //int32_t end_offset = offset; + //Log::debug("got weights from offset %d to %d on UGRNN_Node %d\n", start_offset, end_offset, innovation_number); } -void UGRNN_Node::get_gradients(vector& gradients) { + +void UGRNN_Node::get_gradients(vector &gradients) { gradients.assign(NUMBER_UGRNN_WEIGHTS, 0.0); for (int32_t i = 0; i < NUMBER_UGRNN_WEIGHTS; i++) { @@ -297,7 +288,7 @@ void UGRNN_Node::reset(int32_t _series_length) { g.assign(series_length, 0.0); ld_g.assign(series_length, 0.0); - // reset values from rnn_node_interface + //reset values from rnn_node_interface d_input.assign(series_length, 0.0); error_values.assign(series_length, 0.0); @@ -311,7 +302,7 @@ void UGRNN_Node::reset(int32_t _series_length) { RNN_Node_Interface* UGRNN_Node::copy() const { UGRNN_Node* n = new UGRNN_Node(innovation_number, layer_type, depth); - // copy UGRNN_Node values + //copy UGRNN_Node values n->cw = cw; n->ch = ch; n->c_bias = c_bias; @@ -333,7 +324,7 @@ RNN_Node_Interface* UGRNN_Node::copy() const { n->g = g; n->ld_g = ld_g; - // copy RNN_Node_Interface values + //copy RNN_Node_Interface values n->series_length = series_length; n->input_values = input_values; n->output_values = output_values; @@ -351,6 +342,7 @@ RNN_Node_Interface* UGRNN_Node::copy() const { return n; } -void UGRNN_Node::write_to_stream(ostream& out) { +void UGRNN_Node::write_to_stream(ostream &out) { RNN_Node_Interface::write_to_stream(out); } + diff --git a/rnn/ugrnn_node.hxx b/rnn/ugrnn_node.hxx index 620a8caf..bb457f8e 100644 --- a/rnn/ugrnn_node.hxx +++ b/rnn/ugrnn_node.hxx @@ -12,68 +12,69 @@ using std::uniform_real_distribution; using std::vector; #include "common/random.hxx" + #include "rnn_node_interface.hxx" class UGRNN_Node : public RNN_Node_Interface { - private: - double cw; - double ch; - double c_bias; + private: + double cw; + double ch; + double c_bias; + + double gw; + double gh; + double g_bias; - double gw; - double gh; - double g_bias; + vector d_cw; + vector d_ch; + vector d_c_bias; + vector d_gw; + vector d_gh; + vector d_g_bias; - vector d_cw; - vector d_ch; - vector d_c_bias; - vector d_gw; - vector d_gh; - vector d_g_bias; + vector d_h_prev; - vector d_h_prev; + vector c; + vector ld_c; + vector g; + vector ld_g; - vector c; - vector ld_c; - vector g; - vector ld_g; + public: - public: - UGRNN_Node(int32_t _innovation_number, int32_t _type, double _depth); - ~UGRNN_Node(); + UGRNN_Node(int32_t _innovation_number, int32_t _type, double _depth); + ~UGRNN_Node(); - void initialize_lamarckian( - minstd_rand0& generator, NormalDistribution& normal_distribution, double mu, double sigma - ); - void initialize_xavier(minstd_rand0& generator, uniform_real_distribution& rng1_1, double range); - void initialize_kaiming(minstd_rand0& generator, NormalDistribution& normal_distribution, double range); - void initialize_uniform_random(minstd_rand0& generator, uniform_real_distribution& rng); + void initialize_lamarckian(minstd_rand0 &generator, NormalDistribution &normal_distribution, double mu, double sigma); + void initialize_xavier(minstd_rand0 &generator, uniform_real_distribution &rng1_1, double range); + void initialize_kaiming(minstd_rand0 &generator, NormalDistribution &normal_distribution, double range); + void initialize_uniform_random(minstd_rand0 &generator, uniform_real_distribution &rng); + + double get_gradient(string gradient_name); + void print_gradient(string gradient_name); - double get_gradient(string gradient_name); - void print_gradient(string gradient_name); + void input_fired(int32_t time, double incoming_output); - void input_fired(int32_t time, double incoming_output); + void try_update_deltas(int32_t time); + void error_fired(int32_t time, double error); + void output_fired(int32_t time, double delta); - void try_update_deltas(int32_t time); - void error_fired(int32_t time, double error); - void output_fired(int32_t time, double delta); + int32_t get_number_weights() const; - int32_t get_number_weights() const; + void get_weights(vector ¶meters) const; + void set_weights(const vector ¶meters); - void get_weights(vector& parameters) const; - void set_weights(const vector& parameters); + void get_weights(int32_t &offset, vector ¶meters) const; + void set_weights(int32_t &offset, const vector ¶meters); - void get_weights(int32_t& offset, vector& parameters) const; - void set_weights(int32_t& offset, const vector& parameters); + void get_gradients(vector &gradients); - void get_gradients(vector& gradients); + void reset(int32_t _series_length); - void reset(int32_t _series_length); + void write_to_stream(ostream &out); - void write_to_stream(ostream& out); + RNN_Node_Interface* copy() const; - RNN_Node_Interface* copy() const; + friend class RNN_Edge; - friend class RNN_Edge; }; #endif diff --git a/weights/weight_rules.cxx b/weights/weight_rules.cxx index a4b42636..3dfdb7d6 100644 --- a/weights/weight_rules.cxx +++ b/weights/weight_rules.cxx @@ -1,5 +1,4 @@ #include "weights/weight_rules.hxx" - #include "common/arguments.hxx" #include "common/log.hxx" @@ -9,11 +8,7 @@ WeightRules::WeightRules() { mutated_components_weight = LAMARCKIAN; } -WeightRules::WeightRules(const vector& arguments) { - initialize_from_args(arguments); -} - -void WeightRules::initialize_from_args(const vector& arguments) { +void WeightRules::generate_weight_initialize_from_arguments(const vector &arguments) { Log::info("Getting arguments for weight initialize and weight inheritance methods\n"); string weight_initialize_string = "xavier"; get_argument(arguments, "--weight_initialize", false, weight_initialize_string); @@ -66,10 +61,10 @@ string WeightRules::get_mutated_components_weight_method_name() { } WeightRules* WeightRules::copy() { - WeightRules* weight_rule_copy = new WeightRules(); + WeightRules *weight_rule_copy = new WeightRules(); weight_rule_copy->set_weight_initialize_method(weight_initialize); weight_rule_copy->set_weight_inheritance_method(weight_inheritance); weight_rule_copy->set_mutated_components_weight_method(mutated_components_weight); - + return weight_rule_copy; -} +} \ No newline at end of file diff --git a/weights/weight_rules.hxx b/weights/weight_rules.hxx index c496bfe7..e2fa0c70 100644 --- a/weights/weight_rules.hxx +++ b/weights/weight_rules.hxx @@ -6,11 +6,18 @@ using std::string; #include using std::vector; -enum WeightType { RANDOM = 0, XAVIER = 1, KAIMING = 2, LAMARCKIAN = 3, NONE = -1 }; +enum WeightType { + RANDOM = 0, + XAVIER = 1, + KAIMING = 2, + LAMARCKIAN = 3, + NONE = -1 +}; static string WEIGHT_TYPES_STRING[] = {"random", "xavier", "kaiming", "lamarckian"}; static int32_t NUM_WEIGHT_TYPES = 4; + inline WeightType get_enum_from_string(string input_string) { WeightType weight_type; for (int i = 0; i < NUM_WEIGHT_TYPES; i++) { @@ -26,34 +33,36 @@ int32_t enum_to_integer(Weight_Type weight) { return static_cast::type>(weight); } -inline WeightType integer_to_enum(int32_t input_int) { +inline WeightType integer_to_enum (int32_t input_int) { WeightType weight_type = static_cast(input_int); return weight_type; } class WeightRules { - private: - WeightType weight_initialize; - WeightType weight_inheritance; - WeightType mutated_components_weight; - - public: - WeightRules(); - explicit WeightRules(const vector& arguments); - - void initialize_from_args(const vector& arguments); - WeightType get_weight_initialize_method(); - WeightType get_weight_inheritance_method(); - WeightType get_mutated_components_weight_method(); - - string get_weight_initialize_method_name(); - string get_weight_inheritance_method_name(); - string get_mutated_components_weight_method_name(); - - void set_weight_initialize_method(WeightType _weight_initialize); - void set_weight_inheritance_method(WeightType _weight_inheritance); - void set_mutated_components_weight_method(WeightType _mutated_components_weight); - WeightRules* copy(); + private: + WeightType weight_initialize; + WeightType weight_inheritance; + WeightType mutated_components_weight; + + public: + WeightRules(); + void generate_weight_initialize_from_arguments(const vector &arguments); + WeightType get_weight_initialize_method(); + WeightType get_weight_inheritance_method(); + WeightType get_mutated_components_weight_method(); + + string get_weight_initialize_method_name(); + string get_weight_inheritance_method_name(); + string get_mutated_components_weight_method_name(); + + void set_weight_initialize_method(WeightType _weight_initialize); + void set_weight_inheritance_method(WeightType _weight_inheritance); + void set_mutated_components_weight_method(WeightType _mutated_components_weight); + WeightRules* copy(); + }; + + + #endif diff --git a/weights/weight_update.cxx b/weights/weight_update.cxx index aa3154b3..c5e17a21 100644 --- a/weights/weight_update.cxx +++ b/weights/weight_update.cxx @@ -1,7 +1,7 @@ -#include "weight_update.hxx" - #include +#include "weights/weight_update.hxx" + #include "common/arguments.hxx" #include "common/log.hxx" @@ -14,6 +14,7 @@ WeightUpdate::WeightUpdate() { beta1 = 0.9; beta2 = 0.99; + //SHO SY COMMENTED LINE BELOW learning_rate = 0.001; high_threshold = 1.0; low_threshold = 0.05; @@ -21,19 +22,13 @@ WeightUpdate::WeightUpdate() { use_low_norm = true; } -WeightUpdate::WeightUpdate(const vector& arguments) : WeightUpdate() { - generate_from_arguments(arguments); -} - -void WeightUpdate::generate_from_arguments(const vector& arguments) { +void WeightUpdate::generate_from_arguments(const vector &arguments) { Log::info("Getting infomation on weight update methods for backprop\n"); if (argument_exists(arguments, "--weight_update")) { string weight_update_method_string; get_argument(arguments, "--weight_update", true, weight_update_method_string); weight_update_method = get_enum_method_from_string(weight_update_method_string); - Log::info( - "Doing backprop with weight update method: %s\n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str() - ); + Log::info("Doing backprop with weight update method: %s\n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); if (weight_update_method == MOMENTUM) { get_argument(arguments, "--mu", false, momentum); Log::info("Momentum weight update mu=%f\n", momentum); @@ -58,12 +53,7 @@ void WeightUpdate::generate_from_arguments(const vector& arguments) { get_argument(arguments, "--beta2", false, beta2); Log::info("Adam-bias weight update eps=%f, beta1=%f, beta2=%f\n", epsilon, beta1, beta2); } - } else { - Log::info( - "Backprop weight update method not set, using default method %s and default parameters\n", - WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str() - ); - } + } else Log::info("Backprop weight update method not set, using default method %s and default parameters\n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); get_argument(arguments, "--learning_rate", false, learning_rate); get_argument(arguments, "--high_threshold", false, high_threshold); @@ -73,10 +63,10 @@ void WeightUpdate::generate_from_arguments(const vector& arguments) { Log::info("Use low norm is set to %s, low norm is %f\n", use_low_norm ? "True" : "False", low_threshold); } -void WeightUpdate::update_weights( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::update_weights(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch, double _learning_rate) { + //Log::error("Learning rate before update_weights: %lf",learning_rate); + learning_rate = _learning_rate; + //Log::error("Learning rate after update_weights: %lf",learning_rate); if (weight_update_method == VANILLA) { vanilla_weight_update(parameters, velocity, prev_velocity, gradient, epoch); } else if (weight_update_method == MOMENTUM) { @@ -92,42 +82,32 @@ void WeightUpdate::update_weights( } else if (weight_update_method == ADAM_BIAS) { adam_bias_weight_update(parameters, velocity, prev_velocity, gradient, epoch); } else { - Log::fatal( - "Unrecognized weight update method's enom number: %d, this should never happen!\n", weight_update_method - ); + Log::fatal("Unrecognized weight update method's enom number: %d, this should never happen!\n", weight_update_method); exit(1); } + } -void WeightUpdate::vanilla_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::vanilla_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { parameters[i] -= learning_rate * gradient[i]; gradient_clip(parameters[i]); } } -void WeightUpdate::momentum_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::momentum_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { velocity[i] = momentum * velocity[i] - learning_rate * gradient[i]; parameters[i] += velocity[i]; gradient_clip(parameters[i]); } } -void WeightUpdate::nesterov_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::nesterov_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::info("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { prev_velocity[i] = velocity[i]; velocity[i] = momentum * velocity[i] - learning_rate * gradient[i]; parameters[i] += -momentum * prev_velocity[i] + (1 + momentum) * velocity[i]; @@ -135,12 +115,9 @@ void WeightUpdate::nesterov_weight_update( } } -void WeightUpdate::adagrad_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::adagrad_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { // here the velocity is the "cache" in Adagrad velocity[i] += gradient[i] * gradient[i]; parameters[i] += -learning_rate * gradient[i] / (sqrt(velocity[i]) + epsilon); @@ -148,12 +125,9 @@ void WeightUpdate::adagrad_weight_update( } } -void WeightUpdate::rmsprop_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::rmsprop_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { // here the velocity is the "cache" in RMSProp velocity[i] = decay_rate * velocity[i] + (1 - decay_rate) * gradient[i] * gradient[i]; parameters[i] += -learning_rate * gradient[i] / (sqrt(velocity[i]) + epsilon); @@ -161,12 +135,9 @@ void WeightUpdate::rmsprop_weight_update( } } -void WeightUpdate::adam_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::adam_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { // here the velocity is the "v" in adam, the prev_velocity is "m" in adam prev_velocity[i] = beta1 * prev_velocity[i] + (1 - beta1) * gradient[i]; velocity[i] = beta2 * velocity[i] + (1 - beta2) * (gradient[i] * gradient[i]); @@ -175,12 +146,9 @@ void WeightUpdate::adam_weight_update( } } -void WeightUpdate::adam_bias_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch -) { +void WeightUpdate::adam_bias_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch) { Log::trace("Doing weight update with method: %s \n", WEIGHT_UPDATE_METHOD_STRING[weight_update_method].c_str()); - for (int32_t i = 0; i < (int32_t) parameters.size(); i++) { + for (int32_t i = 0; i < (int32_t)parameters.size(); i++) { // here the velocity is the "v" in adam, the prev_velocity is "m" in adam prev_velocity[i] = beta1 * prev_velocity[i] + (1 - beta1) * gradient[i]; double mt = prev_velocity[i] / (1 - pow(beta1, epoch)); @@ -191,12 +159,9 @@ void WeightUpdate::adam_bias_weight_update( } } -void WeightUpdate::gradient_clip(double& parameter) { - if (parameter < -10.0) { - parameter = -10.0; - } else if (parameter > 10.0) { - parameter = 10.0; - } +void WeightUpdate::gradient_clip(double ¶meter) { + if (parameter < -10.0) parameter = -10.0; + else if (parameter > 10.0) parameter = 10.0; } double WeightUpdate::get_learning_rate() { @@ -233,30 +198,30 @@ void WeightUpdate::enable_low_threshold(double _low_threshold) { low_threshold = _low_threshold; } -double WeightUpdate::get_norm(vector& analytic_gradient) { +double WeightUpdate::get_norm(vector &analytic_gradient) { double norm = 0.0; - for (int32_t i = 0; i < (int32_t) analytic_gradient.size(); i++) { + for (int32_t i = 0; i < (int32_t)analytic_gradient.size(); i++) { norm += analytic_gradient[i] * analytic_gradient[i]; } norm = sqrt(norm); return norm; } -void WeightUpdate::norm_gradients(vector& analytic_gradient, double norm) { +void WeightUpdate::norm_gradients(vector &analytic_gradient, double norm) { if (use_high_norm && norm > high_threshold) { - double high_threshold_norm = high_threshold / norm; - Log::debug_no_header(", OVER THRESHOLD, multiplier: %lf", high_threshold_norm); + double high_threshold_norm = high_threshold / norm; + Log::debug_no_header(", OVER THRESHOLD, multiplier: %lf", high_threshold_norm); - for (int32_t i = 0; i < (int32_t) analytic_gradient.size(); i++) { - analytic_gradient[i] = high_threshold_norm * analytic_gradient[i]; - } + for (int32_t i = 0; i < (int32_t)analytic_gradient.size(); i++) { + analytic_gradient[i] = high_threshold_norm * analytic_gradient[i]; + } } else if (use_low_norm && norm < low_threshold) { double low_threshold_norm = low_threshold / norm; Log::debug_no_header(", UNDER THRESHOLD, multiplier: %lf", low_threshold_norm); - for (int32_t i = 0; i < (int32_t) analytic_gradient.size(); i++) { + for (int32_t i = 0; i < (int32_t)analytic_gradient.size(); i++) { analytic_gradient[i] = low_threshold_norm * analytic_gradient[i]; } } -} +} \ No newline at end of file diff --git a/weights/weight_update.hxx b/weights/weight_update.hxx index c4828947..e9115a0c 100644 --- a/weights/weight_update.hxx +++ b/weights/weight_update.hxx @@ -4,17 +4,22 @@ #include using std::string; -#include -using std::vector; - #include "common/arguments.hxx" -enum WeightUpdateMethod { VANILLA = 0, MOMENTUM = 1, NESTEROV = 2, ADAGRAD = 3, RMSPROP = 4, ADAM = 5, ADAM_BIAS = 6 }; +enum WeightUpdateMethod { + VANILLA = 0, + MOMENTUM = 1, + NESTEROV = 2, + ADAGRAD = 3, + RMSPROP = 4, + ADAM = 5, + ADAM_BIAS = 6 +}; -static string WEIGHT_UPDATE_METHOD_STRING[] = {"vanilla", "momentum", "nesterov", "adagrad", - "rmsprop", "adam", "adam-bias"}; +static string WEIGHT_UPDATE_METHOD_STRING[] = {"vanilla", "momentum", "nesterov", "adagrad", "rmsprop", "adam", "adam-bias"}; static int32_t NUM_WEIGHT_UPDATE_TYPES = 7; + inline WeightUpdateMethod get_enum_method_from_string(string input_string) { WeightUpdateMethod method; for (int i = 0; i < NUM_WEIGHT_UPDATE_TYPES; i++) { @@ -31,73 +36,51 @@ int32_t enum_method_to_integer(Weight_Update_Type method) { } class WeightUpdate { - private: - WeightUpdateMethod weight_update_method; - double momentum; - double epsilon; - double decay_rate; - double beta1; - double beta2; - double learning_rate; - - bool use_high_norm; - double high_threshold; - bool use_low_norm; - double low_threshold; - - public: - WeightUpdate(); - explicit WeightUpdate(const vector& arguments); - void generate_from_arguments(const vector& arguments); - - void update_weights( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - - void vanilla_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void momentum_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void nesterov_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void adagrad_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void rmsprop_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void adam_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - void adam_bias_weight_update( - vector& parameters, vector& velocity, vector& prev_velocity, vector& gradient, - int32_t epoch - ); - - void gradient_clip(double& parameter); - - void set_learning_rate(double _learning_rate); - void disable_high_threshold(); - void enable_high_threshold(double _high_threshold); - void disable_low_threshold(); - void enable_low_threshold(double _low_threshold); - - double get_learning_rate(); - double get_low_threshold(); - double get_high_threshold(); - - double get_norm(vector& analytic_gradient); - void norm_gradients(vector& analytic_gradient, double norm); + private: + WeightUpdateMethod weight_update_method; + double momentum; + double epsilon; + double decay_rate; + double beta1; + double beta2; + //SHO SY COMMENTED LINE BELOW + double learning_rate; + + bool use_high_norm; + double high_threshold; + bool use_low_norm; + double low_threshold; + + public: + WeightUpdate(); + void generate_from_arguments(const vector &arguments); + + void update_weights(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch, double _learning_rate); + + void vanilla_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void momentum_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void nesterov_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void adagrad_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void rmsprop_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void adam_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + void adam_bias_weight_update(vector ¶meters, vector &velocity, vector &prev_velocity, vector &gradient, int32_t epoch); + + void gradient_clip(double ¶meter); + + void set_learning_rate(double _learning_rate); + void disable_high_threshold(); + void enable_high_threshold(double _high_threshold); + void disable_low_threshold(); + void enable_low_threshold(double _low_threshold); + + double get_learning_rate(); + double get_low_threshold(); + double get_high_threshold(); + + double get_norm(vector &analytic_gradient); + void norm_gradients(vector &analytic_gradient, double norm); }; -#endif + + +#endif \ No newline at end of file