@@ -1446,25 +1446,93 @@ function test_intercept_ForwardDiff_MethodError()
14461446 return
14471447end
14481448
1449- end # TestNonlinear
1450-
1451- TestNonlinear. runtests ()
1449+ function test_extract_subexpression ()
1450+ model = Nonlinear. Model ()
1451+ x = MOI. VariableIndex (1 )
1452+ sub = MOI. ScalarNonlinearFunction (:^ , Any[x, 3 ])
1453+ f = MOI. ScalarNonlinearFunction (:+ , Any[sub, sub])
1454+ expr = Nonlinear. parse_expression (model, f)
1455+ @test expr == Nonlinear. Expression (
1456+ [
1457+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 1 , - 1 ),
1458+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 1 ),
1459+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 1 ),
1460+ ],
1461+ Float64[],
1462+ )
1463+ expected_sub = Nonlinear. Expression (
1464+ [
1465+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 4 , 1 )
1466+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 2 )
1467+ Nonlinear. Node (Nonlinear. NODE_VALUE, 1 , 2 )
1468+ ],
1469+ [3.0 ],
1470+ )
1471+ @test model. expressions == [expected_sub]
1472+ @test model. cache[sub] == Nonlinear. ExpressionIndex (1 )
1473+
1474+ h = MOI. ScalarNonlinearFunction (:* , Any[2 , sub, 1 ])
1475+ g = MOI. ScalarNonlinearFunction (:+ , Any[sub, h])
1476+ expr = MOI. Nonlinear. parse_expression (model, g)
1477+ expected_g = Nonlinear. Expression (
1478+ [
1479+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 1 , - 1 )
1480+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 1 )
1481+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 3 , 1 )
1482+ Nonlinear. Node (Nonlinear. NODE_VALUE, 1 , 3 )
1483+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 3 )
1484+ Nonlinear. Node (Nonlinear. NODE_VALUE, 2 , 3 )
1485+ ],
1486+ [2.0 , 1.0 ],
1487+ )
1488+ @test expr == expected_g
1489+ # It should have detected the sub-expressions that was the same as `f`
1490+ @test model. expressions == [expected_sub]
1491+ # This means that it didn't get to extract from `g`, let's also test
1492+ # with extraction by starting with an empty model
14521493
1453- using Revise, Test
1454- import MathOptInterface as MOI
1494+ model = Nonlinear. Model ()
1495+ MOI. Nonlinear. set_objective (model, g)
1496+ @test model. objective == expected_g
1497+ @test model. expressions == [expected_sub]
1498+ # Test that the objective function gets rewritten as we reuse `h`
1499+ # Also test that we don't change the parents in the stack of `h`
1500+ # by creating a long stack
1501+ prod = MOI. ScalarNonlinearFunction (
1502+ :* ,
1503+ [h, x],
1504+ )
1505+ sum = MOI. ScalarNonlinearFunction (
1506+ :* ,
1507+ [x, x, x, x, prod],
1508+ )
1509+ expr = Nonlinear. parse_expression (model, sum)
1510+ @test isempty (model. objective. values)
1511+ @test model. objective. nodes == [
1512+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 1 , - 1 ),
1513+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 1 ),
1514+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 2 , 1 ),
1515+ ]
1516+ @test model. expressions == [expected_sub, Nonlinear. Expression ([
1517+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 3 , 1 ),
1518+ Nonlinear. Node (Nonlinear. NODE_VALUE, 1 , 3 ),
1519+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 1 , 3 ),
1520+ Nonlinear. Node (Nonlinear. NODE_VALUE, 2 , 3 ),
1521+ ], [2.0 , 1.0 ])]
1522+ @test isempty (expr. values)
1523+ @test expr. nodes == [
1524+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 3 , - 1 ),
1525+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 1 ),
1526+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 1 ),
1527+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 1 ),
1528+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 1 ),
1529+ Nonlinear. Node (Nonlinear. NODE_CALL_MULTIVARIATE, 3 , 1 ),
1530+ Nonlinear. Node (Nonlinear. NODE_SUBEXPRESSION, 2 , 6 ),
1531+ Nonlinear. Node (Nonlinear. NODE_MOI_VARIABLE, 1 , 6 ),
1532+ ]
1533+ return
1534+ end
14551535
1456- model = MOI. Nonlinear. Model ()
1457- x = MOI. VariableIndex (1 )
1458- sub = MOI. ScalarNonlinearFunction (:^ , Any[x, 3 ])
1459- func = MOI. ScalarNonlinearFunction (:+ , Any[sub, sub])
1460- expr = MOI. Nonlinear. parse_expression (model, func)
1536+ end # TestNonlinear
14611537
1462- func = MOI. ScalarNonlinearFunction (:+ , Any[sub, sub])
1463- g = MOI. ScalarNonlinearFunction (:+ , Any[
1464- sub,
1465- MOI. ScalarNonlinearFunction (
1466- :* ,
1467- Any[1 , sub]
1468- ),
1469- ])
1470- expr = MOI. Nonlinear. parse_expression (model, g)
1538+ TestNonlinear. runtests ()
0 commit comments