00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <cmath>
00029
00030 #include "Hex.hpp"
00031 #include "BitsetIterator.hpp"
00032 #include "VCSet.hpp"
00033 #include "Resistance.hpp"
00034 #include "Pattern.hpp"
00035 #include "HashedPatternSet.hpp"
00036
00037 #include "lssolve.h"
00038
00039 using namespace benzene;
00040
00041
00042
00043 Resistance::Resistance()
00044 : m_score(0),
00045 m_simulate_and_over_edge(false)
00046 {
00047 }
00048
00049 Resistance::~Resistance()
00050 {
00051 }
00052
00053
00054
00055 void Resistance::Evaluate(const HexBoard& brd)
00056 {
00057 AdjacencyGraph graph[BLACK_AND_WHITE];
00058 ResistanceUtil::AddAdjacencies(brd, graph);
00059 Evaluate(brd, graph);
00060 }
00061
00062 void Resistance::Evaluate(const HexBoard& brd,
00063 AdjacencyGraph graph[BLACK_AND_WHITE])
00064 {
00065 ConductanceValues values;
00066
00067
00068 if (m_simulate_and_over_edge)
00069 ResistanceUtil::SimulateAndOverEdge(brd, graph);
00070
00071 for (BWIterator c; c; ++c)
00072 ComputeScores(*c, brd.GetGroups(), graph[*c], values, m_scores[*c]);
00073 ComputeScore();
00074 }
00075
00076 void Resistance::Evaluate(const Groups& groups,
00077 AdjacencyGraph graph[BLACK_AND_WHITE])
00078 {
00079 ConductanceValues values;
00080 for (BWIterator c; c; ++c)
00081 ComputeScores(*c, groups, graph[*c], values, m_scores[*c]);
00082 ComputeScore();
00083 }
00084
00085
00086
00087 namespace
00088 {
00089
00090 void SetAllToInfinity(const StoneBoard& brd, HexEval* out)
00091 {
00092 for (BoardIterator it(brd.Const().Interior()); it; ++it)
00093 out[*it] = EVAL_INFINITY;
00094 }
00095
00096
00097
00098 double Conductance(const StoneBoard& brd, HexColor color,
00099 HexPoint a, HexPoint b, bool connected,
00100 const ConductanceValues& values)
00101 {
00102 if (!connected)
00103 return values.no_connection;
00104
00105 HexColor ac = brd.GetColor(a);
00106 HexColor bc = brd.GetColor(b);
00107
00108 if (ac == EMPTY && bc == EMPTY)
00109 return values.empty_to_empty;
00110
00111 if (ac == color && bc == color)
00112 return values.color_to_color;
00113
00114 return values.color_to_empty;
00115 }
00116 }
00117
00118 void Resistance::ComputeScores(HexColor color, const Groups& groups,
00119 const AdjacencyGraph& graph,
00120 const ConductanceValues& values,
00121 HexEval* out)
00122 {
00123 const StoneBoard& brd = groups.Board();
00124 SetAllToInfinity(brd, out);
00125
00126 const HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(color);
00127 const HexPoint source = HexPointUtil::colorEdge1(color);
00128 const HexPoint sink = HexPointUtil::colorEdge2(color);
00129 const int n = groups.NumGroups(not_other) - 1;
00130
00131
00132 int pointToIndex[BITSETSIZE];
00133 HexPoint indexToPoint[BITSETSIZE];
00134 {
00135 int index = 0;
00136 for (GroupIterator i(groups, not_other); i; ++i)
00137 {
00138 if (i->Captain() == sink)
00139 continue;
00140 pointToIndex[i->Captain()] = index;
00141 indexToPoint[index] = i->Captain();
00142 index++;
00143 }
00144 }
00145
00146
00147 Mat<double> G(n, n);
00148 std::vector<double> sinkG(n, 0.0);
00149 G = 0.0;
00150 for (int i = 0; i < n; ++i)
00151 {
00152 HexPoint ip = indexToPoint[i];
00153 for (int j = 0; j < i; ++j)
00154 {
00155 HexPoint jp = indexToPoint[j];
00156 double c = Conductance(brd, color, ip, jp, graph[ip][jp], values);
00157 G(i, i) += c;
00158 G(j, j) += c;
00159 G(i, j) -= c;
00160 G(j, i) -= c;
00161 }
00162 double c = Conductance(brd, color, ip, sink, graph[ip][sink], values);
00163 G(i, i) += c;
00164 sinkG[i] += c;
00165 }
00166
00167
00168 Vec<double> I(n);
00169 I = 0.0;
00170 I[pointToIndex[source]] = 1.0;
00171
00172
00173 const Vec<double>& V = lsSolve(G, I);
00174 m_resistance[color] = fabs(V[pointToIndex[source]]);
00175
00176
00177 for (int i = 0; i < n; ++i)
00178 {
00179 double sum = fabs(sinkG[i] * V[i]);
00180 for (int j = 0; j < n; ++j)
00181 sum += fabs(G(i,j) * (V[i] - V[j]));
00182 out[indexToPoint[i]] = sum;
00183 }
00184 }
00185
00186 void Resistance::ComputeScore()
00187 {
00188 double r = m_resistance[WHITE] / m_resistance[BLACK];
00189 m_score = log(r);
00190 }
00191
00192 double Resistance::Resist(HexColor color) const
00193 {
00194 return log(m_resistance[color]);
00195 }
00196
00197
00198
00199
00200 namespace
00201 {
00202
00203
00204 void AddAdjacent(HexColor color, const HexBoard& brd,
00205 AdjacencyGraph& graph)
00206 {
00207 HexColorSet not_other = HexColorSetUtil::ColorOrEmpty(color);
00208 for (BoardIterator x(brd.GetPosition().Stones(not_other)); x; ++x)
00209 {
00210 for (BoardIterator y(brd.GetPosition().Stones(not_other)); *y != *x; ++y)
00211 {
00212 HexPoint cx = brd.GetGroups().CaptainOf(*x);
00213 HexPoint cy = brd.GetGroups().CaptainOf(*y);
00214 if ((cx==cy) || brd.Cons(color).Exists(cx, cy, VC::FULL))
00215 {
00216 graph[*x][*y] = true;
00217 graph[*y][*x] = true;
00218 }
00219 }
00220 }
00221 }
00222
00223 bool g_ResistanceUtilInitialized = false;
00224
00225 PatternSet s_capmiai[BLACK_AND_WHITE];
00226 HashedPatternSet* s_hash_capmiai[BLACK_AND_WHITE];
00227
00228 void InitializeCapMiai()
00229 {
00230 if (g_ResistanceUtilInitialized) return;
00231
00232 LogFine() << "--InitializeCapMiai" << '\n';
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 std::string capmiai = "m:0,0,0,0,0;0,0,0,0,0;0,0,0,0,0;0,0,0,0,0;7,6,0,4,0;3,2,0,0,0;1";
00243
00244 Pattern pattern;
00245 if (!pattern.unserialize(capmiai)) {
00246 HexAssert(false);
00247 }
00248 pattern.setName("capmiai");
00249
00250 s_capmiai[BLACK].push_back(pattern);
00251 s_hash_capmiai[BLACK] = new HashedPatternSet();
00252 s_hash_capmiai[BLACK]->hash(s_capmiai[BLACK]);
00253
00254 pattern.flipColors();
00255 s_capmiai[WHITE].push_back(pattern);
00256 s_hash_capmiai[WHITE] = new HashedPatternSet();
00257 s_hash_capmiai[WHITE]->hash(s_capmiai[WHITE]);
00258 }
00259
00260
00261
00262
00263
00264 void SimulateAndOverEdge1(const HexBoard& brd, HexColor color,
00265 HexPoint edge, AdjacencyGraph& graph)
00266 {
00267 bitset_t augment = brd.GetGroups().Nbs(edge, EMPTY);
00268
00269
00270 HexAssert(g_ResistanceUtilInitialized);
00271
00272 bitset_t adjToEdge;
00273 for (BitsetIterator p(brd.GetPosition().GetEmpty()); p; ++p)
00274 {
00275 PatternHits hits;
00276 brd.GetPatternState().MatchOnCell(*s_hash_capmiai[color], *p,
00277 PatternState::MATCH_ALL, hits);
00278 for (unsigned j=0; j<hits.size(); ++j)
00279 {
00280 HexPoint cj = brd.GetGroups().CaptainOf(hits[j].moves1()[0]);
00281 if (cj == edge)
00282 {
00283 augment.set(*p);
00284 break;
00285 }
00286 }
00287 }
00288
00289
00290 for (BitsetIterator p(augment); p; ++p) {
00291 for (BoardIterator q(brd.Const().EdgesAndInterior()); q; ++q) {
00292 graph[*p][*q] = graph[*p][*q] || graph[edge][*q];
00293 graph[*q][*p] = graph[*q][*p] || graph[edge][*q];
00294 }
00295 }
00296 }
00297
00298 }
00299
00300 void ResistanceUtil::Initialize()
00301 {
00302 InitializeCapMiai();
00303 g_ResistanceUtilInitialized = true;
00304 }
00305
00306 void ResistanceUtil::AddAdjacencies(const HexBoard& brd,
00307 AdjacencyGraph graph[BLACK_AND_WHITE])
00308 {
00309 for (BWIterator c; c; ++c)
00310 AddAdjacent(*c, brd, graph[*c]);
00311 }
00312
00313 void ResistanceUtil::SimulateAndOverEdge(const HexBoard& brd,
00314 AdjacencyGraph g[BLACK_AND_WHITE])
00315 {
00316 if (brd.Builder().Parameters().and_over_edge)
00317 {
00318 LogWarning()
00319 << "**** Simulating and-over-edge "
00320 << "while vcs are computed over edge!! ****"
00321 << '\n';
00322 }
00323
00324 SimulateAndOverEdge1(brd,BLACK, HexPointUtil::colorEdge1(BLACK), g[BLACK]);
00325 SimulateAndOverEdge1(brd,BLACK, HexPointUtil::colorEdge2(BLACK), g[BLACK]);
00326 SimulateAndOverEdge1(brd,WHITE, HexPointUtil::colorEdge1(WHITE), g[WHITE]);
00327 SimulateAndOverEdge1(brd,WHITE, HexPointUtil::colorEdge2(WHITE), g[WHITE]);
00328 }
00329
00330