Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpp/command/runtests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ int MainCmds::runtests(const vector<string>& args) {
Tests::runBoardStressTest();

Tests::runSgfTests();
Tests::runTrainingDataEndTests();
Tests::runBasicSymmetryTests();
Tests::runBoardSymmetryTests();
Tests::runSymmetryDifferenceTests();
Expand Down
52 changes: 44 additions & 8 deletions cpp/command/writetrainingdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,54 @@
#include "../program/play.h"
#include "../command/commandline.h"
#include "../core/test.h"
#include "../tests/tests.h"
#include "../main.h"

#include <chrono>
#include <csignal>

using namespace std;

// Keep this ownership gate independent of NN evaluation so its thresholds can be tested directly.
static bool isNearEndByOwnership(
int boardArea, int blackWhiteVeryDifferent, int blackCountUnsettled, int whiteCountUnsettled
) {
// count / boardArea < 0.10 + 6.0 / boardArea, compared exactly for positive board areas.
// Widen before scaling to avoid both integer truncation and floating-point boundary drift.
const int64_t maxScaledUnsettled = (int64_t)boardArea + 60;
return
10LL * blackWhiteVeryDifferent < maxScaledUnsettled
&& 10LL * blackCountUnsettled < maxScaledUnsettled
&& 10LL * whiteCountUnsettled < maxScaledUnsettled;
}

void Tests::runTrainingDataEndTests() {
cout << "Running scored-game near-end ownership tests" << endl;
struct TestCase {
int xSize;
int ySize;
int lastAllowedCount;
};
// Rectangles exercise exact thresholds that the fractional comparison can round upward.
// 10x10 also checks the strict comparison at the exact 16-point threshold.
const TestCase cases[] = {
{5,6,8}, {9,9,14}, {9,10,14}, {10,10,15}, {10,12,17},
{10,19,24}, {13,13,22}, {14,15,26}, {15,18,32}, {19,19,42}
};
for(const TestCase& testCase: cases) {
int boardArea = testCase.xSize * testCase.ySize;
// Sweep zero, both sides of the threshold, half the board, and the full board.
// Each counter must reject independently, even when the other two are zero.
for(int count = 0; count <= boardArea; count++) {
bool expected = count <= testCase.lastAllowedCount;
testAssert(isNearEndByOwnership(boardArea,count,0,0) == expected);
testAssert(isNearEndByOwnership(boardArea,0,count,0) == expected);
testAssert(isNearEndByOwnership(boardArea,0,0,count) == expected);
testAssert(isNearEndByOwnership(boardArea,count,count,count) == expected);
}
}
}

static ValueTargets makeForcedWinnerValueTarget(Player winner) {
ValueTargets targets;
if(winner == C_EMPTY) {
Expand Down Expand Up @@ -2028,7 +2069,6 @@ int MainCmds::writetrainingdata(const vector<string>& args) {
double winlossDiff = abs(valuesIfBlackFirst.winLossValue - valuesIfWhiteFirst.winLossValue);
// Remaining difference between side to move is less than 4 pointsish, and the winrate is close
if(leadDiff < 3.5 + 0.05 * absAvgLead && winlossDiff < 0.2) {
const double maxFractionOfBoardUnsettled = 0.10 + 6.0 / boardArea;
int blackCountUnsettled = 0;
int whiteCountUnsettled = 0;
int blackWhiteVeryDifferent = 0;
Expand All @@ -2043,13 +2083,9 @@ int MainCmds::writetrainingdata(const vector<string>& args) {
blackWhiteVeryDifferent += 1;
}
}
if(
blackWhiteVeryDifferent / boardArea < maxFractionOfBoardUnsettled
&& blackCountUnsettled / boardArea < maxFractionOfBoardUnsettled
&& whiteCountUnsettled / boardArea < maxFractionOfBoardUnsettled
) {
gameIsNearEnd = true;
}
gameIsNearEnd = isNearEndByOwnership(
boardArea,blackWhiteVeryDifferent,blackCountUnsettled,whiteCountUnsettled
);
}
}

Expand Down
3 changes: 3 additions & 0 deletions cpp/tests/tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ namespace Tests {
//testtime.cpp
void runTimeControlsTests();

//command/writetrainingdata.cpp
void runTrainingDataEndTests();

//testtrainingwrite.cpp
void runTrainingWriteTests();
void runPassAliveSuicideGameTests();
Expand Down