bradleyTerry.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
bradleyTerry.cc
Go to the documentation of this file.
1 /* bradleyTerry.cc
2 */
3 #include "osl/rating/bradleyTerry.h"
4 #include "osl/rating/group.h"
5 #include "osl/checkmate/immediateCheckmate.h"
6 #include "osl/move_generator/legalMoves.h"
7 #include "osl/record/kisen.h"
8 #include "osl/container/moveVector.h"
9
10 #include <boost/thread/thread.hpp>
11 #include <iostream>
12 #include <iomanip>
13
14 #ifndef MINIMAL
15 osl::rating::
16 BradleyTerry::BradleyTerry(FeatureSet& f, const std::string& kisen_file, int kisen_start)
17 : features(f), kisen_filename(kisen_file), kisen_start(kisen_start), num_cpus(1), num_records(200),
18 verbose(1), fix_group(-1), min_rating(0)
19 {
20 }
21
22 osl::rating::BradleyTerry::~BradleyTerry()
23 {
24 }
25
26 bool osl::rating::
27 BradleyTerry::addSquare(size_t g, const NumEffectState& state,
28 const RatingEnv& env, Move selected,
29 valarray_t& wins, std::valarray<long double>& denominator) const
30 {
31 MoveVector moves;
32 LegalMoves::generate(state, moves);
33 if (! moves.isMember(selected))
34 return false; // checkmate or illegal move
35 const range_t range = features.range(g);
36 #ifdef SPEEDUP_TEST
37 const bool in_check = EffectUtil::isKingInCheck(state.turn(), state);
38 if (! in_check || features.effectiveInCheck(g))
39 #endif
40 {
41 int found = features.group(g).findMatch(state, selected, env);
42 if (found >= 0)
43 ++wins[found+range.first];
44 }
45 valarray_t sum_c(0.0, range.second-range.first);
46 long double sum_e = 0.0;
47 for (size_t i=0; i<moves.size(); ++i) {
48 Move m = moves[i];
49 double product = 1.0;
50 int count = 0;
51 int match_id = -1;
52 for (size_t j=0; j<features.groupSize(); ++j) {
53 #ifdef SPEEDUP_TEST
54 if (in_check && ! features.effectiveInCheck(j))
55 continue;
56 #endif
57 int found = features.group(j).findMatch(state, m, env);
58 if (found < 0)
59 continue;
60 found += features.range(j).first;
61 product *= features.weight(found);
62 ++count;
63 if (j == g) {
64 assert(range.first <= found && found < range.second);
65 match_id = found;
66 }
67 }
68 assert(count);
69 sum_e += product;
70 if (match_id >= 0)
71 sum_c[match_id-range.first] += product / features.weight(match_id);
72 }
73 assert(sum_e > 0);
74 for (int f=range.first; f<range.second; ++f)
75 denominator[f] += sum_c[f-range.first]/sum_e;
76 return true;
77 }
78
79 class osl::rating::
80 BradleyTerry::Thread
81 {
82 public:
83 const BradleyTerry *features;
84 size_t target;
85 size_t first, last;
86 valarray_t *wins;
87 std::valarray<long double> *denominator;
88 size_t *skip;
89 Thread(const BradleyTerry *a, size_t t, size_t f, size_t l, valarray_t *w, std::valarray<long double> *d,
90 size_t *s)
91 : features(a), target(t), first(f), last(l), wins(w), denominator(d), skip(s)
92 {
93 }
94 void operator()()
95 {
96 *skip = features->accumulate(target, first, last, *wins, *denominator);
97 }
98 };
99
100 size_t osl::rating::
101 BradleyTerry::accumulate(size_t g, size_t first, size_t last, valarray_t& wins, std::valarray<long double>& denominator) const
102 {
103 assert(wins.size() == features.featureSize());
104 KisenFile kisen_file(kisen_filename.c_str());
105 KisenIpxFile ipx(KisenFile::ipxFileName(kisen_filename));
106 size_t skip = 0;
107 for (size_t i=first; i<last; i++) {
108 if ((i % 4000) == 0)
109 std::cerr << ".";
110 if (ipx.getRating(i, BLACK) < min_rating
111 || ipx.getRating(i, WHITE) < min_rating) {
112 ++skip;
113 continue;
114 }
115 NumEffectState state(kisen_file.getInitialState());
116 RatingEnv env;
117 env.make(state);
118 const vector<Move> moves=kisen_file.getMoves(i+kisen_start);
119 for (size_t j=0; j<moves.size(); j++) {
120 if (j<2)
121 goto next;
122 {
123 const Player turn = state.turn();
124 if (! state.inCheck()
125 && ImmediateCheckmate::hasCheckmateMove(turn, state))
126 break;
127 }
128 if (! addSquare(g, state, env, moves[j], wins, denominator))
129 break;
130 next:
131 state.makeMove(moves[j]);
132 env.update(state, moves[j]);
133 }
134 }
135 return skip;
136 }
137
138 void osl::rating::
139 BradleyTerry::update(size_t g)
140 {
141 std::valarray<valarray_t> wins(valarray_t(0.0, features.featureSize()), num_cpus);
142 std::valarray<std::valarray<long double> > denominator(std::valarray<long double>(0.0, features.featureSize()), num_cpus);
143 assert(wins.size() == num_cpus);
144
145 KisenFile kisen_file(kisen_filename.c_str());
146 if (num_records==0)
147 num_records=kisen_file.size();
148 if (num_cpus == 1) {
149 accumulate(g, 0, num_records, wins[0], denominator[0]);
150 }
151 else {
152 size_t cur = 0;
153 size_t last = num_records, step = (last - cur)/num_cpus;
154 boost::ptr_vector<boost::thread> threads;
155 std::valarray<size_t> skip((size_t)0, num_cpus);
156 for (size_t i=0; i<num_cpus; ++i, cur += step) {
157 size_t next = (i+1 == num_cpus) ? last : cur + step;
158 threads.push_back(new boost::thread(Thread(this, g, cur, next, &wins[i], &denominator[i], &skip[i])));
159 }
160 for (size_t i=0; i<num_cpus; ++i)
161 threads[i].join();
162 if (g == 0)
163 std::cerr << "skip " << skip.sum() << " / " << num_records << "\n";
164 }
165 const range_t range = features.range(g);
166 for (int f=range.first; f<range.second; ++f) {
167 const int NPRIOR = 10; // assume NPRIOR wins, NPRIOR losses
168 double sum_win = NPRIOR;
169 long double sum_denom = (1.0 / (features.weight(f) + 1.0)) * 2 * NPRIOR;
170 for (size_t i=0; i<num_cpus; ++i) {
171 sum_win += wins[i][f];
172 sum_denom += denominator[i][f];
173 }
174 #ifdef DEBUG
175 std::cerr << " " << std::setw(14) << features.feature(f).name()
176 << " " << features.weight(f) << " => " << sum_win/sum_denom
177 << " " << sum_win << " / " << sum_denom
178 << " " << 400*log10(sum_win/sum_denom) << "\n";
179 #endif
180 // update
181 if (sum_denom)
182 features.setWeight(f, sum_win/sum_denom);
183 assert(! std::isinf(features.weight(f)));
184 assert(! std::isnan(features.weight(f)));
185 }
186
187 features.showGroup(std::cerr, g);
188 }
189
190 void osl::rating::
191 BradleyTerry::iterate()
192 {
193 for (int j=0; j<16; ++j) {
194 std::cerr << "\nnew iteration " << j << "\n";
195 for (size_t i=0; i<features.groupSize(); ++i) {
196 update(i);
197 features.save(output_directory, i);
198 if ((int)(i+1) == fix_group)
199 break;
200 }
201 }
202 }
203 #endif
204 /* ------------------------------------------------------------------------- */
205 // ;;; Local Variables:
206 // ;;; mode:c++
207 // ;;; c-basic-offset:2
208 // ;;; End: