From 88ecc5a8adaabef13006744e3d8f67a534377163 Mon Sep 17 00:00:00 2001 From: Yuji Ichikawa Date: Mon, 14 Jun 2021 13:56:28 +0900 Subject: [PATCH 1/8] standard deviation of ownership --- cpp/search/search.h | 4 +++- cpp/search/searchresults.cpp | 23 +++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cpp/search/search.h b/cpp/search/search.h index 7807ea35a..4f114990d 100644 --- a/cpp/search/search.h +++ b/cpp/search/search.h @@ -467,6 +467,7 @@ struct Search { //or changing parameters or clearing search. //If node is not providied, defaults to using the root node. std::vector getAverageTreeOwnership(double minWeight, const SearchNode* node = NULL) const; + std::vector getStandardDeviationTreeOwnership(double minWeight, const std::vector ownership, const SearchNode* node = NULL) const; //Get ownership map as json nlohmann::json getJsonOwnershipMap(const Player pla, const Player perspective, const Board& board, const SearchNode* node, double ownershipMinWeight) const; @@ -649,7 +650,8 @@ struct Search { std::string& prefix, int64_t origVisits, int depth, const AnalysisData& data, Player perspective ) const; - double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const; + template + double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, F&& func, const SearchNode* node) const; }; diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index c16cc161c..185de5d6d 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1217,11 +1217,26 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod if(!alwaysIncludeOwnerMap) throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,node); + getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x) { return x; },node); return vec; } -double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const { +vector Search::getStandardDeviationTreeOwnership(double minWeight, const std::vector ownership, const SearchNode* node) const { + if(node == NULL) + node = rootNode; + if(!alwaysIncludeOwnerMap) + throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); + vector vec(nnXLen*nnYLen,0.0); + getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x) { return x * x; },node); + for(int pos = 0; pos +double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, F&& func, const SearchNode* node) const { if(node == NULL) return 0; @@ -1265,14 +1280,14 @@ double Search::getAverageTreeOwnershipHelper(vector& accum, double minWe const SearchNode* child = children[i].getIfAllocated(); assert(child != NULL); double desiredWeightFromChild = (double)childWeight * childWeight / relativeChildrenWeightSum * desiredWeightFromChildren; - actualWeightFromChildren += getAverageTreeOwnershipHelper(accum,minWeight,desiredWeightFromChild,child); + actualWeightFromChildren += getAverageTreeOwnershipHelper(accum,minWeight,desiredWeightFromChild,func,child); } double selfWeight = desiredWeight - actualWeightFromChildren; float* ownerMap = nnOutput->whiteOwnerMap; assert(ownerMap != NULL); for(int pos = 0; pos Date: Mon, 14 Jun 2021 14:11:54 +0900 Subject: [PATCH 2/8] clearer naming --- cpp/search/search.h | 4 ++-- cpp/search/searchresults.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/search/search.h b/cpp/search/search.h index 4f114990d..a7da80f96 100644 --- a/cpp/search/search.h +++ b/cpp/search/search.h @@ -650,8 +650,8 @@ struct Search { std::string& prefix, int64_t origVisits, int depth, const AnalysisData& data, Player perspective ) const; - template - double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, F&& func, const SearchNode* node) const; + template + double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, Func&& preprocess, const SearchNode* node) const; }; diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index 185de5d6d..aca055a61 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1235,8 +1235,8 @@ vector Search::getStandardDeviationTreeOwnership(double minWeight, const return vec; } -template -double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, F&& func, const SearchNode* node) const { +template +double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, Func&& preprocess, const SearchNode* node) const { if(node == NULL) return 0; @@ -1280,14 +1280,14 @@ double Search::getAverageTreeOwnershipHelper(vector& accum, double minWe const SearchNode* child = children[i].getIfAllocated(); assert(child != NULL); double desiredWeightFromChild = (double)childWeight * childWeight / relativeChildrenWeightSum * desiredWeightFromChildren; - actualWeightFromChildren += getAverageTreeOwnershipHelper(accum,minWeight,desiredWeightFromChild,func,child); + actualWeightFromChildren += getAverageTreeOwnershipHelper(accum,minWeight,desiredWeightFromChild,preprocess,child); } double selfWeight = desiredWeight - actualWeightFromChildren; float* ownerMap = nnOutput->whiteOwnerMap; assert(ownerMap != NULL); for(int pos = 0; pos Date: Mon, 14 Jun 2021 14:16:14 +0900 Subject: [PATCH 3/8] removed unnecessary check since it requires ownership as an argument --- cpp/search/searchresults.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index aca055a61..f5c51a87e 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1224,8 +1224,6 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod vector Search::getStandardDeviationTreeOwnership(double minWeight, const std::vector ownership, const SearchNode* node) const { if(node == NULL) node = rootNode; - if(!alwaysIncludeOwnerMap) - throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x) { return x * x; },node); for(int pos = 0; pos Date: Tue, 15 Jun 2021 09:51:42 +0900 Subject: [PATCH 4/8] calculated (x[i] - avg(x))^2 instead of avg(x[i]^2) since the latter has large error --- cpp/search/searchresults.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index f5c51a87e..22a37af24 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1217,7 +1217,7 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod if(!alwaysIncludeOwnerMap) throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x) { return x; },node); + getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x, int pos) { return x; },node); return vec; } @@ -1225,10 +1225,10 @@ vector Search::getStandardDeviationTreeOwnership(double minWeight, const if(node == NULL) node = rootNode; vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x) { return x * x; },node); + getAverageTreeOwnershipHelper(vec,minWeight,1.0,[&ownership](double x, int pos) { const double d = x - ownership[pos]; return d * d; },node); for(int pos = 0; pos= 0.0); + vec[pos] = sqrt(vec[pos]); } return vec; } @@ -1285,7 +1285,7 @@ double Search::getAverageTreeOwnershipHelper(vector& accum, double minWe float* ownerMap = nnOutput->whiteOwnerMap; assert(ownerMap != NULL); for(int pos = 0; pos Date: Wed, 16 Jun 2021 11:52:13 +0900 Subject: [PATCH 5/8] calculated average and squared average at the same time --- cpp/search/search.h | 6 +-- cpp/search/searchresults.cpp | 83 ++++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/cpp/search/search.h b/cpp/search/search.h index a7da80f96..0526b9899 100644 --- a/cpp/search/search.h +++ b/cpp/search/search.h @@ -467,7 +467,7 @@ struct Search { //or changing parameters or clearing search. //If node is not providied, defaults to using the root node. std::vector getAverageTreeOwnership(double minWeight, const SearchNode* node = NULL) const; - std::vector getStandardDeviationTreeOwnership(double minWeight, const std::vector ownership, const SearchNode* node = NULL) const; + std::tuple,std::vector> getAverageAndStandardDeviationTreeOwnership(double minWeight, const SearchNode* node = NULL) const; //Get ownership map as json nlohmann::json getJsonOwnershipMap(const Player pla, const Player perspective, const Board& board, const SearchNode* node, double ownershipMinWeight) const; @@ -650,8 +650,8 @@ struct Search { std::string& prefix, int64_t origVisits, int depth, const AnalysisData& data, Player perspective ) const; - template - double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, Func&& preprocess, const SearchNode* node) const; + double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const; + double getAverageAndStandardDeviationTreeOwnershipHelper(std::vector& average, std::vector& squaredAverage, double minWeight, double desiredWeight, const SearchNode* node) const; }; diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index 22a37af24..5df017997 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1217,24 +1217,80 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod if(!alwaysIncludeOwnerMap) throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,[](double x, int pos) { return x; },node); + getAverageTreeOwnershipHelper(vec,minWeight,1.0,node); return vec; } -vector Search::getStandardDeviationTreeOwnership(double minWeight, const std::vector ownership, const SearchNode* node) const { +double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const { + if(node == NULL) + return 0; + + const NNOutput* nnOutput = node->getNNOutput(); + if(nnOutput == NULL) + return 0; + + int childrenCapacity; + const SearchChildPointer* children = node->getChildren(childrenCapacity); + + vector childWeightBuf(childrenCapacity); + double thisNodeWeight = computeWeightFromNNOutput(nnOutput); + int numChildren = 0; + for(int i = 0; istats.weightSum.load(std::memory_order_acquire); + childWeightBuf[i] = childWeight; + numChildren += 1; + } + + double relativeChildrenWeightSum = 0.0; + double usedChildrenWeightSum = 0; + for(int i = 0; iwhiteOwnerMap; + assert(ownerMap != NULL); + for(int pos = 0; pos,vector> Search::getAverageAndStandardDeviationTreeOwnership(double minWeight, const SearchNode* node) const { if(node == NULL) node = rootNode; - vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,[&ownership](double x, int pos) { const double d = x - ownership[pos]; return d * d; },node); + vector average(nnXLen*nnYLen,0.0); + vector stdev(nnXLen*nnYLen,0.0); + getAverageAndStandardDeviationTreeOwnershipHelper(average,stdev,minWeight,1.0,node); for(int pos = 0; pos= 0.0); - vec[pos] = sqrt(vec[pos]); + const double avg = average[pos]; + stdev[pos] = sqrt(max(stdev[pos] - avg * avg, 0.0)); } - return vec; + return make_tuple(average, stdev); } -template -double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, Func&& preprocess, const SearchNode* node) const { +double Search::getAverageAndStandardDeviationTreeOwnershipHelper(vector& average, vector& squaredAverage, double minWeight, double desiredWeight, const SearchNode* node) const { if(node == NULL) return 0; @@ -1278,14 +1334,17 @@ double Search::getAverageTreeOwnershipHelper(vector& accum, double minWe const SearchNode* child = children[i].getIfAllocated(); assert(child != NULL); double desiredWeightFromChild = (double)childWeight * childWeight / relativeChildrenWeightSum * desiredWeightFromChildren; - actualWeightFromChildren += getAverageTreeOwnershipHelper(accum,minWeight,desiredWeightFromChild,preprocess,child); + actualWeightFromChildren += getAverageAndStandardDeviationTreeOwnershipHelper(average,squaredAverage,minWeight,desiredWeightFromChild,child); } double selfWeight = desiredWeight - actualWeightFromChildren; float* ownerMap = nnOutput->whiteOwnerMap; assert(ownerMap != NULL); - for(int pos = 0; pos Date: Wed, 16 Jun 2021 16:08:08 +0900 Subject: [PATCH 6/8] traverseTreeWithOwnershipAndSelfWeight instead of getAverageTreeOwnershipHelper and getAverageAndStandardDeviationTreeOwnershipHelper --- cpp/search/search.h | 4 +- cpp/search/searchresults.cpp | 77 ++++++------------------------------ 2 files changed, 14 insertions(+), 67 deletions(-) diff --git a/cpp/search/search.h b/cpp/search/search.h index 0526b9899..5c281f6a3 100644 --- a/cpp/search/search.h +++ b/cpp/search/search.h @@ -650,8 +650,8 @@ struct Search { std::string& prefix, int64_t origVisits, int depth, const AnalysisData& data, Player perspective ) const; - double getAverageTreeOwnershipHelper(std::vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const; - double getAverageAndStandardDeviationTreeOwnershipHelper(std::vector& average, std::vector& squaredAverage, double minWeight, double desiredWeight, const SearchNode* node) const; + template + double traverseTreeWithOwnershipAndSelfWeight(Func&& averaging, double minWeight, double desiredWeight, const SearchNode* node) const; }; diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index 5df017997..c5d104d35 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1217,72 +1217,21 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod if(!alwaysIncludeOwnerMap) throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); - getAverageTreeOwnershipHelper(vec,minWeight,1.0,node); + traverseTreeWithOwnershipAndSelfWeight([&vec](int pos, double ownership, double selfWeight) { + vec[pos] += selfWeight * ownership; + },minWeight,1.0,node); return vec; } -double Search::getAverageTreeOwnershipHelper(vector& accum, double minWeight, double desiredWeight, const SearchNode* node) const { - if(node == NULL) - return 0; - - const NNOutput* nnOutput = node->getNNOutput(); - if(nnOutput == NULL) - return 0; - - int childrenCapacity; - const SearchChildPointer* children = node->getChildren(childrenCapacity); - - vector childWeightBuf(childrenCapacity); - double thisNodeWeight = computeWeightFromNNOutput(nnOutput); - int numChildren = 0; - for(int i = 0; istats.weightSum.load(std::memory_order_acquire); - childWeightBuf[i] = childWeight; - numChildren += 1; - } - - double relativeChildrenWeightSum = 0.0; - double usedChildrenWeightSum = 0; - for(int i = 0; iwhiteOwnerMap; - assert(ownerMap != NULL); - for(int pos = 0; pos,vector> Search::getAverageAndStandardDeviationTreeOwnership(double minWeight, const SearchNode* node) const { if(node == NULL) node = rootNode; vector average(nnXLen*nnYLen,0.0); vector stdev(nnXLen*nnYLen,0.0); - getAverageAndStandardDeviationTreeOwnershipHelper(average,stdev,minWeight,1.0,node); + traverseTreeWithOwnershipAndSelfWeight([&average,&stdev](int pos, double ownership, double selfWeight) { + average[pos] += selfWeight * ownership; + stdev[pos] += selfWeight * ownership * ownership; + },minWeight,1.0,node); for(int pos = 0; pos,vector> Search::getAverageAndStandardDeviationTreeO return make_tuple(average, stdev); } -double Search::getAverageAndStandardDeviationTreeOwnershipHelper(vector& average, vector& squaredAverage, double minWeight, double desiredWeight, const SearchNode* node) const { +template +double Search::traverseTreeWithOwnershipAndSelfWeight(Func&& averaging, double minWeight, double desiredWeight, const SearchNode* node) const { if(node == NULL) return 0; @@ -1334,17 +1284,14 @@ double Search::getAverageAndStandardDeviationTreeOwnershipHelper(vector& const SearchNode* child = children[i].getIfAllocated(); assert(child != NULL); double desiredWeightFromChild = (double)childWeight * childWeight / relativeChildrenWeightSum * desiredWeightFromChildren; - actualWeightFromChildren += getAverageAndStandardDeviationTreeOwnershipHelper(average,squaredAverage,minWeight,desiredWeightFromChild,child); + actualWeightFromChildren += traverseTreeWithOwnershipAndSelfWeight(averaging,minWeight,desiredWeightFromChild,child); } double selfWeight = desiredWeight - actualWeightFromChildren; float* ownerMap = nnOutput->whiteOwnerMap; assert(ownerMap != NULL); - for(int pos = 0; pos Date: Fri, 30 Jul 2021 21:48:54 +0900 Subject: [PATCH 7/8] Support output of ownershipStdev in kata-analyze * input: `kata-analyze ... ownership true ownershipStdev true` * output: `info ... info ... ownership ... ownershipStdev ...` --- cpp/command/gtp.cpp | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/cpp/command/gtp.cpp b/cpp/command/gtp.cpp index 3feb0c72b..9b0b11cdb 100644 --- a/cpp/command/gtp.cpp +++ b/cpp/command/gtp.cpp @@ -626,6 +626,7 @@ struct GTPEngine { int minMoves = 0; int maxMoves = 10000000; bool showOwnership = false; + bool showOwnershipStdev = false; bool showPVVisits = false; double secondsPerReport = TimeControls::UNLIMITED_TIME_DEFAULT; vector avoidMoveUntilByLocBlack; @@ -690,8 +691,15 @@ struct GTPEngine { if(buf.size() <= 0) return; - vector ownership; - if(args.showOwnership) { + vector ownership, ownershipStdev; + if(args.showOwnershipStdev) { + static constexpr int64_t ownershipStdevMinVisits = 3; + tuple,vector> ownershipAverageAndStdev; + ownershipAverageAndStdev = search->getAverageAndStandardDeviationTreeOwnership(ownershipStdevMinVisits); + ownership = std::get<0>(ownershipAverageAndStdev); + ownershipStdev = std::get<1>(ownershipAverageAndStdev); + } + else if(args.showOwnership) { static constexpr int64_t ownershipMinVisits = 3; ownership = search->getAverageTreeOwnership(ownershipMinVisits); } @@ -767,6 +775,19 @@ struct GTPEngine { } } + if(args.showOwnershipStdev) { + out << " "; + + out << "ownershipStdev"; + int nnXLen = search->nnXLen; + for(int y = 0; ysetAvoidMoveUntilByLoc(args.avoidMoveUntilByLocBlack,args.avoidMoveUntilByLocWhite); if(args.analyzing) { std::function callback = getAnalyzeCallback(pla,args); - if(args.showOwnership) + if(args.showOwnership || args.showOwnershipStdev) bot->setAlwaysIncludeOwnerMap(true); else bot->setAlwaysIncludeOwnerMap(false); @@ -1068,7 +1089,7 @@ struct GTPEngine { std::function callback = getAnalyzeCallback(pla,args); bot->setAvoidMoveUntilByLoc(args.avoidMoveUntilByLocBlack,args.avoidMoveUntilByLocWhite); - if(args.showOwnership) + if(args.showOwnership || args.showOwnershipStdev) bot->setAlwaysIncludeOwnerMap(true); else bot->setAlwaysIncludeOwnerMap(false); @@ -1261,6 +1282,7 @@ static GTPEngine::AnalyzeArgs parseAnalyzeCommand( int minMoves = 0; int maxMoves = 10000000; bool showOwnership = false; + bool showOwnershipStdev = false; bool showPVVisits = false; vector avoidMoveUntilByLocBlack; vector avoidMoveUntilByLocWhite; @@ -1280,6 +1302,7 @@ static GTPEngine::AnalyzeArgs parseAnalyzeCommand( //minmoves //maxmoves //ownership + //ownershipStdev //pvVisits //Parse optional player @@ -1382,6 +1405,9 @@ static GTPEngine::AnalyzeArgs parseAnalyzeCommand( else if(isKata && key == "ownership" && Global::tryStringToBool(value,showOwnership)) { continue; } + else if(isKata && key == "ownershipStdev" && Global::tryStringToBool(value,showOwnershipStdev)) { + continue; + } else if(isKata && key == "pvVisits" && Global::tryStringToBool(value,showPVVisits)) { continue; } @@ -1399,6 +1425,7 @@ static GTPEngine::AnalyzeArgs parseAnalyzeCommand( args.minMoves = minMoves; args.maxMoves = maxMoves; args.showOwnership = showOwnership; + args.showOwnershipStdev = showOwnershipStdev; args.showPVVisits = showPVVisits; args.avoidMoveUntilByLocBlack = avoidMoveUntilByLocBlack; args.avoidMoveUntilByLocWhite = avoidMoveUntilByLocWhite; From b32bb23d51c5a699170c66dae46a65b9529d34c3 Mon Sep 17 00:00:00 2001 From: y-ich Date: Sat, 31 Jul 2021 17:04:28 +0900 Subject: [PATCH 8/8] optimized --- cpp/search/search.h | 2 ++ cpp/search/searchresults.cpp | 43 ++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/cpp/search/search.h b/cpp/search/search.h index 5c281f6a3..1b96d14f7 100644 --- a/cpp/search/search.h +++ b/cpp/search/search.h @@ -652,6 +652,8 @@ struct Search { template double traverseTreeWithOwnershipAndSelfWeight(Func&& averaging, double minWeight, double desiredWeight, const SearchNode* node) const; + template + double traverseTreeWithOwnershipAndSelfWeightHeler(Func&& averaging, double minWeight, double desiredWeight, double thisNodeWeight, const SearchChildPointer* children, double* childWeightBuf, int childrenCapacity) const; }; diff --git a/cpp/search/searchresults.cpp b/cpp/search/searchresults.cpp index c5d104d35..84e8e8783 100644 --- a/cpp/search/searchresults.cpp +++ b/cpp/search/searchresults.cpp @@ -1217,8 +1217,9 @@ vector Search::getAverageTreeOwnership(double minWeight, const SearchNod if(!alwaysIncludeOwnerMap) throw StringError("Called Search::getAverageTreeOwnership when alwaysIncludeOwnerMap is false"); vector vec(nnXLen*nnYLen,0.0); - traverseTreeWithOwnershipAndSelfWeight([&vec](int pos, double ownership, double selfWeight) { - vec[pos] += selfWeight * ownership; + traverseTreeWithOwnershipAndSelfWeight([&vec,this](float* ownership, double selfWeight){ + for (int pos = 0; pos < nnXLen*nnYLen; pos++) + vec[pos] += selfWeight * ownership[pos]; },minWeight,1.0,node); return vec; } @@ -1228,9 +1229,12 @@ tuple,vector> Search::getAverageAndStandardDeviationTreeO node = rootNode; vector average(nnXLen*nnYLen,0.0); vector stdev(nnXLen*nnYLen,0.0); - traverseTreeWithOwnershipAndSelfWeight([&average,&stdev](int pos, double ownership, double selfWeight) { - average[pos] += selfWeight * ownership; - stdev[pos] += selfWeight * ownership * ownership; + traverseTreeWithOwnershipAndSelfWeight([&average,&stdev,this](float* ownership, double selfWeight) { + for (int pos = 0; pos < nnXLen*nnYLen; pos++) { + const double value = ownership[pos]; + average[pos] += selfWeight * value; + stdev[pos] += selfWeight * value * value; + } },minWeight,1.0,node); for(int pos = 0; posgetChildren(childrenCapacity); - vector childWeightBuf(childrenCapacity); + double actualWeightFromChildren; double thisNodeWeight = computeWeightFromNNOutput(nnOutput); + if (childrenCapacity <= 8) { + double childWeightBuf[8]; + actualWeightFromChildren = traverseTreeWithOwnershipAndSelfWeightHeler(averaging, minWeight, desiredWeight, thisNodeWeight, children, childWeightBuf, childrenCapacity); + } else { + vector childWeightBuf(childrenCapacity); + actualWeightFromChildren = traverseTreeWithOwnershipAndSelfWeightHeler(averaging, minWeight, desiredWeight, thisNodeWeight, children, &childWeightBuf[0], childrenCapacity); + } + + double selfWeight = desiredWeight - actualWeightFromChildren; + float* ownerMap = nnOutput->whiteOwnerMap; + assert(ownerMap != NULL); + averaging(ownerMap, selfWeight); + return desiredWeight; +} + +template +double Search::traverseTreeWithOwnershipAndSelfWeightHeler(Func&& averaging, double minWeight, double desiredWeight, double thisNodeWeight, const SearchChildPointer* children, double* childWeightBuf, int childrenCapacity) const { int numChildren = 0; for(int i = 0; iwhiteOwnerMap; - assert(ownerMap != NULL); - for(int pos = 0; pos