diff --git a/algorithm/feature_context.py b/algorithm/feature_context.py index 1c3c53e..4580d4f 100644 --- a/algorithm/feature_context.py +++ b/algorithm/feature_context.py @@ -1,14 +1,23 @@ import numpy as np from numpy.typing import NDArray -from dataclasses import dataclass +from dataclasses import dataclass, field from game.board import compute_prefix_sum - +from game.action import Action +from game.board import Board @dataclass class FeatureContext: board: NDArray[np.int8] # 숫자 배열의 좌푯값 prefix: NDArray # 누적합 count_by_value: dict[int, int] #숫자별 남아있는 개수 + action : Action + _valid_actions: list | None = field(default=None, repr=False) + + @property + def valid_actions(self): #valid action 함수 불러오기 + if self._valid_actions is None: + self._valid_actions = Board.get_valid_actions(self.board) # next_board 기준으로 딱 1번 + return self._valid_actions @classmethod def from_board(cls, board: NDArray[np.int8]) -> "FeatureContext": diff --git a/algorithm/features.py b/algorithm/features.py index 283da13..5011820 100644 --- a/algorithm/features.py +++ b/algorithm/features.py @@ -3,7 +3,7 @@ #숫자 편향 features ex) 지울 수 있는 'n'이라는 숫자가 몇 개 남았는가 점수를 올림으로써 지우게끔 유도 def feature_remove_nine(ctx: FeatureContext) -> float: - area = ctx.area + area = ctx.board if not(area == 9).any(): #격자 안에 9가 없을시 0을 return한다 return 0.0 nine_count = int((area==9).sum()) #area안에 9가 있는 수의 개수 @@ -12,44 +12,41 @@ def feature_remove_nine(ctx: FeatureContext) -> float: return sigmoid(nine_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 def feature_remove_eight(ctx: FeatureContext) -> float: - area = ctx.area - if not(area == 8).any(): #격자 안에 9가 없을시 0을 return한다 + area = ctx.board + if not(area == 8).any(): return 0.0 - eight_count = int((area==8).sum()) #area안에 9가 있는 수의 개수 - if not _has_eight_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지 + eight_count = int((area==8).sum()) + if not _has_eight_pair(ctx): return 0.0 - return sigmoid(eight_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 + return sigmoid(eight_count, k = 0.5, x0 = 3.0) def feature_remove_seven(ctx: FeatureContext) -> float: - area = ctx.area - if not(area == 7).any(): #격자 안에 9가 없을시 0을 return한다 + area = ctx.board + if not(area == 7).any(): return 0.0 - seven_count = int((area==7).sum()) #area안에 9가 있는 수의 개수 - if not _has_seven_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지 + seven_count = int((area==7).sum()) + if not _has_seven_pair(ctx): return 0.0 - return sigmoid(seven_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 + return sigmoid(seven_count, k = 0.5, x0 = 3.0) def feature_remove_six(ctx: FeatureContext) -> float: - area = ctx.area - if not(area == 6).any(): #격자 안에 9가 없을시 0을 return한다 + area = ctx.board + if not(area == 6).any(): return 0.0 - six_count = int((area==6).sum()) #area안에 9가 있는 수의 개수 - if not _has_six_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지 + six_count = int((area==6).sum()) + if not _has_six_pair(ctx): return 0.0 - return sigmoid(six_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 + return sigmoid(six_count, k = 0.5, x0 = 3.0) def feature_remove_five(ctx: FeatureContext) -> float: - area = ctx.area - if not(area == 5).any(): #격자 안에 9가 없을시 0을 return한다 + area = ctx.board + if not(area == 5).any(): return 0.0 - five_count = int((area==5).sum()) #area안에 9가 있는 수의 개수 - if not _has_five_pair(ctx): #9와 짝 지어지는 경우의 수가 판 내에 존재하는지 + five_count = int((area==5).sum()) + if not _has_five_pair(ctx): return 0.0 - return sigmoid(five_count, k = 0.5, x0 = 3.0) #추후 이 값을 조정하면서 k 값과 x0 값을 찾아도 됨 - -def feature_remove_middle(ctx: FeatureContext) -> float: - area + return sigmoid(five_count, k = 0.5, x0 = 3.0) #feature_remove series를 구현하기 위한 보조 함수 @@ -59,43 +56,43 @@ def _has_nine_one_pair(ctx : FeatureContext) -> bool: for action in ctx.valid_actions: r1, c1 = action.top_left r2, c2 = action.bottom_right - region = ctx.area[r1:r2+1, c1:c2+1] + region = ctx.board[r1:r2+1, c1:c2+1] if (region == 9).any(): return True return False def _has_eight_pair(ctx : FeatureContext) -> bool: - for action in ctx.valid_actions: + for action in ctx._valid_actions: r1, c1 = action.top_left r2, c2 = action.bottom_right - region = ctx.area[r1:r2+1, c1:c2+1] + region = ctx.board[r1:r2+1, c1:c2+1] if (region == 8).any(): return True return False def _has_seven_pair(ctx : FeatureContext) -> bool: - for action in ctx.valid_actions: + for action in ctx._valid_actions: r1, c1 = action.top_left r2, c2 = action.bottom_right - region = ctx.area[r1:r2+1, c1:c2+1] + region = ctx.board[r1:r2+1, c1:c2+1] if (region == 7).any(): return True return False def _has_six_pair(ctx : FeatureContext) -> bool: - for action in ctx.valid_actions: + for action in ctx._valid_actions: r1, c1 = action.top_left r2, c2 = action.bottom_right - region = ctx.area[r1:r2+1, c1:c2+1] + region = ctx.board[r1:r2+1, c1:c2+1] if (region == 6).any(): return True return False def _has_five_pair(ctx : FeatureContext) -> bool: - for action in ctx.valid_actions: + for action in ctx._valid_actions: r1, c1 = action.top_left r2, c2 = action.bottom_right - region = ctx.area[r1:r2+1, c1:c2+1] + region = ctx.board[r1:r2+1, c1:c2+1] if (region == 5).any(): return True return False