From 7102825c61321457048441dd4938b440e6712672 Mon Sep 17 00:00:00 2001 From: CoronelBuendia Date: Fri, 4 Apr 2025 09:23:52 +0200 Subject: [PATCH 1/4] add tests for the wikipedia example --- tests/test_vmcon_paper.py | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/test_vmcon_paper.py b/tests/test_vmcon_paper.py index ec4115b..2dc5069 100644 --- a/tests/test_vmcon_paper.py +++ b/tests/test_vmcon_paper.py @@ -109,9 +109,28 @@ class VMCONTestAsset(NamedTuple): initial_x=np.array([1.0, 1.0]), epsilon=2e-8, expected_x=[0.5 * 2**0.5, 0.5 * 2**0.5], # Shouldn't these be negative? + # MC: Yes, they absolutely should be... see next test + # It would appear VMCON has a predilection for stationary points + # This solution is in fact the worst possible objective function value (maximum) + # whilst still satisfying the constraint. expected_lamda_equality=[2 ** (-0.5)], expected_lamda_inequality=[], ), + VMCONTestAsset( + Problem( + lambda x: x[0] + x[1], + lambda _: np.array([1, 1]), + [lambda x: (x[0] ** 2) + (x[1] ** 2) - 1], + [], + [lambda x: np.array([2 * x[0], 2 * x[1]])], + [], + ), + initial_x=np.array([-0.1, -0.1]), + epsilon=2e-8, + expected_x=[-0.5 * 2**0.5, -0.5 * 2**0.5], + expected_lamda_equality=[-0.5 * 2 ** (0.5)], + expected_lamda_inequality=[], + ), ], ) def test_vmcon_paper_feasible_examples(vmcon_example: VMCONTestAsset): @@ -172,3 +191,44 @@ def test_vmcon_paper_infeasible_examples(vmcon_example: VMCONTestAsset): max_iter=vmcon_example.max_iter, epsilon=vmcon_example.epsilon, ) + +@pytest.mark.parametrize( + "wikipedia_example", + [ + VMCONTestAsset( + Problem( + lambda x: x[0] + x[1], + lambda _: np.array([1, 1]), + [lambda x: (x[0] ** 2) + (x[1] ** 2) - 1], + [], + [lambda x: np.array([2 * x[0], 2 * x[1]])], + [], + ), + # VMCON will struggle to escape this stationary point + initial_x=np.array([0.0, 0.0]), + epsilon=2e-8, + expected_x=[-0.5 * 2**0.5, -0.5 * 2**0.5], + expected_lamda_equality=[-0.5 * 2 ** (0.5)], + expected_lamda_inequality=[], + ), + ] +) +def test_wikipedia_example_failures(wikipedia_example: VMCONTestAsset): + """Tests runs of VMCON where the problem describes a minimisation + which is infeasible given the constraints. + + Assertions on the returned `x` (the last tried input vector) and + corresponding Lagrange multipliers have been removed as the QSP + implementation produced different final points from the VMCON + paper. This is not surprising considering these problems are + infeasible and we deem the assertions to hold little meaning; + what is important--and thus tested--is that VMCON fails to + converge in these infeasible cases. + """ + with pytest.raises(VMCONConvergenceException): + solve( + wikipedia_example.problem, + wikipedia_example.initial_x, + max_iter=wikipedia_example.max_iter, + epsilon=wikipedia_example.epsilon, + ) \ No newline at end of file From 937645950efa6ac7b2e798ba5410ae0f47771f67 Mon Sep 17 00:00:00 2001 From: CoronelBuendia Date: Fri, 4 Apr 2025 09:30:25 +0200 Subject: [PATCH 2/4] add tests for the wikipedia example --- tests/test_vmcon_paper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_vmcon_paper.py b/tests/test_vmcon_paper.py index 2dc5069..a1d3a20 100644 --- a/tests/test_vmcon_paper.py +++ b/tests/test_vmcon_paper.py @@ -125,6 +125,7 @@ class VMCONTestAsset(NamedTuple): [lambda x: np.array([2 * x[0], 2 * x[1]])], [], ), + # Different starting solution yields the the true minimum initial_x=np.array([-0.1, -0.1]), epsilon=2e-8, expected_x=[-0.5 * 2**0.5, -0.5 * 2**0.5], @@ -204,7 +205,8 @@ def test_vmcon_paper_infeasible_examples(vmcon_example: VMCONTestAsset): [lambda x: np.array([2 * x[0], 2 * x[1]])], [], ), - # VMCON will struggle to escape this stationary point + # VMCON will struggle to escape this point in the QSP + # x = [0, 0] means that the initial_x=np.array([0.0, 0.0]), epsilon=2e-8, expected_x=[-0.5 * 2**0.5, -0.5 * 2**0.5], @@ -231,4 +233,5 @@ def test_wikipedia_example_failures(wikipedia_example: VMCONTestAsset): wikipedia_example.initial_x, max_iter=wikipedia_example.max_iter, epsilon=wikipedia_example.epsilon, + qsp_options={"max_iter": 10000}, ) \ No newline at end of file From a4664a1b3613034b85f183c31b39dc10c5be928a Mon Sep 17 00:00:00 2001 From: CoronelBuendia Date: Fri, 4 Apr 2025 09:32:46 +0200 Subject: [PATCH 3/4] clean up --- tests/test_vmcon_paper.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_vmcon_paper.py b/tests/test_vmcon_paper.py index a1d3a20..0bd5220 100644 --- a/tests/test_vmcon_paper.py +++ b/tests/test_vmcon_paper.py @@ -206,7 +206,6 @@ def test_vmcon_paper_infeasible_examples(vmcon_example: VMCONTestAsset): [], ), # VMCON will struggle to escape this point in the QSP - # x = [0, 0] means that the initial_x=np.array([0.0, 0.0]), epsilon=2e-8, expected_x=[-0.5 * 2**0.5, -0.5 * 2**0.5], From 910b8b59c1a166dbbe0d5ebc2d5fd6e0711475a4 Mon Sep 17 00:00:00 2001 From: CoronelBuendia Date: Mon, 7 Apr 2025 13:57:54 +0200 Subject: [PATCH 4/4] pre-commit --- tests/test_vmcon_paper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_vmcon_paper.py b/tests/test_vmcon_paper.py index 0bd5220..6b35e0d 100644 --- a/tests/test_vmcon_paper.py +++ b/tests/test_vmcon_paper.py @@ -193,6 +193,7 @@ def test_vmcon_paper_infeasible_examples(vmcon_example: VMCONTestAsset): epsilon=vmcon_example.epsilon, ) + @pytest.mark.parametrize( "wikipedia_example", [ @@ -212,7 +213,7 @@ def test_vmcon_paper_infeasible_examples(vmcon_example: VMCONTestAsset): expected_lamda_equality=[-0.5 * 2 ** (0.5)], expected_lamda_inequality=[], ), - ] + ], ) def test_wikipedia_example_failures(wikipedia_example: VMCONTestAsset): """Tests runs of VMCON where the problem describes a minimisation @@ -233,4 +234,4 @@ def test_wikipedia_example_failures(wikipedia_example: VMCONTestAsset): max_iter=wikipedia_example.max_iter, epsilon=wikipedia_example.epsilon, qsp_options={"max_iter": 10000}, - ) \ No newline at end of file + )