Skip to content

Commit ed3bd82

Browse files
committed
Merge remote-tracking branch 'origin/feat/dcegm' into feat/nb-egm
2 parents 226e846 + a69f40a commit ed3bd82

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

tests/solution/test_egm_interp_query_derivative.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
interp_right_germ_on_padded_grid,
3838
prepare_padded_grid,
3939
)
40+
from _lcm.egm.outer_envelope import outer_envelope_at_query
4041

4142

4243
def test_exact_node_continuation_gradient_matches_carry_marginal():
@@ -189,6 +190,32 @@ def read(fp):
189190
np.testing.assert_allclose(float(weights[2]), 0.0, atol=1e-12)
190191

191192

193+
def test_terminal_tie_between_right_identical_candidates_is_owned_by_index():
194+
"""A tie exactly at a shared terminal abscissa follows the index convention.
195+
196+
Two candidates ending at the same abscissa with equal terminal values are
197+
right-identical there (both clamp: right-finite, all germ derivatives
198+
zero), even when their left-neighborhood economics differ — the boundary
199+
subgradient is not unique, so ownership is the documented deterministic
200+
convention: the lowest index wins and its marginal is published. This pins
201+
the convention so a future change cannot silently reinterpret the
202+
terminal boundary.
203+
"""
204+
candidate_endog = jnp.array([[0.0, 1.0, 2.0], [0.0, 1.0, 2.0]])
205+
candidate_value = jnp.array([[0.0, 1.0, 2.0], [-2.0, 0.0, 2.0]])
206+
candidate_marginal = jnp.array([[1.0, 1.0, 1.0], [2.0, 2.0, 2.0]])
207+
208+
value, marginal = outer_envelope_at_query(
209+
candidate_endog=candidate_endog,
210+
candidate_value=candidate_value,
211+
candidate_marginal=candidate_marginal,
212+
x_query=jnp.array([2.0]),
213+
)
214+
215+
np.testing.assert_allclose(float(value[0]), 2.0, atol=1e-12)
216+
np.testing.assert_allclose(float(marginal[0]), 1.0, atol=1e-12)
217+
218+
192219
def test_singleton_query_gradient_stays_zero_under_the_analytic_rule():
193220
"""A singleton row keeps its zero query derivative under the analytic rule."""
194221
xp = jnp.array([1.0, jnp.nan, jnp.nan])

0 commit comments

Comments
 (0)