Skip to content

Commit

Permalink
add docs and tests for orderings
Browse files Browse the repository at this point in the history
  • Loading branch information
cahity committed Nov 12, 2024
1 parent 41bad80 commit 96ac8de
Show file tree
Hide file tree
Showing 6 changed files with 471 additions and 28 deletions.
27 changes: 27 additions & 0 deletions docs/source/order.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.. role:: hidden
:class: hidden-section


vectoptal.order
===================================

.. automodule:: vectoptal.order
.. currentmodule:: vectoptal.order

.. autoclass:: Order
:members:

Useful Orders
-----------------------------

.. autoclass:: ComponentwiseOrder
:members:

.. autoclass:: ConeTheta2DOrder
:members:

.. autoclass:: ConeOrder3D
:members:

.. autoclass:: ConeOrder3DIceCream
:members:
15 changes: 15 additions & 0 deletions docs/source/ordering_cone.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.. role:: hidden
:class: hidden-section


vectoptal.ordering_cone
===================================

.. automodule:: vectoptal.ordering_cone
.. currentmodule:: vectoptal.ordering_cone

.. autoclass:: OrderingCone
:members:

.. autoclass:: ConeTheta2D
:members:
94 changes: 94 additions & 0 deletions test/test_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from unittest import TestCase

import numpy as np
from matplotlib import pyplot as plt

from vectoptal.ordering_cone import OrderingCone, ConeTheta2D
from vectoptal.order import (
Order,
ComponentwiseOrder,
ConeTheta2DOrder,
ConeOrder3D,
ConeOrder3DIceCream,
)


class TestOrder(TestCase):
"""Test the Order class."""

def test_dominates(self):
ordering_cone = OrderingCone(np.eye(2))
order = Order(ordering_cone)

self.assertTrue(order.dominates(np.array([1, 1]), np.array([0, 0])))
self.assertFalse(order.dominates(np.array([0, 0]), np.array([1, 1])))

def test_get_pareto_set(self):
ordering_cone = OrderingCone(np.eye(2))
order = Order(ordering_cone)
elements = np.array([[0.5, 1], [0, 0], [1, 0.5]])
self.assertListEqual(order.get_pareto_set(elements).tolist(), [0, 2])

ordering_cone = OrderingCone(np.eye(2))
order = Order(ordering_cone)
elements = np.array([[0.5, 1], [0, 0], [1, 0.5]])
self.assertListEqual(order.get_pareto_set_naive(elements).tolist(), [0, 2])

def test_plot_pareto_set(self):
ordering_cone = OrderingCone(np.eye(2))
order = Order(ordering_cone)
elements = np.array([[1, 1], [0, 0], [-1, -1]])

fig = order.plot_pareto_set(elements)
self.assertIsInstance(fig, plt.Figure)

with self.assertRaises(ValueError):
elements = np.zeros((3))
order.plot_pareto_set(elements)

with self.assertRaises(ValueError):
elements = np.zeros((3, 5))
order.plot_pareto_set(elements)


class TestComponentwiseOrder(TestCase):
"""Test the ComponentwiseOrder class."""

def test_init(self):
order = ComponentwiseOrder(2)
self.assertIsInstance(order, Order)
self.assertEqual(order.ordering_cone, OrderingCone(np.eye(2)))


class TestConeTheta2DOrder(TestCase):
"""Test the ConeTheta2DOrder class."""

def test_init(self):
order = ConeTheta2DOrder(45)
self.assertIsInstance(order, Order)
self.assertEqual(order.ordering_cone, ConeTheta2D(45))


class TestConeOrder3D(TestCase):
"""Test the ConeOrder3D class."""

def test_init(self):
with self.assertRaises(ValueError):
order = ConeOrder3D(cone_type="weird_3d_cone_type")

for cone_type in ["acute", "right", "obtuse"]:
with self.subTest(cone_type=cone_type):
order = ConeOrder3D(cone_type)
self.assertIsInstance(order, Order)
self.assertTrue(np.allclose(np.linalg.norm(order.ordering_cone.W, axis=1), 1))


class TestConeOrder3DIceCream(TestCase):
"""Test the ConeOrder3DIceCream class."""

def test_init(self):
for num_halfspace in range(3, 5):
with self.subTest(num_halfspace=num_halfspace):
order = ConeOrder3DIceCream(60, num_halfspace)
self.assertIsInstance(order, Order)
self.assertTrue(np.allclose(np.linalg.norm(order.ordering_cone.W, axis=1), 1))
78 changes: 78 additions & 0 deletions test/test_ordering_cone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from unittest import TestCase, mock

import numpy as np

from vectoptal.ordering_cone import OrderingCone, ConeTheta2D


class TestOrderingCone(TestCase):
"""
Test the OrderingCone class.
"""

def test_is_inside(self):
W = [[1, 0], [0, 1]]
ordering_cone = OrderingCone(W)

self.assertTrue(ordering_cone.is_inside([1, 1]))
self.assertTrue(ordering_cone.is_inside([0, 0]))
self.assertFalse(ordering_cone.is_inside([-1, -1]))

W = [[-1, 0], [0, -1]]
ordering_cone = OrderingCone(W)

self.assertFalse(ordering_cone.is_inside([1, 1]))
self.assertTrue(ordering_cone.is_inside([-1, -1]))

def test_plot(self):
with mock.patch("vectoptal.ordering_cone.plot_2d_cone") as mock_plot:
W = np.eye(2)
ordering_cone = OrderingCone(W)
ordering_cone.plot()

mock_plot.assert_called_once()

with mock.patch("vectoptal.ordering_cone.plot_3d_cone") as mock_plot:
W = np.eye(3)
ordering_cone = OrderingCone(W)
ordering_cone.plot()

mock_plot.assert_called_once()

with self.assertRaises(ValueError):
W = np.eye(4)
ordering_cone = OrderingCone(W)
ordering_cone.plot()

def test_equal(self):
W = [[1, 0], [0, 1]]
ordering_cone1 = OrderingCone(W)
ordering_cone2 = OrderingCone(W)

self.assertEqual(ordering_cone1, ordering_cone2)

W = [[1, 0], [0, 2]]
ordering_cone2 = OrderingCone(W)

self.assertNotEqual(ordering_cone1, ordering_cone2)


class TestConeTheta2D(TestCase):
"""
Test the OrderingCone class.
"""

def test_init(self):
degree = 45
angle_rad = np.deg2rad(degree)

ordering_cone = ConeTheta2D(degree)
self.assertEqual(ordering_cone.cone_degree, degree)
self.assertAlmostEqual(ordering_cone.beta, 1 / np.sin(angle_rad))

def test_plot(self):
with mock.patch("vectoptal.ordering_cone.plot_2d_theta_cone") as mock_plot:
ordering_cone = ConeTheta2D(45)
ordering_cone.plot()

mock_plot.assert_called_once()
Loading

0 comments on commit 96ac8de

Please sign in to comment.