00001
00002
00003 #include "osl/rating/featureSet.h"
00004 #include "osl/config.h"
00005 #include "osl/rating/group.h"
00006 #include "osl/rating/group/captureGroup.h"
00007 #include "osl/rating/group/escape.h"
00008 #include "osl/rating/group/squareGroup.h"
00009 #include "osl/rating/group/patternGroup.h"
00010 #include "osl/rating/group/bigramGroup.h"
00011 #include "osl/rating/group/king8Group.h"
00012 #include "osl/rating/group/checkmateGroup.h"
00013 #include "osl/rating/group/pinGroup.h"
00014 #include "osl/move_generator/allMoves.h"
00015 #include "osl/move_generator/escape_.h"
00016 #include "osl/move_classifier/moveAdaptor.h"
00017 #include "osl/move_classifier/safeMove.h"
00018 #include "osl/container/moveVector.h"
00019 #include "osl/stat/variance.h"
00020 #include "osl/oslConfig.h"
00021 #include <boost/format.hpp>
00022 #include <boost/foreach.hpp>
00023 #include <map>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <sstream>
00027 #include <iomanip>
00028 #include <stdexcept>
00029 #include <cmath>
00030
00031
00032
00033
00034
00035
00036
00037
00038 const int MinRating = -4000;
00039
00040 struct osl::rating::FeatureSet::Statistics
00041 {
00043 int average_after, sigma_after;
00045 double average, variance, probability;
00046 Statistics() : average_after(0), sigma_after(0),
00047 average(0), variance(0), probability(0)
00048 {
00049 }
00050 };
00051
00052
00053 osl::rating::
00054 FeatureSet::FeatureSet()
00055 : capture_group(-1), checkmate_if_capture_group(-1), sendoff_group(-1)
00056 {
00057 }
00058
00059 osl::rating::
00060 FeatureSet::~FeatureSet()
00061 {
00062 #ifdef RATING_STAT
00063 showStatistics(std::cerr);
00064 #endif
00065 }
00066
00067 const osl::rating::range_t osl::rating::
00068 FeatureSet::makeRange(size_t group) const
00069 {
00070 int first = 0;
00071 for (size_t i=0; i<groups.size(); ++i) {
00072 if (i == group)
00073 return std::make_pair(first, first+groups[i].size());
00074 first += groups[i].size();
00075 }
00076 assert(0);
00077 abort();
00078 }
00079
00080 void osl::rating::
00081 FeatureSet::addFinished()
00082 {
00083 assert(normal_groups.size() == groups.size());
00084 weights.resize(features.size(), 1.0);
00085 weightslog10.resize(features.size(), 1);
00086 assert(weights.size() == features.size());
00087 ranges.resize(groups.size());
00088 for (size_t i=0; i<groups.size(); ++i)
00089 ranges[i] = makeRange(i);
00090 variance_match.resize(groups.size());
00091 variance_all.resize(groups.size());
00092 frequency.resize(groups.size());
00093 statistics.resize(groups.size());
00094 }
00095
00096 void osl::rating::
00097 FeatureSet::add(Feature *f)
00098 {
00099 add(new Group(f));
00100 }
00101
00102 void osl::rating::
00103 FeatureSet::addCommon(Group *g)
00104 {
00105 features.reserve(features.size()+g->size());
00106 for (size_t i=0; i<g->size(); ++i) {
00107 features.push_back(&(*g)[i]);
00108 }
00109 groups.push_back(g);
00110 effective_in_check.push_back(g->effectiveInCheck());
00111 }
00112
00113 void osl::rating::
00114 FeatureSet::add(Group *g)
00115 {
00116 normal_groups.push_back(true);
00117 addCommon(g);
00118 }
00119
00120 void osl::rating::
00121 FeatureSet::add(CaptureGroup *g)
00122 {
00123 capture_group = normal_groups.size();
00124 normal_groups.push_back(false);
00125 addCommon(g);
00126 }
00127
00128 void osl::rating::
00129 FeatureSet::add(SendOffGroup *g)
00130 {
00131 sendoff_group = normal_groups.size();
00132 normal_groups.push_back(false);
00133 addCommon(g);
00134 }
00135
00136 void osl::rating::
00137 FeatureSet::add(CheckmateIfCaptureGroup *g)
00138 {
00139 checkmate_if_capture_group = normal_groups.size();
00140 normal_groups.push_back(false);
00141 addCommon(g);
00142 }
00143
00144 bool osl::rating::
00145 FeatureSet::tryLoad(const std::string& input_directory)
00146 {
00147 bool result = true;
00148 for (size_t i=0; i<groups.size(); ++i) {
00149 const bool success = groups[i].load(input_directory, ranges[i], weights);
00150 if (! success && result)
00151 std::cerr << "warning: rating load failed " << groups[i].group_name << " " << i
00152 << " in " << input_directory << "\n";
00153 result &= success;
00154 }
00155 for (size_t i=0; i<features.size(); ++i)
00156 weightslog10[i] = static_cast<int>(400*log10(weights[i]));
00157 #ifndef RATING_STAT
00158 std::string filename = input_directory + "/statistics.txt";
00159 std::ifstream is(filename.c_str());
00160 typedef std::map<std::string,Statistics> map_t;
00161 map_t table;
00162 std::string name;
00163 double a, s, p, dummy;
00164 while (is >> name >> a >> s >> dummy >> dummy >> p) {
00165 Statistics& stat = table[name];
00166 stat.average = a;
00167 stat.variance = s*s;
00168 stat.probability = p;
00169 }
00170 for (size_t i=0; i<groups.size(); ++i) {
00171 double a = 0.0, v = 0.0;
00172 for (size_t j=i+1; j<groups.size(); ++j) {
00173 map_t::iterator q = table.find(groups[j].group_name);
00174 if (q == table.end()) {
00175 result = false;
00176 break;
00177 }
00178 a += q->second.probability * q->second.average;
00179 v += q->second.probability * q->second.variance;
00180 }
00181 statistics[i] = table[groups[i].group_name];
00182 statistics[i].average_after = static_cast<int>(a);
00183 statistics[i].sigma_after = static_cast<int>(sqrt(v)*3);
00184 # ifdef VERBOSE_RATING
00185 std::cerr << groups[i].group_name
00186 << " " << statistics[i].average_after
00187 << " " << statistics[i].sigma_after << "\n";
00188 # endif
00189 }
00190 #endif
00191 return result;
00192 }
00193
00194 void osl::rating::
00195 FeatureSet::setWeight(size_t feature_id, const double& value)
00196 {
00197 weights[feature_id] = value;
00198 weightslog10[feature_id] = static_cast<int>(400*log10(value));
00199 }
00200
00201 void osl::rating::
00202 FeatureSet::generateRating(const NumEffectState& state, const RatingEnv& env,
00203 int limit, RatedMoveVector& out, bool in_pv_or_all) const
00204 {
00205 #if (defined RATING_STAT) || (defined RATING_STAT2)
00206 in_pv_or_all = true;
00207 #endif
00208 MoveVector moves;
00209 const bool in_check = state.inCheck();
00210
00211 if (in_check)
00212 GenerateEscapeKing::generate(state, moves);
00213 else
00214 GenerateAllMoves::generate(state.turn(), state, moves);
00215
00216 for (size_t i=0; i<moves.size(); ++i) {
00217 if (moves[i].ptype() == KING) {
00218 if (state.hasEffectAt(alt(state.turn()), moves[i].to()))
00219 continue;
00220 } else {
00221 if (! in_check && env.my_pin.any() && ! moves[i].isDrop()
00222 && move_classifier::PlayerMoveAdaptor<move_classifier::KingOpenMove>::isMember(state, moves[i]))
00223 continue;
00224 }
00225
00226 if (in_pv_or_all)
00227 out.push_back(makeRate(state, in_check, env, moves[i]));
00228 else {
00229 RatedMove r = makeRateWithCut(state, in_check, env, limit, moves[i]);
00230 if (r.rating() > MinRating)
00231 out.push_back(r);
00232 }
00233 }
00234 out.sort();
00235 }
00236
00237
00238 static const osl::CArray2d<int, 8, 20> order_to_depth = {{
00239 { 186, 213, 243, 247, 249, 255, 252, 258, 263, 269, 267, 279, 295, 295, 295, 295, 295, 295, 295, 295, },
00240 { 191, 245, 283, 300, 313, 315, 319, 323, 326, 339, 321, 347, 334, 346, 328, 368, 328, 328, 328, 328, },
00241 { 183, 250, 304, 328, 346, 352, 373, 366, 365, 379, 396, 379, 392, 416, 420, 374, 423, 378, 395, 399, },
00242 { 184, 253, 312, 346, 358, 378, 389, 407, 409, 403, 404, 421, 432, 395, 421, 444, 444, 461, 411, 408, },
00243 { 190, 256, 319, 350, 373, 397, 397, 403, 420, 431, 415, 450, 424, 416, 436, 447, 456, 439, 429, 428, },
00244 { 197, 262, 324, 357, 374, 390, 407, 423, 415, 425, 436, 444, 458, 455, 439, 474, 451, 466, 464, 457, },
00245 { 202, 268, 332, 360, 381, 386, 416, 416, 418, 433, 447, 446, 452, 462, 479, 468, 467, 486, 483, 459, },
00246 { 205, 270, 330, 361, 383, 394, 410, 418, 427, 438, 438, 452, 446, 445, 447, 463, 475, 472, 483, 485, },
00247 }};
00248 static const osl::CArray2d<int, 8, 20> order_to_width = {{
00249 { 262, 445, 584, 685, 788, 890, 982,1067,1120,1148, 1137,1156,1182,1231,1259, 1343,1352,1359,1359,1359, },
00250 { 265, 456, 577, 665, 745, 809, 874, 938, 997,1061, 1088,1154,1179,1231,1259, 1343,1352,1359,1359,1359, },
00251 { 260, 467, 596, 680, 751, 807, 872, 908, 951,1003, 1054,1072,1117,1168,1198, 1188,1267,1259,1311,1344, },
00252 { 261, 467, 599, 688, 747, 810, 861, 914, 948, 975, 1008,1055,1092,1084,1142, 1189,1214,1254,1231,1258, },
00253 { 264, 463, 595, 679, 746, 808, 844, 885, 933, 973, 987,1049,1048,1068,1115, 1151,1184,1191,1209,1233, },
00254 { 268, 459, 588, 673, 732, 788, 840, 887, 910, 950, 989,1022,1059,1078,1088, 1144,1144,1180,1201,1216, },
00255 { 271, 459, 587, 664, 727, 771, 835, 866, 899, 942, 984,1006,1037,1069,1105, 1114,1134,1173,1188,1186, },
00256 { 272, 458, 581, 661, 725, 773, 824, 863, 902, 940, 966,1005,1023,1047,1074, 1113,1145,1163,1193,1214, },
00257 }};
00258
00259 const int sc_width = 100, sc_length = 18, sc_start = -400;
00260 static const osl::CArray2d<int, 8, sc_length> score_to_depth = {{
00261 { 263, 271, 274, 270, 278, 253, 235, 201, 171, 151, 111, 95, 83, 76, 78, 65, 71, 61,},
00262 { 330, 334, 328, 316, 312, 304, 284, 256, 218, 188, 159, 136, 113, 103, 92, 87, 82, 71,},
00263 { 377, 374, 376, 368, 356, 337, 311, 278, 246, 203, 175, 146, 131, 118, 107, 96, 81, 65,},
00264 { 415, 424, 406, 396, 376, 345, 315, 276, 243, 211, 179, 155, 138, 121, 110, 91, 80, 62,},
00265 { 423, 422, 433, 423, 405, 381, 341, 313, 276, 243, 210, 182, 158, 142, 123, 104, 85, 73,},
00266 { 442, 451, 448, 437, 417, 395, 364, 333, 297, 267, 234, 202, 178, 158, 133, 107, 91, 76,},
00267 { 446, 447, 455, 439, 427, 402, 373, 339, 307, 274, 242, 212, 188, 162, 133, 111, 92, 75,},
00268 { 467, 468, 469, 453, 433, 412, 389, 365, 334, 301, 268, 236, 205, 177, 153, 131, 116, 101,},
00269 }};
00270 static const osl::CArray2d<int, 8, sc_length> score_to_width = {{
00271 { 978, 880, 786, 676, 586, 475, 383, 302, 239, 208, 167, 153, 134, 127, 126, 100, 100, 82,},
00272 { 1020, 935, 836, 730, 634, 549, 472, 412, 351, 312, 269, 232, 190, 167, 143, 127, 112, 95,},
00273 { 1095, 998, 910, 810, 715, 623, 543, 471, 407, 338, 291, 246, 216, 189, 160, 140, 115, 90,},
00274 { 1106,1031, 929, 829, 730, 635, 551, 469, 402, 341, 290, 249, 217, 186, 159, 127, 108, 85,},
00275 { 1185,1092, 1011, 913, 811, 717, 617, 538, 459, 391, 331, 285, 242, 210, 176, 143, 114, 96,},
00276 { 1224,1150, 1058, 957, 853, 755, 658, 573, 493, 424, 363, 308, 262, 223, 181, 142, 116, 96,},
00277 { 1224,1134, 1057, 953, 857, 759, 666, 579, 501, 432, 373, 315, 267, 220, 178, 141, 115, 93,},
00278 { 1296,1201, 1115,1009, 904, 807, 717, 638, 563, 492, 425, 363, 305, 254, 210, 172, 145, 123,},
00279 }};
00280
00281 const int rsc_length = 15;
00282 static const osl::CArray2d<int, 8, rsc_length> relative_score_to_depth = {{
00283 { 193, 220, 235, 249, 256, 263, 268, 274, 279, 284, 283, 279, 292, 267, 272, },
00284 { 220, 243, 263, 273, 287, 300, 306, 308, 317, 325, 328, 339, 319, 336, 323, },
00285 { 215, 242, 267, 287, 302, 314, 329, 340, 347, 360, 367, 364, 349, 387, 374, },
00286 { 209, 243, 267, 293, 317, 332, 347, 360, 372, 383, 387, 387, 395, 398, 405, },
00287 { 216, 244, 276, 303, 322, 344, 360, 374, 378, 397, 405, 414, 408, 400, 424, },
00288 { 220, 251, 278, 307, 331, 355, 365, 381, 398, 406, 418, 423, 414, 433, 403, },
00289 { 226, 254, 284, 311, 336, 354, 378, 390, 408, 418, 420, 448, 414, 446, 408, },
00290 { 219, 250, 283, 310, 333, 356, 377, 391, 403, 417, 426, 426, 440, 445, 452, },
00291 }};
00292 static const osl::CArray2d<int, 8, rsc_length> relative_score_to_width = {{
00293 { 214, 285, 357, 442, 520, 596, 669, 742, 816, 881, 928, 972,1045,1079,1143, },
00294 { 237, 302, 374, 442, 519, 595, 662, 731, 799, 870, 925, 994,1031,1112,1159, },
00295 { 230, 294, 367, 442, 517, 595, 675, 746, 815, 884, 951,1012,1060,1149,1185, },
00296 { 224, 292, 361, 441, 524, 602, 682, 758, 833, 904, 964,1028,1105,1164,1223, },
00297 { 231, 295, 369, 449, 525, 611, 692, 771, 839, 922, 985,1041,1094,1150,1239, },
00298 { 235, 301, 370, 450, 532, 616, 690, 769, 851, 920, 991,1054,1100,1194,1217, },
00299 { 240, 300, 373, 448, 527, 607, 693, 768, 845, 919, 981,1066,1094,1191,1218, },
00300 { 233, 294, 364, 435, 511, 591, 674, 753, 832, 917, 993,1065,1157,1224,1300, },
00301 }};
00302
00303 inline int make_prob(int score, int order, int limit, int highest, int progress8, bool in_pv_or_all)
00304 {
00305 const int order_index = std::min((int)order/4, 19);
00306 int result = limit+1;
00307 if (order_to_width[progress8][order_index] <= limit) {
00308 result = (order == 0) ? 100 : order_to_depth[progress8][order_index];
00309 }
00310 score = std::max(sc_start, score);
00311 highest = std::max(sc_start, highest);
00312 const int score_index = std::min((score - sc_start)/sc_width, sc_length-1);
00313 if (limit > 600 && score_to_width[progress8][score_index] <= limit) {
00314 result = std::min(result, score_to_depth[progress8][score_index]);
00315 }
00316 if (limit > 700 && order > 0 && in_pv_or_all) {
00317 const int rscore_index = std::min((highest - score)/100, rsc_length-1);
00318 assert(rscore_index >= 0);
00319 if (relative_score_to_width[progress8][rscore_index] <= limit)
00320 result = std::min(result, relative_score_to_depth[progress8][rscore_index]);
00321 }
00322 return result;
00323 }
00324
00325 #ifdef RATING_STAT2
00326 namespace osl
00327 {
00328 namespace
00329 {
00330 CArray2d<CArray<stat::Average,8>,14,40> data;
00331 CArray2d<CArray<double,8>,14,80> selected_all;
00332 void add_stat(int limit, int rating, bool added, int progress8)
00333 {
00334 limit = std::min(limit, 999);
00335 limit -= 300;
00336 limit = std::max(limit, 0);
00337 rating = std::max(-999,rating);
00338 rating = std::min(999,rating);
00339 data[limit/50][(rating+1000)/50][progress8].add(added);
00340 if (added)
00341 selected_all[limit/50][(rating+1000)/25][progress8] += 1.0;
00342 }
00343 struct Reporter
00344 {
00345 ~Reporter()
00346 {
00347 std::cerr << "limit " << 0*50+300 << " - " << (data.size1()-1)*50+300 << "\n";
00348 for (int p=0; p<8; ++p)
00349 {
00350 std::cerr << "progress8 " << p << "\n ";
00351 for (size_t j=0; j<data.size1(); ++j)
00352 {
00353 size_t i=0;
00354 for (; i<data.size2(); ++i)
00355 if (data[j][i][p].getAverage() > 0.05)
00356 break;
00357 std::cerr << (boost::format("%+4d, ") % static_cast<int>(i)*50-1000);
00358 }
00359 std::cerr << "\n";
00360 }
00361 std::cerr << "limit " << 0*50+300 << " - " << (selected_all.size1()-1)*50+300 << "\n";
00362 CArray<double, 3> prob = {{ 0.01, 0.03, 0.05 }};
00363 for (size_t pp=0; pp<prob.size(); ++pp) {
00364 std::cerr << "prob " << prob[pp] << "\n";
00365 for (int p=0; p<8; ++p)
00366 {
00367 std::cerr << "progress8 " << p << "\n ";
00368 for (size_t j=0; j<selected_all.size1(); ++j)
00369 {
00370 double sum = 0;
00371 for (size_t i=0; i<selected_all.size2(); ++i)
00372 sum += selected_all[j][i][p];
00373 size_t i=0
00374 for (double so_far = 0; i<selected_all.size2(); ++i) {
00375 so_far += selected_all[j][i][p];
00376 if (so_far > prob[pp]*sum)
00377 break;
00378 }
00379 std::cerr << (boost::format("%+4d, ") % static_cast<int>(i)*25-1000);
00380 }
00381 std::cerr << "\n";
00382 }
00383 }
00384 }
00385 } _reporter;
00386 }
00387 }
00388 #endif
00389
00390 void osl::rating::
00391 FeatureSet::generateLogProb(const NumEffectState& state, const RatingEnv& env,
00392 int limit, MoveLogProbVector& out, bool in_pv_or_all) const
00393 {
00394 RatedMoveVector score;
00395 generateRating(state, env, limit, score, in_pv_or_all);
00396 if (score.empty())
00397 return;
00398
00399 const int highest = score[0].rating();
00400 const int progress8 = env.progress.value()/2;
00401 for (size_t i=0; i<score.size(); ++i) {
00402 const int log_prob = make_prob(score[i].rating(), i, limit, highest, progress8, in_pv_or_all);
00403 #ifdef RATING_STAT2
00404 add_stat(limit, score[i].rating(), log_prob <= limit, progress8);
00405 #endif
00406 out.push_back(MoveLogProb(score[i].move(), log_prob));
00407 }
00408 }
00409
00410 const int max_score = 999, min_score = 0;
00411 static const osl::CArray<int, 10> score_to_depth_takeback = {{
00412 223, 204, 208, 190, 159, 137, 124, 110, 100, 89
00413 }};
00414 static const osl::CArray<int, 10> score_to_depth_seeplus = {{
00415 356, 337, 296, 262, 230, 200, 171, 148, 132, 120,
00416 }};
00417 static const osl::CArray<int, 10> score_to_depth_kingescape = {{
00418 203, 201, 199, 188, 181, 169, 159, 147, 136, 122,
00419 }};
00420
00421 int osl::rating::
00422 FeatureSet::logProbTakeBack(const NumEffectState& state, const RatingEnv& env, Move move) const
00423 {
00424 const bool in_check = state.inCheck();
00425 const int score = makeRate(state, in_check, env, move).rating();
00426 if (score >= 1000) {
00427 const int score_index = std::min((score - sc_start)/sc_width, sc_length-1);
00428 return score_to_depth[env.progress.value()/2][score_index];
00429 }
00430 return score_to_depth_takeback[std::max(min_score, std::min(max_score, score))/100];
00431 }
00432 int osl::rating::
00433 FeatureSet::logProbSeePlus(const NumEffectState& state, const RatingEnv& env,
00434 Move move) const
00435 {
00436 const bool in_check = state.inCheck();
00437 const int score = makeRate(state, in_check, env, move).rating();
00438 if (score >= 1000) {
00439 const int score_index = std::min((score - sc_start)/sc_width, sc_length-1);
00440 return score_to_depth[env.progress.value()/2][score_index];
00441 }
00442 return score_to_depth_seeplus[std::max(min_score, std::min(max_score, score))/100];
00443 }
00444 int osl::rating::
00445 FeatureSet::logProbKingEscape(const NumEffectState& state, const RatingEnv& env,
00446 Move move) const
00447 {
00448 const bool in_check = state.inCheck();
00449 const int score = makeRate(state, in_check, env, move).rating();
00450 if (score >= 1000) {
00451 const int score_index = std::min((score - sc_start)/sc_width, sc_length-1);
00452 return score_to_depth[env.progress.value()/2][score_index];
00453 }
00454 const int prob = score_to_depth_kingescape[std::max(min_score, std::min(max_score, score))/100];
00455 assert(prob > 0);
00456 return prob;
00457 }
00458
00459 int osl::rating::
00460 FeatureSet::rating(const NumEffectState& state,
00461 const RatingEnv& env, Move move, size_t group_id) const
00462 {
00463 int found = groups[group_id].findMatch(state, move, env);
00464 if (found < 0) {
00465 #ifdef RATING_STAT
00466 const int progress8 = env.progress.value()/2;
00467 frequency[group_id][progress8].add(0);
00468 variance_all[group_id].add(0);
00469 #endif
00470 return 0;
00471 }
00472 found += ranges[group_id].first;
00473 #ifdef RATING_STAT
00474 const int progress8 = env.progress.value()/2;
00475 frequency[group_id][progress8].add(1);
00476 variance_match[group_id][progress8].add(weightslog10[found]);
00477 variance_all[group_id].add(weightslog10[found]);
00478 #endif
00479 return weightslog10[found];
00480 }
00481
00482 const osl::rating::RatedMove osl::rating::
00483 FeatureSet::makeRate(const NumEffectState& state, bool in_check,
00484 const RatingEnv& env, Move move) const
00485 {
00486 int sum = 0;
00487 for (size_t j=0; j<groups.size(); ++j) {
00488 if (! normal_groups[j])
00489 continue;
00490 if (in_check && ! effectiveInCheck(j))
00491 continue;
00492 sum += rating(state, env, move, j);
00493 }
00494 int capture = 0;
00495 if (capture_group >= 0)
00496 capture = rating(state, env, move, capture_group);
00497 int checkmate_if_capture = 0;
00498 if (checkmate_if_capture_group >= 0)
00499 checkmate_if_capture = rating(state, env, move, checkmate_if_capture_group);
00500 sum += checkmate_if_capture;
00501 int sendoff = 0;
00502 if (sendoff_group >= 0)
00503 sendoff = rating(state, env, move, sendoff_group);
00504 sum += sendoff;
00505
00506 if (checkmate_if_capture > 0)
00507 capture = std::max(0, capture);
00508 else if (sendoff > 0 && capture < 0)
00509 capture /= 2;
00510 const int optimistic = sum + std::max(0, capture);
00511 sum += capture;
00512
00513 return RatedMove(move, sum, optimistic);
00514 }
00515
00516
00517
00518 #if 1
00519
00520 static const osl::CArray2d<int,8,16> threshold = {{
00521 {
00522 0, 0, 0, 0, 0, 0,
00523 100, 100, 50, 0, 0, -75,-100,-150,-200,-200,
00524 },
00525 {
00526 0, 0, 0, 0, 0, 0,
00527 125, 125, 125, 25, 25, -50, -50,-100,-125,-225,
00528 },
00529 {
00530 0, 0, 0, 0, 0, 0,
00531 100, 75, 100, 25, 0, -25, -50,-100,-125,-175,
00532 },
00533 {
00534 0, 0, 0, 0, 0, 0,
00535 75, 50, 75, 0, -25, -25, -75,-100,-125,-200,
00536 },
00537 {
00538 0, 0, 0, 0, 0, 0,
00539 125, 125, 150, 50, 50, 50, -25, 0, -50,-200,
00540 },
00541 {
00542 0, 0, 0, 0, 0, 0,
00543 175, 200, 200, 75, 75, 75, 0, 0,-175,-300,
00544 },
00545 {
00546 0, 0, 0, 0, 0, 0,
00547 175, 175, 200, 50, 75, 75, 25, 0,-100,-250,
00548 },
00549 {
00550 0, 0, 0, 0, 0, 0,
00551 225, 200, 225, 75, 100, 75, 50, 0, 0,-250,
00552 },
00553 }};
00554 #endif
00555 #if 0
00556 static const osl::CArray2d<int,8,16> threshold = {{
00557
00558 {
00559 0, 0, 0, 0, 0, 0,
00560 100,100,100,0,0,-100,-100,-200,-200,-200,
00561 },
00562 {
00563 0, 0, 0, 0, 0, 0,
00564 100,100,100,0,0,-100,-100,-100,-100,-200,
00565 },
00566 {
00567 0, 0, 0, 0, 0, 0,
00568 100,100,100,0,0,0,-100,-100,-100,-200
00569 },
00570 {
00571 0, 0, 0, 0, 0, 0,
00572 100,100,100,0,0,0,-100,-100,-100,-200
00573 },
00574 {
00575 0, 0, 0, 0, 0, 0,
00576 200,200,200,100,100,100,0,0,0,-100
00577 },
00578 {
00579 0, 0, 0, 0, 0, 0,
00580 300,300,300,100,100,100,100,0,-200,-300
00581 },
00582 {
00583 0, 0, 0, 0, 0, 0,
00584 300,300,300,100,100,100,100,0,0,-200
00585 },
00586 {
00587 0, 0, 0, 0, 0, 0,
00588 300,300,300,100,200,200,100,0,0,-200
00589 },
00590 }};
00591 #endif
00592 const osl::rating::RatedMove osl::rating::
00593 FeatureSet::makeRateWithCut(const NumEffectState& state,
00594 bool in_check,
00595 const RatingEnv& env,
00596 int limit, Move move) const
00597 {
00598 if (limit >= 800)
00599 return makeRate(state, in_check, env, move);
00600
00601 limit /= 50;
00602 int sum = 0;
00603 int capture = 0;
00604 int checkmate_if_capture = 0;
00605 const int progress8 = env.progress.value()/2;
00606 for (size_t j=0; j<groups.size(); ++j) {
00607 if (in_check && ! effectiveInCheck(j))
00608 continue;
00609 const int r = rating(state, env, move, j);
00610 sum += r;
00611 if ((int)j == capture_group) {
00612 capture = r;
00613 }
00614 else if ((int)j == checkmate_if_capture_group) {
00615 checkmate_if_capture = r;
00616 if (checkmate_if_capture > 0 && capture < 0) {
00617 sum -= capture;
00618 capture = 0;
00619 }
00620 }
00621
00622 if (j % 8 == 7) {
00623 int sigma = statistics[j].sigma_after;
00624 if (sum + statistics[j].average_after + sigma < threshold[progress8][limit]) {
00625 return RatedMove(move, MinRating, MinRating);
00626 }
00627 }
00628 }
00629
00630 const int optimistic = sum + std::max(0, capture);
00631 return RatedMove(move, sum, optimistic);
00632 }
00633
00634 const std::string osl::rating::
00635 FeatureSet::annotate(const NumEffectState& state,
00636 const RatingEnv& env, Move move) const
00637 {
00638 const bool in_check = state.inCheck();
00639 vector<std::pair<int, std::string> > values;
00640 for (size_t j=0; j<groups.size(); ++j) {
00641 if (in_check && ! effectiveInCheck(j))
00642 continue;
00643 int found = groups[j].findMatch(state, move, env);
00644 if (found < 0)
00645 continue;
00646 found += ranges[j].first;
00647 values.push_back(std::make_pair(weightslog10[found], groups[j].group_name));
00648 }
00649 std::sort(values.begin(), values.end());
00650 std::reverse(values.begin(), values.end());
00651 std::ostringstream ss;
00652 for (size_t i=0; i<values.size(); ++i) {
00653 if (i)
00654 ss << " ";
00655 ss << values[i].second << " " << values[i].first;
00656 }
00657 return ss.str();
00658 }
00659
00660 #ifndef MINIMAL
00661 void osl::rating::
00662 FeatureSet::showGroup(std::ostream& os, size_t group_id) const
00663 {
00664 os << std::setprecision(3);
00665 group(group_id).show(os, 12, range(group_id), weights);
00666 }
00667
00668 void osl::rating::
00669 FeatureSet::save(const std::string& output_directory, size_t group_id) const
00670 {
00671 group(group_id).saveResult(output_directory, range(group_id), weights);
00672 }
00673
00674 void osl::rating::
00675 FeatureSet::showStatistics(std::ostream& os) const
00676 {
00677 os << std::setprecision(3);
00678 for (size_t i=0; i<groups.size(); ++i) {
00679 os << groups[i].group_name << "\t";
00680 for (int p=0; p<8; ++p) {
00681 os << " " << variance_match[i][p].getAverage()
00682 << " " << sqrt(variance_match[i][p].variance())
00683 << " " << frequency[i][p].getAverage() << " ";
00684 }
00685 os << "\t" << variance_all[i].getAverage()
00686 << "\t" << sqrt(variance_all[i].variance())
00687 << "\n";
00688 }
00689 }
00690 #endif
00691
00692 std::string osl::rating::FeatureSet::defaultDirectory()
00693 {
00694 return OslConfig::home()+"/data/rating";
00695 }
00696
00697
00698
00699 osl::rating::
00700 StandardFeatureSet::StandardFeatureSet(bool allow_load_failure)
00701 {
00702 add(new CaptureGroup());
00703 add(new SquareYGroup());
00704 add(new RelativeKingXGroup(true));
00705 add(new SquareXGroup());
00706 add(new TakeBackGroup());
00707 add(new RelativeKingYGroup(true));
00708 add(new FromEffectGroup());
00709 add(new PatternGroup(U));
00710 add(new RelativeKingXGroup(false));
00711 add(new PatternGroup(D));
00712
00713 add(new PatternLongGroup(0));
00714 add(new CheckGroup());
00715 add(new BlockGroup());
00716 add(new PtypeAttackedGroup());
00717
00718 add(new PatternGroup(U,U));
00719 add(new ImmediateAddSupportGroup());
00720 add(new PatternGroup(DR));
00721 add(new RelativeKingYGroup(false));
00722 add(new DefenseKing8Group());
00723 add(new PatternGroup(L));
00724 add(new PatternGroup(UL));
00725
00726 add(new ToSupportedGroup());
00727
00728 add(new PatternGroup(UR));
00729 add(new PatternBlockGroup(ROOK));
00730 add(new AttackKing8Group());
00731 add(new PatternGroup(R));
00732 add(new PatternGroup(DL));
00733
00734 add(new PatternGroup(R,R));
00735 add(new PatternLongGroup(3));
00736 add(new PatternGroup(UUL));
00737 add(new PatternGroup(UUR));
00738 add(new PatternGroup(L,L));
00739
00740 add(new PatternLongGroup(2));
00741 add(new OpenGroup());
00742 add(new PatternBlockGroup(LANCE));
00743 add(new ChaseGroup());
00744 add(new PatternLongGroup(1));
00745 add(new PatternLongGroup2(1));
00746 add(new PatternBlockGroup(BISHOP));
00747 add(new PatternGroup(UR,R));
00748 add(new PatternLongGroup2(0));
00749 add(new PatternGroup(UL,L));
00750
00751 add(new ImmediateEscapeGroup());
00752 add(new PatternLongGroup2(3));
00753 add(new PatternLongGroup2(2));
00754 add(new KaranariGroup());
00755
00756 add(new BigramAttackGroup(true, true));
00757 add(new BigramAttackGroup(false, true));
00758 add(new BigramAttackGroup(true, false));
00759 add(new BigramAttackGroup(false, false));
00760
00761 add(new DropCapturedGroup());
00762 add(new ContinueCaptureGroup());
00763 add(new PawnAttackGroup());
00764 add(new ThreatmateGroup());
00765
00766 add(new BadLanceGroup());
00767 add(new CheckmateIfCaptureGroup());
00768 add(new RookDefense());
00769 add(new SendOffGroup());
00770
00771 add(new PinGroup());
00772 add(new KingEscapeGroup());
00773 add(new EscapePinGroup());
00774
00775 addFinished();
00776 bool success = tryLoad(defaultDirectory());
00777 if (! allow_load_failure && ! success) {
00778 std::cerr << "error: unable to load rating from " << defaultDirectory();
00779 throw std::runtime_error("load failed " + OslConfig::home()+defaultDirectory());
00780 }
00781 }
00782
00783
00784 const osl::rating::StandardFeatureSet& osl::rating::
00785 StandardFeatureSet::instance()
00786 {
00787 static osl::rating::StandardFeatureSet common_instance;
00788 return common_instance;
00789 }
00790
00791 bool osl::rating::StandardFeatureSet::healthCheck()
00792 {
00793 std::cerr << "loading " << defaultDirectory() << ' ';
00794 try {
00795 instance();
00796 std::cerr << "success\n";
00797 }
00798 catch (std::exception& e)
00799 {
00800 std::cerr << e.what() << "\n";
00801 return false;
00802 }
00803 catch (...) {
00804 std::cerr << "unknown exception\n";
00805 return false;
00806 }
00807 return true;
00808 }
00809
00810 osl::rating::
00811 CaptureSet::CaptureSet(bool allow_load_failure)
00812 {
00813 add(new CaptureGroup());
00814 add(new ShadowEffectGroup());
00815
00816 addFinished();
00817 bool success = tryLoad(defaultDirectory());
00818 if (! allow_load_failure && ! success) {
00819 std::cerr << "error: unable to load rating from " << defaultDirectory();
00820 throw std::runtime_error("load failed " + defaultDirectory());
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829