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