@@ -1564,3 +1564,318 @@ function setup_test(
15641564 )
15651565 return
15661566end
1567+
1568+ function _test_matrix_norm_cone (
1569+ model:: MOI.ModelLike ,
1570+ config:: Config{T} ,
1571+ set:: Union{MOI.NormSpectralCone,MOI.NormNuclearCone} ,
1572+ b:: Union{Nothing,Vector{T}} ,
1573+ ) where {T}
1574+ @requires _supports (config, MOI. optimize!)
1575+ F = b == nothing ? MOI. VectorOfVariables : MOI. VectorAffineFunction{T}
1576+ @requires MOI. supports_constraint (model, F, typeof (set))
1577+ t = MOI. add_variable (model)
1578+ X = MOI. add_variables (model, 6 )
1579+ f = if b === nothing
1580+ MOI. VectorOfVariables ([t; X])
1581+ else
1582+ fx = MOI. Utilities. operate .(+ , T, X, b)
1583+ MOI. Utilities. operate (vcat, T, t, fx... )
1584+ end
1585+ MOI. add_constraint (model, f, set)
1586+ for i in 1 : 6
1587+ MOI. add_constraint (model, X[i], MOI. EqualTo {T} (i))
1588+ end
1589+ MOI. set (model, MOI. ObjectiveSense (), MOI. MIN_SENSE)
1590+ MOI. set (model, MOI. ObjectiveFunction {MOI.VariableIndex} (), t)
1591+ MOI. optimize! (model)
1592+ x_result = MOI. get (model, MOI. VariablePrimal (), X)
1593+ @test ≈ (x_result, 1 : 6 , config)
1594+ Y = reshape (x_result .+ something (b, T (0 )), set. row_dim, set. column_dim)
1595+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1596+ # type when computing the singular values.
1597+ σ = LinearAlgebra. svdvals (convert (Matrix{Float64}, Y))
1598+ result = set isa MOI. NormSpectralCone ? maximum (σ) : sum (σ)
1599+ @test ≈ (MOI. get (model, MOI. VariablePrimal (), t), result, config)
1600+ return
1601+ end
1602+
1603+ function test_NormSpectralCone_VectorOfVariables_without_transform (
1604+ model:: MOI.ModelLike ,
1605+ config:: Config ,
1606+ )
1607+ _test_matrix_norm_cone (model, config, MOI. NormSpectralCone (3 , 2 ), nothing )
1608+ return
1609+ end
1610+
1611+ function setup_test (
1612+ :: typeof (test_NormSpectralCone_VectorOfVariables_without_transform),
1613+ model:: MOIU.MockOptimizer ,
1614+ :: Config{T} ,
1615+ ) where {T}
1616+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1617+ # type when computing the result.
1618+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1619+ t = LinearAlgebra. opnorm (reshape (result, 3 , 2 ))
1620+ MOIU. set_mock_optimize! (
1621+ model,
1622+ (mock:: MOIU.MockOptimizer ) ->
1623+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1624+ )
1625+ return
1626+ end
1627+
1628+ function test_NormSpectralCone_VectorOfVariables_with_transform (
1629+ model:: MOI.ModelLike ,
1630+ config:: Config ,
1631+ )
1632+ _test_matrix_norm_cone (model, config, MOI. NormSpectralCone (2 , 3 ), nothing )
1633+ return
1634+ end
1635+
1636+ function setup_test (
1637+ :: typeof (test_NormSpectralCone_VectorOfVariables_with_transform),
1638+ model:: MOIU.MockOptimizer ,
1639+ :: Config{T} ,
1640+ ) where {T}
1641+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1642+ # type when computing the result.
1643+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1644+ t = LinearAlgebra. opnorm (reshape (result, 2 , 3 ))
1645+ MOIU. set_mock_optimize! (
1646+ model,
1647+ (mock:: MOIU.MockOptimizer ) ->
1648+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1649+ )
1650+ return
1651+ end
1652+
1653+ function test_NormSpectralCone_VectorAffineFunction_without_transform (
1654+ model:: MOI.ModelLike ,
1655+ config:: Config{T} ,
1656+ ) where {T}
1657+ b = convert (Vector{T}, 7 : 12 )
1658+ _test_matrix_norm_cone (model, config, MOI. NormSpectralCone (3 , 2 ), b)
1659+ return
1660+ end
1661+
1662+ function setup_test (
1663+ :: typeof (test_NormSpectralCone_VectorAffineFunction_without_transform),
1664+ model:: MOIU.MockOptimizer ,
1665+ :: Config{T} ,
1666+ ) where {T}
1667+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1668+ # type when computing the result.
1669+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1670+ t = LinearAlgebra. opnorm (reshape (result + collect (7 : 12 ), 3 , 2 ))
1671+ MOIU. set_mock_optimize! (
1672+ model,
1673+ (mock:: MOIU.MockOptimizer ) ->
1674+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1675+ )
1676+ return
1677+ end
1678+
1679+ function test_NormSpectralCone_VectorAffineFunction_with_transform (
1680+ model:: MOI.ModelLike ,
1681+ config:: Config{T} ,
1682+ ) where {T}
1683+ b = convert (Vector{T}, 7 : 12 )
1684+ _test_matrix_norm_cone (model, config, MOI. NormSpectralCone (2 , 3 ), b)
1685+ return
1686+ end
1687+
1688+ function setup_test (
1689+ :: typeof (test_NormSpectralCone_VectorAffineFunction_with_transform),
1690+ model:: MOIU.MockOptimizer ,
1691+ :: Config{T} ,
1692+ ) where {T}
1693+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1694+ # type when computing the result.
1695+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1696+ t = LinearAlgebra. opnorm (reshape (result + collect (7 : 12 ), 2 , 3 ))
1697+ MOIU. set_mock_optimize! (
1698+ model,
1699+ (mock:: MOIU.MockOptimizer ) ->
1700+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1701+ )
1702+ return
1703+ end
1704+
1705+ function test_NormNuclearCone_VectorOfVariables_without_transform (
1706+ model:: MOI.ModelLike ,
1707+ config:: Config ,
1708+ )
1709+ _test_matrix_norm_cone (model, config, MOI. NormNuclearCone (3 , 2 ), nothing )
1710+ return
1711+ end
1712+
1713+ function setup_test (
1714+ :: typeof (test_NormNuclearCone_VectorOfVariables_without_transform),
1715+ model:: MOIU.MockOptimizer ,
1716+ :: Config{T} ,
1717+ ) where {T}
1718+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1719+ # type when computing the result.
1720+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1721+ t = sum (LinearAlgebra. svdvals (reshape (result, 3 , 2 )))
1722+ MOIU. set_mock_optimize! (
1723+ model,
1724+ (mock:: MOIU.MockOptimizer ) ->
1725+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1726+ )
1727+ return
1728+ end
1729+
1730+ function test_NormNuclearCone_VectorOfVariables_with_transform (
1731+ model:: MOI.ModelLike ,
1732+ config:: Config ,
1733+ )
1734+ _test_matrix_norm_cone (model, config, MOI. NormNuclearCone (2 , 3 ), nothing )
1735+ return
1736+ end
1737+
1738+ function setup_test (
1739+ :: typeof (test_NormNuclearCone_VectorOfVariables_with_transform),
1740+ model:: MOIU.MockOptimizer ,
1741+ :: Config{T} ,
1742+ ) where {T}
1743+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1744+ # type when computing the result.
1745+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1746+ t = sum (LinearAlgebra. svdvals (reshape (result, 2 , 3 )))
1747+ MOIU. set_mock_optimize! (
1748+ model,
1749+ (mock:: MOIU.MockOptimizer ) ->
1750+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1751+ )
1752+ return
1753+ end
1754+
1755+ function test_NormNuclearCone_VectorAffineFunction_without_transform (
1756+ model:: MOI.ModelLike ,
1757+ config:: Config{T} ,
1758+ ) where {T}
1759+ b = convert (Vector{T}, 7 : 12 )
1760+ _test_matrix_norm_cone (model, config, MOI. NormNuclearCone (3 , 2 ), b)
1761+ return
1762+ end
1763+
1764+ function setup_test (
1765+ :: typeof (test_NormNuclearCone_VectorAffineFunction_without_transform),
1766+ model:: MOIU.MockOptimizer ,
1767+ :: Config{T} ,
1768+ ) where {T}
1769+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1770+ # type when computing the result.
1771+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1772+ t = sum (LinearAlgebra. svdvals (reshape (result + collect (7 : 12 ), 3 , 2 )))
1773+ MOIU. set_mock_optimize! (
1774+ model,
1775+ (mock:: MOIU.MockOptimizer ) ->
1776+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1777+ )
1778+ return
1779+ end
1780+
1781+ function test_NormNuclearCone_VectorAffineFunction_with_transform (
1782+ model:: MOI.ModelLike ,
1783+ config:: Config{T} ,
1784+ ) where {T}
1785+ b = convert (Vector{T}, 7 : 12 )
1786+ _test_matrix_norm_cone (model, config, MOI. NormNuclearCone (2 , 3 ), b)
1787+ return
1788+ end
1789+
1790+ function setup_test (
1791+ :: typeof (test_NormNuclearCone_VectorAffineFunction_with_transform),
1792+ model:: MOIU.MockOptimizer ,
1793+ :: Config{T} ,
1794+ ) where {T}
1795+ # svdvals doesn't work for BigFloat etc. So don't use `T` as the element
1796+ # type when computing the result.
1797+ result = [1 , 2 , 3 , 4 , 5 , 6 ]
1798+ t = sum (LinearAlgebra. svdvals (reshape (result + collect (7 : 12 ), 2 , 3 )))
1799+ MOIU. set_mock_optimize! (
1800+ model,
1801+ (mock:: MOIU.MockOptimizer ) ->
1802+ MOIU. mock_optimize! (mock, MOI. OPTIMAL, T[t; result]),
1803+ )
1804+ return
1805+ end
1806+
1807+ function test_HermitianPSDCone_basic (
1808+ model:: MOI.ModelLike ,
1809+ config:: Config{T} ,
1810+ ) where {T}
1811+ @requires _supports (config, MOI. optimize!)
1812+ S = MOI. HermitianPositiveSemidefiniteConeTriangle
1813+ @requires MOI. supports_constraint (model, MOI. VectorAffineFunction{T}, S)
1814+ x = MOI. add_variables (model, 9 )
1815+ for i in eachindex (x)
1816+ MOI. add_constraint (model, x[i], MOI. EqualTo {T} (i))
1817+ end
1818+ b = T[12 , 0 , 12 , 0 , 0 , 12 , 0 , 0 , 0 ]
1819+ f = MOI. Utilities. operate (vcat, T, MOI. Utilities. operate .(+ , T, x, b)... )
1820+ set = MOI. HermitianPositiveSemidefiniteConeTriangle (3 )
1821+ MOI. add_constraint (model, f, set)
1822+ MOI. optimize! (model)
1823+ MOI. get (model, MOI. TerminationStatus ()) == config. optimal_status
1824+ @test ≈ (MOI. get (model, MOI. VariablePrimal (), x), 1 : 9 , config)
1825+ return
1826+ end
1827+
1828+ function setup_test (
1829+ :: typeof (test_HermitianPSDCone_basic),
1830+ model:: MOIU.MockOptimizer ,
1831+ :: Config{T} ,
1832+ ) where {T}
1833+ MOIU. set_mock_optimize! (
1834+ model,
1835+ (mock:: MOIU.MockOptimizer ) -> MOIU. mock_optimize! (
1836+ mock,
1837+ MOI. OPTIMAL,
1838+ T[1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ],
1839+ ),
1840+ )
1841+ return
1842+ end
1843+
1844+ function test_HermitianPSDCone_min_t (
1845+ model:: MOI.ModelLike ,
1846+ config:: Config{T} ,
1847+ ) where {T}
1848+ @requires _supports (config, MOI. optimize!)
1849+ S = MOI. HermitianPositiveSemidefiniteConeTriangle
1850+ @requires MOI. supports_constraint (model, MOI. VectorAffineFunction{T}, S)
1851+ t = MOI. add_variable (model)
1852+ x = MOI. add_variables (model, 9 )
1853+ for (i, xi) in enumerate (x)
1854+ MOI. add_constraint (model, xi, MOI. EqualTo {T} (i))
1855+ end
1856+ bt = Union{MOI. VariableIndex,T}[t, T (0 ), t, T (0 ), T (0 ), t, T (0 ), T (0 ), T (0 )]
1857+ f = MOI. Utilities. operate (vcat, T, MOI. Utilities. operate .(+ , T, x, bt)... )
1858+ set = MOI. HermitianPositiveSemidefiniteConeTriangle (3 )
1859+ MOI. add_constraint (model, f, set)
1860+ MOI. set (model, MOI. ObjectiveSense (), MOI. MIN_SENSE)
1861+ MOI. set (model, MOI. ObjectiveFunction {MOI.VariableIndex} (), t)
1862+ MOI. optimize! (model)
1863+ MOI. get (model, MOI. TerminationStatus ()) == config. optimal_status
1864+ x_result = MOI. get (model, MOI. VariablePrimal (), x)
1865+ @test ≈ (x_result, 1 : 9 , config)
1866+ @test ≈ (MOI. get (model, MOI. VariablePrimal (), t), 11.034899152582094 , config)
1867+ return
1868+ end
1869+
1870+ function setup_test (
1871+ :: typeof (test_HermitianPSDCone_min_t),
1872+ model:: MOIU.MockOptimizer ,
1873+ :: Config{T} ,
1874+ ) where {T}
1875+ x = T[11.034899152582094 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
1876+ MOIU. set_mock_optimize! (
1877+ model,
1878+ (mock:: MOIU.MockOptimizer ) -> MOIU. mock_optimize! (mock, MOI. OPTIMAL, x),
1879+ )
1880+ return
1881+ end
0 commit comments