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