"""비교용 baseline 정책 (NegotiationPolicy 구현). 학습 정책과 같은 인터페이스로 하네스에 등록.""" import numpy as np from negotiation.policies.base import ActionDecision, NegotiationPolicy, PolicyContext, Transition class RandomPolicy(NegotiationPolicy): """가용 액션 중 무작위 선택. 학습하지 않음(update no-op). 학습 정책의 하한 비교군.""" name = "random" def __init__(self, seed: int = 0): self.rng = np.random.default_rng(seed) def _available(self, ctx: PolicyContext): used = ctx.episode.used_action_ids if ctx.episode else set() avail = [a for a in range(ctx.action_space_size) if a not in used] return avail or list(range(ctx.action_space_size)) def select(self, ctx: PolicyContext) -> ActionDecision: avail = self._available(ctx) a = int(self.rng.choice(avail)) if ctx.episode: ctx.episode.mark_used(a) return ActionDecision(action_id=a, propensity=1.0 / len(avail), available_actions=avail) def update(self, transition: Transition) -> None: pass def predict_action_dist(self, ctx: PolicyContext) -> np.ndarray: avail = self._available(ctx) dist = np.zeros(ctx.action_space_size) for a in avail: dist[a] = 1.0 / len(avail) return dist class StaticPolicy(NegotiationPolicy): """항상 고정 카드(기본 action 0). '정적 운영'(학습 없음) 비교군.""" name = "static" def __init__(self, fixed_action: int = 0): self.fixed = fixed_action def select(self, ctx: PolicyContext) -> ActionDecision: used = ctx.episode.used_action_ids if ctx.episode else set() a = self.fixed if self.fixed not in used else next( (x for x in range(ctx.action_space_size) if x not in used), self.fixed) if ctx.episode: ctx.episode.mark_used(a) return ActionDecision(action_id=a, propensity=1.0, available_actions=[a]) def update(self, transition: Transition) -> None: pass