Skip to content

Commit

Permalink
Add komi integration to ratings math
Browse files Browse the repository at this point in the history
Add komi integration to the ratings math. This path can be turned on using:

- `--compute-handicap-via-komi-small` for 9x9 and 13x13 boards
- `--compute-handicap-via-komi-19x19` for 19x19 boards

For now, none of the scripts pass the necessary extra arguments (they assert
out if you pass those arguments).

Relates to online-go#45
  • Loading branch information
dexonsmith committed Dec 12, 2023
1 parent 4c677e3 commit a1486cb
Showing 1 changed file with 72 additions and 3 deletions.
75 changes: 72 additions & 3 deletions analysis/util/RatingMath.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,25 @@
P = 1
HALF_STONE_HANDICAP = False
HALF_STONE_HANDICAP_FOR_ALL_RANKS = False
COMPUTE_HANDICAP_VIA_KOMI_SMALL = False
COMPUTE_HANDICAP_VIA_KOMI_19X19 = False

cli.add_argument(
"--half-stone-handicap", dest="half_stone_handicap", const=1, default=False, action="store_const", help="Use a 0.5 rank adjustment for hc1",
)
cli.add_argument(
"--half-stone-handicap-for-all-ranks", dest="half_stone_handicap_for_all_ranks", const=1, default=False, action="store_const", help="use rankdiff -0.5 for handicap",
)
cli.add_argument(
"--compute-handicap-via-komi-small",
dest="compute_handicap_via_komi_small", const=1, default=False, action="store_const",
help="compute effective handicap from komi for small boards",
)
cli.add_argument(
"--compute-handicap-via-komi-19x19",
dest="compute_handicap_via_komi_19x19", const=1, default=False, action="store_const",
help="compute effective handicap from komi for 19x19 boards",
)

logarithmic = cli.add_argument_group(
"logarithmic ranking variables", "rating to ranks converted with `(log(rating / a) ** p) * c + d`",
Expand Down Expand Up @@ -77,14 +89,67 @@ def set_exhaustive_log_parameters(a: float, c:float, d:float, p:float = 1.0) ->
D = d
P = p

def get_handicap_adjustment(rating: float, handicap: int) -> float:
def get_handicap_adjustment(rating: float, handicap: int, size: int | None = None, komi: float | None = None, rules: str | None = None) -> float:
global HALF_STONE_HANDICAP
global HALF_STONE_HANDICAP_FOR_ALL_RANKS
global COMPUTE_HANDICAP_VIA_KOMI_SMALL
global COMPUTE_HANDICAP_VIA_KOMI_19X19

if COMPUTE_HANDICAP_VIA_KOMI_19X19 or COMPUTE_HANDICAP_VIA_KOMI_SMALL:
assert size is not None
assert (size == 9 or
size == 13 or
size == 19)
assert komi is not None
assert rules is not None
assert (rules == "chinese" or
rules == "aga" or
rules == "japanese" or
rules == "korean" or
rules == "ing" or
rules == "nz")
if (COMPUTE_HANDICAP_VIA_KOMI_19X19 and size == 19) or (COMPUTE_HANDICAP_VIA_KOMI_SMALL and size != 19):
# Use a "even game komi" that allows for draws for computing ratings.
# It's okay to expect a draw.
stone_value = 12
if rules == "japanese" or rules == "korean":
# Territory scoring.
area_bonus = 0
komi_bonus = 0
else:
# Bonus for the area value of a stone in area scoring.
area_bonus = 1

# Chinese and AGA rules add extra komi when there's a handicap but
# don't store it in the 'komi' field.
if rules == "chinese":
komi_bonus = 1 * handicap
elif rules == "aga":
komi_bonus = 1 * (handicap - 1) if handicap else 0
else:
komi_bonus = 0

# Convert the handicap into an equivalent komi, and subtract it from
# the komi for an even game.
handicap_as_komi = ((stone_value / 2 + area_bonus) - (komi + komi_bonus) +
((stone_value + area_bonus) * handicap if handicap > 1 else 0))

# Convert back to a fractional handicap, using scaling factors of 3x
# and 6x for 9x9 and 13x13.
if size == 9:
adjusted_handicap = handicap_as_komi * 6 / stone_value
elif size == 13:
adjusted_handicap = handicap_as_komi * 3 / stone_value
else:
adjusted_handicap = handicap_as_komi / stone_value

return rank_to_rating(rating_to_rank(rating) + adjusted_handicap) - rating

if HALF_STONE_HANDICAP_FOR_ALL_RANKS:
return rank_to_rating(rating_to_rank(rating) + (handicap - 0.5 if handicap > 0 else 0)) - rating
if HALF_STONE_HANDICAP:
return rank_to_rating(rating_to_rank(rating) + (0.5 if handicap == 1 else handicap)) - rating
return rank_to_rating(rating_to_rank(rating) + handicap) - rating
return rank_to_rating(rating_to_rank(rating)) - rating

def set_optimizer_rating_points(points: List[float]) -> None:
global optimizer_rating_control_points
Expand All @@ -99,9 +164,13 @@ def configure_rating_to_rank(args: argparse.Namespace) -> None:
global D
global HALF_STONE_HANDICAP
global HALF_STONE_HANDICAP_FOR_ALL_RANKS
global COMPUTE_HANDICAP_VIA_KOMI_SMALL
global COMPUTE_HANDICAP_VIA_KOMI_19X19

HALF_STONE_HANDICAP = args.half_stone_handicap
HALF_STONE_HANDICAP_FOR_ALL_RANKS = args.half_stone_handicap_for_all_ranks
COMPUTE_HANDICAP_VIA_KOMI_SMALL = args.compute_handicap_via_komi_small
COMPUTE_HANDICAP_VIA_KOMI_19X19 = args.compute_handicap_via_komi_19x19
system: str = args.ranks
a: float = args.a
c: float = args.c
Expand Down Expand Up @@ -260,7 +329,7 @@ def __rating_to_rank(rating: float) -> float:
else:
raise NotImplementedError

assert round(get_handicap_adjustment(1000.0, 0), 8) == 0
assert round(get_handicap_adjustment(1000.0, 0, size=19, rules="japanese",komi="0.5"), 8) == 0


def lerp(x:float, y:float, a:float):
Expand Down

0 comments on commit a1486cb

Please sign in to comment.