fewer hints, alternatives search

This commit is contained in:
Sander Land committed 2020-09-08 22:26:14 +02:00
1 parent 2758e936c8
commit 4e2ee03db7
26 files changed
+137 -47

No files matched your search

+1
View File
@@ -440,6 +440,7 @@ class KaTrainGui(Screen, KaTrainBase):
"a": ("analyze-extra", "extra"),
"s": ("analyze-extra", "equalize"),
"d": ("analyze-extra", "sweep"),
"f": ("analyze-extra", "alternative"),
"p": ("play", None),
"down": ("switch-branch", 1),
"up": ("switch-branch", -1),
+16 -1
View File
@@ -77,7 +77,9 @@ class KataGoEngine:
elif not os.path.isfile(cfg):
self.katrain.log(i18n._("Kata config not found").format(config=cfg), OUTPUT_ERROR)
return # don't start
self.command = shlex.split(f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}')
self.command = shlex.split(
f'"{exe}" analysis -model "{model}" -config "{cfg}" -analysis-threads {config["threads"]}'
)
self.start()
def start(self):
@@ -224,6 +226,7 @@ class KataGoEngine:
visits: int = None,
analyze_fast: bool = False,
time_limit=True,
find_alternatives: bool = False,
priority: int = 0,
ownership: Optional[bool] = None,
next_move: Optional[GameNode] = None,
@@ -241,6 +244,17 @@ class KataGoEngine:
if analyze_fast and self.config.get("fast_visits"):
visits = self.config["fast_visits"]
if find_alternatives:
avoid = [
{
"moves": list(analysis_node.analysis["moves"].keys()),
"player": analysis_node.next_player,
"untilDepth": 1,
}
]
else:
avoid = []
size_x, size_y = analysis_node.board_size
settings = copy.copy(self.override_settings)
if time_limit:
@@ -254,6 +268,7 @@ class KataGoEngine:
"analyzeTurns": [len(moves)],
"maxVisits": visits,
"komi": analysis_node.komi,
"avoidMoves": avoid,
"boardXSize": size_x,
"boardYSize": size_y,
"includeOwnership": ownership and not next_move,
+12 -6
View File
@@ -369,21 +369,27 @@ class Game:
visits = engine.config["fast_visits"]
self.katrain.controls.set_status(i18n._("sweep analysis").format(visits=visits), STATUS_ANALYSIS)
priority = -1_000_000_000
elif mode == "equalize":
elif mode in ["equalize", "alternative"]:
if not cn.analysis_ready:
self.katrain.controls.set_status(i18n._("wait-before-equalize"), STATUS_INFO, self.current_node)
return
analyze_moves = [Move.from_gtp(gtp, player=cn.next_player) for gtp, _ in cn.analysis["moves"].items()]
visits = max(d["visits"] for d in cn.analysis["moves"].values())
self.katrain.controls.set_status(i18n._("equalizing analysis").format(visits=visits), STATUS_ANALYSIS)
priority = -1_000
if mode == "alternative": # also do a quick update on current candidates so it doesn't look too weird
self.katrain.controls.set_status("Searching for alternatives", STATUS_ANALYSIS)
cn.analyze(engine, priority=-500, time_limit=False, find_alternatives=True)
visits = engine.config["fast_visits"]
else:
visits = max(d["visits"] for d in cn.analysis["moves"].values())
self.katrain.controls.set_status(i18n._("equalizing analysis").format(visits=visits), STATUS_ANALYSIS)
else:
raise ValueError("Invalid analysis mode")
for move in analyze_moves:
cn.analyze(
engine, priority, visits=visits, refine_move=move, time_limit=False
) # explicitly requested so take as long as you need
if cn.analysis["moves"].get(move.gtp(), {"visits": 0})["visits"] < visits:
cn.analyze(
engine, priority, visits=visits, refine_move=move, time_limit=False
) # explicitly requested so take as long as you need
def analyze_undo(self, node):
train_config = self.katrain.config("trainer")
+18 -4
View File
@@ -68,15 +68,25 @@ class GameNode(SGFNode):
) # analyzed/not undone main, non-teach second, undone last
# various analysis functions
def analyze(self, engine, priority=0, visits=None, time_limit=True, refine_move=None, analyze_fast=False):
def analyze(
self,
engine,
priority=0,
visits=None,
time_limit=True,
refine_move=None,
analyze_fast=False,
find_alternatives=False,
):
engine.request_analysis(
self,
lambda result: self.set_analysis(result, refine_move),
lambda result: self.set_analysis(result, refine_move, find_alternatives),
priority=priority,
visits=visits,
analyze_fast=analyze_fast,
time_limit=time_limit,
next_move=refine_move,
find_alternatives=find_alternatives,
)
def update_move_analysis(self, move_analysis, move_gtp):
@@ -90,18 +100,22 @@ class GameNode(SGFNode):
elif cur["visits"] < move_analysis["visits"]:
cur.update(move_analysis)
def set_analysis(self, analysis_json, refine_move):
def set_analysis(self, analysis_json, refine_move, alternatives_mode):
if refine_move:
pvtail = analysis_json["moveInfos"][0]["pv"] if analysis_json["moveInfos"] else []
self.update_move_analysis(
{"pv": [refine_move.gtp()] + pvtail, **analysis_json["rootInfo"]}, refine_move.gtp()
)
else:
if alternatives_mode:
for m in analysis_json["moveInfos"]:
m["order"] += 10 # offset for not making this top
for move_analysis in analysis_json["moveInfos"]:
self.update_move_analysis(move_analysis, move_analysis["move"])
self.ownership = analysis_json.get("ownership")
self.policy = analysis_json.get("policy")
self.analysis["root"] = analysis_json["rootInfo"]
if not alternatives_mode:
self.analysis["root"] = analysis_json["rootInfo"]
if self.parent and self.move:
analysis_json["rootInfo"]["pv"] = [self.move.gtp()] + (
analysis_json["moveInfos"][0]["pv"] if analysis_json["moveInfos"] else []
+5
View File
@@ -744,6 +744,11 @@
icon: 'img/Sweep.png'
shortcut: 'd'
on_action: root.katrain("analyze-extra", "sweep")
AnalysisMenuItem:
text: i18n._("analysis:alternatives")
icon: 'img/Alternative.png'
shortcut: 'f'
on_action: root.katrain("analyze-extra", "alternative")
AnalysisMenuItem:
text: i18n._("analysis:game")
icon: 'img/analysis.png'
+17 -7
View File
@@ -361,7 +361,7 @@ class BadukPanWidget(Widget):
polsize = 1.1 * math.sqrt(policy_grid[y][x])
policy_circle_color = (
*POLICY_COLOR,
POLICY_ALPHA + TOP_MOVE_ALPHA * (policy_grid[y][x] == best_move_policy),
POLICY_ALPHA + TOP_POLICY_ALPHA * (policy_grid[y][x] == best_move_policy),
)
draw_circle(
(self.gridpos_x[x], self.gridpos_y[y]), polsize * self.stone_size, policy_circle_color
@@ -409,27 +409,37 @@ class BadukPanWidget(Widget):
self.active_pv_moves = []
# hints or PV
if katrain.analysis_controls.hints.active and not katrain.analysis_controls.policy.active and not game_ended:
if (
katrain.analysis_controls.hints.active
and not katrain.analysis_controls.policy.active
and not game_ended
):
hint_moves = current_node.candidate_moves
for i, move_dict in enumerate(hint_moves):
move = Move.from_gtp(move_dict["move"])
if move.coords is not None:
scale = 0.95
if move_dict["visits"] < VISITS_FRAC_SMALL * hint_moves[0]["visits"]:
scale = 0.75
scale = HINT_SCALE
text_on = True
alpha = HINTS_ALPHA
if move_dict["visits"] < katrain.config("engine/fast_visits"):
scale = UNCERTAIN_HINT_SCALE
text_on = False
alpha = HINTS_MIN_ALPHA + (HINTS_ALPHA - HINTS_MIN_ALPHA) * (
move_dict["visits"] / katrain.config("engine/fast_visits")
)
if "pv" in move_dict:
self.active_pv_moves.append((move.coords, move_dict["pv"], current_node))
else:
katrain.log(f"PV missing for move_dict {move_dict}", OUTPUT_DEBUG)
evalsize = self.stone_size * scale
evalcol = self.eval_color(move_dict["pointsLost"])
Color(*evalcol[:3], HINTS_ALPHA)
Color(*evalcol[:3], alpha)
Rectangle(
pos=(self.gridpos_x[move.coords[0]] - evalsize, self.gridpos_y[move.coords[1]] - evalsize),
size=(2 * evalsize, 2 * evalsize),
source="katrain/img/topmove.png",
)
if self.trainer_config["text_point_loss"]:
if self.trainer_config["text_point_loss"] and text_on:
if move_dict["pointsLost"] < 0.05:
ptloss_text = "0.0"
else:
+1
View File
@@ -373,6 +373,7 @@ class AnalysisToggle(MDBoxLayout):
default_active = BooleanProperty(False)
font_name = StringProperty(DEFAULT_FONT)
disabled = BooleanProperty(False)
def trigger_action(self, *args, **kwargs):
return self.checkbox.trigger_action(*args, **kwargs)
+7 -4
View File
@@ -59,13 +59,16 @@ POLICY_COLOR = [0.9, 0.2, 0.8]
STARPOINT_SIZE = 0.1
BOARD_COLOR = [0.85, 0.68, 0.40, 1]
STONE_SIZE = 0.505 # texture edge is transparent
VISITS_FRAC_SMALL = 0.1
POLICY_ALPHA = 0.5
HINTS_ALPHA = 0.75
TOP_MOVE_ALPHA = 0.4
HINTS_ALPHA = 0.8
HINTS_MIN_ALPHA = 0.1 # single visit
POLICY_ALPHA = 0.6
TOP_POLICY_ALPHA = 0.3
TOP_MOVE_BORDER_COLOR = [10 / 255, 200 / 255, 250 / 255, 1.0]
CHILD_SCALE = 0.95
HINT_SCALE = 0.975
UNCERTAIN_HINT_SCALE = 0.7
# ponder light
ENGINE_DOWN_COL = EVAL_COLORS["theme:normal"][1]
Binary file not shown.
@@ -521,6 +521,7 @@ msgstr "读秒声音开启"
msgid "tab:info-details"
msgstr "详细"
#. TODO: updated
msgid "teaching undo message"
msgstr "撤销第 {move} 手棋因为损失超过 {points_lost:.1f} 目. 悬停在该手棋 上方查看信息. 请再次尝试."
@@ -631,3 +632,7 @@ msgstr "启动katago失败因缺失dll文件. 请检查运行要求, 或尝试
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
+11 -6
View File
@@ -105,12 +105,6 @@ msgstr "AI Zug erzwingen"
msgid "pass-button-text"
msgstr "Passen"
msgid "teaching undo message"
msgstr ""
"Zug {move} zurückgenommen, da er {points_lost:.1f} Punkte verliert. Bewege "
"Mauszeiger über den Zug,um die erwartete Widerlegung zu sehen. Bitte "
"versuche es erneut."
msgid "ai-ponder"
msgstr ""
"Zeigt den Enginestatus an von grün (Leerlauf) bis orange(Zugberechnung). Ist"
@@ -680,3 +674,14 @@ msgstr "Zeig den Punkteverlust auf Beste Züge"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"Zug {move} zurückgenommen, da er {points_lost:.1f} Punkte verliert. Bewege "
"Mauszeiger über den Zug,um die erwartete Widerlegung zu sehen. Bitte "
"versuche es erneut."
Binary file not shown.
@@ -102,6 +102,10 @@ msgstr "Fast analysis of all moves"
msgid "analysis:game"
msgstr "Deeper full game analysis"
#. Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. Keep improving current position analysis when there is nothing else to do
msgid "analysis:continuous"
msgstr "Toggle continuous analysis"
@@ -133,10 +137,12 @@ msgstr "Pass"
msgid "resign"
msgstr "Resign"
#. Shown when a move is undone in teaching mode.
msgid "teaching undo message"
msgstr ""
"Undid move {move} as it lost {points_lost:.1f} points. Hover over the move "
"to see expected refutation. Please try again."
"Undid move {move} as it lost {points_lost:.1f} points. Please try again. For"
" a hint, hover over the move to see expected refutation, or check expected "
"territory (t) to see the areas of the board where point loss is expected."
msgid "ai-ponder"
msgstr ""
Binary file not shown.
@@ -105,6 +105,7 @@ msgstr "Forzar jugada IA"
msgid "pass-button-text"
msgstr "Pasar"
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"Deshice jugada {move} ya que perdía {points_lost:.1f} puntos. Coloca el "
@@ -688,3 +689,7 @@ msgstr "Show point loss on top moves"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -522,6 +522,7 @@ msgstr ""
"possiblement pour cause de \n"
"mémoire insuffisante : {error}"
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"Le coup {move} a été annulé car il perdait {points_lost:.1f} points. Vous "
@@ -715,3 +716,7 @@ msgstr "Indiquer les points perdus"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -129,10 +129,6 @@ msgstr "一局全体を再分析中(各{visits}手)"
msgid "pass-button-text"
msgstr "パス"
msgid "teaching undo message"
msgstr ""
"待った。{move}は{points_lost:.1f}目損です(マウスカーソルをこの手にかざせばとがめる手順が表示されます)。打ち直してください。"
msgid "ai-ponder"
msgstr "この印はエンジンの状態をシンプルに表します(緑=空き、オレンジ=処理中)。エンジンが止まったり起動できなかったりすると赤くなります。"
@@ -670,3 +666,12 @@ msgstr "損失目数を候補手上に表示"
#. - resign the game
msgid "resign"
msgstr "投了"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"待った。{move}は{points_lost:.1f}目損です(マウスカーソルをこの手にかざせばとがめる手順が表示されます)。打ち直してください。"
Binary file not shown.
@@ -546,6 +546,7 @@ msgstr ""
"`threshold`선 밑의 수를 더 많이 뽑은 후 그 중 최선의 수를 둡니다. `line_weight`을 증가시키면 바둑판 중앙에 있는"
" 수를 더욱 꺼리게 됩니다. 판이 `endgame` 비율만큼 차면 평범하게 둡니다."
#. TODO: updated
msgid "teaching undo message"
msgstr ""
"{points_lost:.1f}집 손해이므로 {move}을/를 물렀습니다. 커서를 올려 상대의 대응책을 보십시오. 다시 두어 주세요."
@@ -648,3 +649,7 @@ msgstr "돌 위에 집 손해 표시하기"
#. TODO - resign the game
msgid "resign"
msgstr "기권함"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.
@@ -117,6 +117,7 @@ msgstr "Дополнительный анализ всех ходов-канди
msgid "pass-button-text"
msgstr "Пас"
#. TODO - updated
msgid "teaching undo message"
msgstr ""
"Ход {move} отменён, т.к. это потеря {points_lost:.1f} очков. Наведите на "
@@ -676,3 +677,7 @@ msgstr "Показывать потерянные очки текстом"
#. TODO - resign the game
msgid "resign"
msgstr "Resign"
#. TODO - Analyze again but exclude all currently considered moves
msgid "analysis:alternatives"
msgstr "Find alternative moves"
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB