Deep CFR 정보 상태 encoding 확장
This commit is contained in:
@@ -1,11 +1,23 @@
|
|||||||
# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True, initializedcheck=False
|
# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True, initializedcheck=False
|
||||||
"""Minimal deterministic information-state encoding for Deep CFR scaffolding."""
|
"""Deterministic information-state encoding for Deep CFR."""
|
||||||
|
|
||||||
from coolrl_lost_cities.games.classic.game cimport GameState
|
from coolrl_lost_cities.games.classic.game cimport GameState
|
||||||
|
|
||||||
|
|
||||||
cdef int input_dim_c(GameState state) noexcept:
|
cdef int input_dim_c(GameState state) noexcept:
|
||||||
return 5 + state.hand_size * 3 + 2 * state.hand_size + 1 + state.n_colors
|
cdef int action_size = 2 * state.hand_size + 1 + state.n_colors
|
||||||
|
cdef int card_type_size = state.n_colors * (state.n_ranks + 1)
|
||||||
|
return (
|
||||||
|
5
|
||||||
|
+ state.hand_size * 3
|
||||||
|
+ 2 * state.n_colors * 4
|
||||||
|
+ state.n_colors * 4
|
||||||
|
+ card_type_size
|
||||||
|
+ 3
|
||||||
|
+ 1
|
||||||
|
+ state.n_colors + 1
|
||||||
|
+ action_size
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
cdef int encode_info_state_c(GameState state, int player, float* out) except -1:
|
cdef int encode_info_state_c(GameState state, int player, float* out) except -1:
|
||||||
@@ -15,6 +27,16 @@ cdef int encode_info_state_c(GameState state, int player, float* out) except -1:
|
|||||||
cdef int color
|
cdef int color
|
||||||
cdef int rank
|
cdef int rank
|
||||||
cdef int action_size = 2 * state.hand_size + 1 + state.n_colors
|
cdef int action_size = 2 * state.hand_size + 1 + state.n_colors
|
||||||
|
cdef int card_type_size = state.n_colors * (state.n_ranks + 1)
|
||||||
|
cdef int public_base
|
||||||
|
cdef int player_index
|
||||||
|
cdef int length
|
||||||
|
cdef int top_card
|
||||||
|
cdef int card_index
|
||||||
|
cdef int max_expedition_len = state.n_ranks + state.n_handshakes
|
||||||
|
cdef float score_denom = <float>(
|
||||||
|
max(1, state.bonus_amount + (state.n_ranks * (state.n_ranks + 1)) * (state.n_handshakes + 1))
|
||||||
|
)
|
||||||
cdef int action_count
|
cdef int action_count
|
||||||
cdef int actions[64]
|
cdef int actions[64]
|
||||||
cdef int i
|
cdef int i
|
||||||
@@ -49,6 +71,61 @@ cdef int encode_info_state_c(GameState state, int player, float* out) except -1:
|
|||||||
out[idx + 2] = 0.0
|
out[idx + 2] = 0.0
|
||||||
idx += 3
|
idx += 3
|
||||||
|
|
||||||
|
for player_index in range(2):
|
||||||
|
for color in range(state.n_colors):
|
||||||
|
card_index = state._expedition_len_index(player_index, color)
|
||||||
|
length = state.expedition_lens[card_index]
|
||||||
|
out[idx] = <float>length / <float>max_expedition_len
|
||||||
|
out[idx + 1] = <float>state.last_numeric_ranks[card_index] / <float>state.n_ranks
|
||||||
|
out[idx + 2] = <float>state.handshake_counts[card_index] / <float>max(1, state.n_handshakes)
|
||||||
|
out[idx + 3] = <float>state.expedition_scores[card_index] / score_denom
|
||||||
|
idx += 4
|
||||||
|
|
||||||
|
for color in range(state.n_colors):
|
||||||
|
length = state.discard_lens[color]
|
||||||
|
out[idx] = <float>length / <float>max_expedition_len
|
||||||
|
if length > 0:
|
||||||
|
top_card = state.discard_cards[state._discard_index(color, length - 1)]
|
||||||
|
out[idx + 1] = 1.0
|
||||||
|
out[idx + 2] = <float>(state._card_color(top_card) + 1) / <float>state.n_colors
|
||||||
|
out[idx + 3] = <float>state._card_rank(top_card) / <float>state.n_ranks
|
||||||
|
else:
|
||||||
|
out[idx + 1] = 0.0
|
||||||
|
out[idx + 2] = 0.0
|
||||||
|
out[idx + 3] = 0.0
|
||||||
|
idx += 4
|
||||||
|
|
||||||
|
public_base = idx
|
||||||
|
for i in range(card_type_size):
|
||||||
|
out[public_base + i] = 0.0
|
||||||
|
for player_index in range(2):
|
||||||
|
for color in range(state.n_colors):
|
||||||
|
card_index = state._expedition_len_index(player_index, color)
|
||||||
|
for i in range(state.expedition_lens[card_index]):
|
||||||
|
card = state.expedition_cards[state._expedition_index(player_index, color, i)]
|
||||||
|
out[public_base + state._card_color(card) * (state.n_ranks + 1) + state._card_rank(card)] += 1.0
|
||||||
|
for color in range(state.n_colors):
|
||||||
|
for i in range(state.discard_lens[color]):
|
||||||
|
card = state.discard_cards[state._discard_index(color, i)]
|
||||||
|
out[public_base + state._card_color(card) * (state.n_ranks + 1) + state._card_rank(card)] += 1.0
|
||||||
|
idx += card_type_size
|
||||||
|
|
||||||
|
out[idx] = <float>state.total_scores[player] / score_denom
|
||||||
|
out[idx + 1] = <float>state.total_scores[1 - player] / score_denom
|
||||||
|
out[idx + 2] = <float>(state.total_scores[player] - state.total_scores[1 - player]) / score_denom
|
||||||
|
idx += 3
|
||||||
|
|
||||||
|
out[idx] = <float>state.turn_count / <float>max(1, state.total_cards * 2)
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
for i in range(state.n_colors + 1):
|
||||||
|
out[idx + i] = 0.0
|
||||||
|
if state.pending_discarded_color < 0:
|
||||||
|
out[idx + state.n_colors] = 1.0
|
||||||
|
else:
|
||||||
|
out[idx + state.pending_discarded_color] = 1.0
|
||||||
|
idx += state.n_colors + 1
|
||||||
|
|
||||||
for i in range(action_size):
|
for i in range(action_size):
|
||||||
out[idx + i] = 0.0
|
out[idx + i] = 0.0
|
||||||
action_count = state._unified_legal_actions_c(actions)
|
action_count = state._unified_legal_actions_c(actions)
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ def test_encode_info_state_is_deterministic_and_matches_legal_mask_tail() -> Non
|
|||||||
|
|
||||||
assert encoded.dtype == np.float32
|
assert encoded.dtype == np.float32
|
||||||
assert encoded.shape == (input_dim(state),)
|
assert encoded.shape == (input_dim(state),)
|
||||||
|
assert input_dim(state) > 5 + state.config.hand_size * 3 + len(legal_mask)
|
||||||
np.testing.assert_array_equal(encoded, encoded_again)
|
np.testing.assert_array_equal(encoded, encoded_again)
|
||||||
np.testing.assert_array_equal(encoded[-len(legal_mask) :], legal_mask)
|
np.testing.assert_array_equal(encoded[-len(legal_mask) :], legal_mask)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user