@@ -1446,25 +1446,93 @@ function test_intercept_ForwardDiff_MethodError()
1446
1446
return
1447
1447
end
1448
1448
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
1452
1493
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
1455
1535
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
1461
1537
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