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