gonum.org/v1/gonum@v0.14.0/optimize/unconstrained_test.go (about) 1 // Copyright ©2014 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package optimize 6 7 import ( 8 "fmt" 9 "math" 10 "testing" 11 12 "gonum.org/v1/gonum/floats" 13 "gonum.org/v1/gonum/mat" 14 "gonum.org/v1/gonum/optimize/functions" 15 ) 16 17 type unconstrainedTest struct { 18 // name is the name of the test. 19 name string 20 // p is the optimization problem to be solved. 21 p Problem 22 // x is the initial guess. 23 x []float64 24 // gradTol is the absolute gradient tolerance for the test. If gradTol == 0, 25 // the default value of 1e-12 will be used. 26 gradTol float64 27 // fAbsTol is the absolute function convergence for the test. If fAbsTol == 0, 28 // the default value of 1e-12 will be used. 29 fAbsTol float64 30 // fIter is the number of iterations for function convergence. If fIter == 0, 31 // the default value of 20 will be used. 32 fIter int 33 // long indicates that the test takes long time to finish and will be 34 // excluded if testing.Short returns true. 35 long bool 36 } 37 38 func (t unconstrainedTest) String() string { 39 dim := len(t.x) 40 if dim <= 10 { 41 // Print the initial X only for small-dimensional problems. 42 return fmt.Sprintf("F: %v\nDim: %v\nInitial X: %v\nGradientThreshold: %v", 43 t.name, dim, t.x, t.gradTol) 44 } 45 return fmt.Sprintf("F: %v\nDim: %v\nGradientThreshold: %v", 46 t.name, dim, t.gradTol) 47 } 48 49 var gradFreeTests = []unconstrainedTest{ 50 { 51 name: "Beale", 52 p: Problem{ 53 Func: functions.Beale{}.Func, 54 }, 55 x: []float64{1, 1}, 56 }, 57 { 58 name: "BiggsEXP6", 59 p: Problem{ 60 Func: functions.BiggsEXP6{}.Func, 61 }, 62 x: []float64{1, 2, 1, 1, 1, 1}, 63 }, 64 { 65 name: "BrownAndDennis", 66 p: Problem{ 67 Func: functions.BrownAndDennis{}.Func, 68 }, 69 x: []float64{25, 5, -5, -1}, 70 }, 71 { 72 name: "ExtendedRosenbrock", 73 p: Problem{ 74 Func: functions.ExtendedRosenbrock{}.Func, 75 }, 76 x: []float64{-10, 10}, 77 }, 78 { 79 name: "ExtendedRosenbrock", 80 p: Problem{ 81 Func: functions.ExtendedRosenbrock{}.Func, 82 }, 83 x: []float64{-5, 4, 16, 3}, 84 }, 85 } 86 87 var gradientDescentTests = []unconstrainedTest{ 88 { 89 name: "Beale", 90 p: Problem{ 91 Func: functions.Beale{}.Func, 92 Grad: functions.Beale{}.Grad, 93 }, 94 x: []float64{1, 1}, 95 }, 96 { 97 name: "Beale", 98 p: Problem{ 99 Func: functions.Beale{}.Func, 100 Grad: functions.Beale{}.Grad, 101 }, 102 x: []float64{3.00001, 0.50001}, 103 }, 104 { 105 name: "BiggsEXP2", 106 p: Problem{ 107 Func: functions.BiggsEXP2{}.Func, 108 Grad: functions.BiggsEXP2{}.Grad, 109 }, 110 x: []float64{1, 2}, 111 }, 112 { 113 name: "BiggsEXP2", 114 p: Problem{ 115 Func: functions.BiggsEXP2{}.Func, 116 Grad: functions.BiggsEXP2{}.Grad, 117 }, 118 x: []float64{1.00001, 10.00001}, 119 }, 120 { 121 name: "BiggsEXP3", 122 p: Problem{ 123 Func: functions.BiggsEXP3{}.Func, 124 Grad: functions.BiggsEXP3{}.Grad, 125 }, 126 x: []float64{1, 2, 1}, 127 }, 128 { 129 name: "BiggsEXP3", 130 p: Problem{ 131 Func: functions.BiggsEXP3{}.Func, 132 Grad: functions.BiggsEXP3{}.Grad, 133 }, 134 x: []float64{1.00001, 10.00001, 3.00001}, 135 }, 136 { 137 name: "ExtendedRosenbrock", 138 p: Problem{ 139 Func: functions.ExtendedRosenbrock{}.Func, 140 Grad: functions.ExtendedRosenbrock{}.Grad, 141 }, 142 x: []float64{-1.2, 1}, 143 gradTol: 1e-10, 144 }, 145 { 146 name: "ExtendedRosenbrock", 147 p: Problem{ 148 Func: functions.ExtendedRosenbrock{}.Func, 149 Grad: functions.ExtendedRosenbrock{}.Grad, 150 }, 151 x: []float64{1.00001, 1.00001}, 152 gradTol: 1e-10, 153 }, 154 { 155 name: "ExtendedRosenbrock", 156 p: Problem{ 157 Func: functions.ExtendedRosenbrock{}.Func, 158 Grad: functions.ExtendedRosenbrock{}.Grad, 159 }, 160 x: []float64{-1.2, 1, -1.2}, 161 gradTol: 1e-10, 162 }, 163 { 164 name: "ExtendedRosenbrock", 165 p: Problem{ 166 Func: functions.ExtendedRosenbrock{}.Func, 167 Grad: functions.ExtendedRosenbrock{}.Grad, 168 }, 169 x: []float64{-120, 100, 50}, 170 long: true, 171 }, 172 { 173 name: "ExtendedRosenbrock", 174 p: Problem{ 175 Func: functions.ExtendedRosenbrock{}.Func, 176 Grad: functions.ExtendedRosenbrock{}.Grad, 177 }, 178 x: []float64{1, 1, 1}, 179 }, 180 { 181 name: "ExtendedRosenbrock", 182 p: Problem{ 183 Func: functions.ExtendedRosenbrock{}.Func, 184 Grad: functions.ExtendedRosenbrock{}.Grad, 185 }, 186 x: []float64{1.00001, 1.00001, 1.00001}, 187 gradTol: 1e-8, 188 }, 189 { 190 name: "Gaussian", 191 p: Problem{ 192 Func: functions.Gaussian{}.Func, 193 Grad: functions.Gaussian{}.Grad, 194 }, 195 x: []float64{0.4, 1, 0}, 196 gradTol: 1e-9, 197 }, 198 { 199 name: "Gaussian", 200 p: Problem{ 201 Func: functions.Gaussian{}.Func, 202 Grad: functions.Gaussian{}.Grad, 203 }, 204 x: []float64{0.3989561, 1.0000191, 0}, 205 gradTol: 1e-9, 206 }, 207 { 208 name: "HelicalValley", 209 p: Problem{ 210 Func: functions.HelicalValley{}.Func, 211 Grad: functions.HelicalValley{}.Grad, 212 }, 213 x: []float64{-1, 0, 0}, 214 }, 215 { 216 name: "HelicalValley", 217 p: Problem{ 218 Func: functions.HelicalValley{}.Func, 219 Grad: functions.HelicalValley{}.Grad, 220 }, 221 x: []float64{1.00001, 0.00001, 0.00001}, 222 }, 223 { 224 name: "Trigonometric", 225 p: Problem{ 226 Func: functions.Trigonometric{}.Func, 227 Grad: functions.Trigonometric{}.Grad, 228 }, 229 x: []float64{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, 230 gradTol: 1e-7, 231 }, 232 { 233 name: "Trigonometric", 234 p: Problem{ 235 Func: functions.Trigonometric{}.Func, 236 Grad: functions.Trigonometric{}.Grad, 237 }, 238 x: []float64{0.042964, 0.043976, 0.045093, 0.046338, 0.047744, 239 0.049354, 0.051237, 0.195209, 0.164977, 0.060148}, 240 gradTol: 1e-8, 241 }, 242 newVariablyDimensioned(2, 0), 243 { 244 name: "VariablyDimensioned", 245 p: Problem{ 246 Func: functions.VariablyDimensioned{}.Func, 247 Grad: functions.VariablyDimensioned{}.Grad, 248 }, 249 x: []float64{1.00001, 1.00001}, 250 }, 251 newVariablyDimensioned(10, 0), 252 { 253 name: "VariablyDimensioned", 254 p: Problem{ 255 Func: functions.VariablyDimensioned{}.Func, 256 Grad: functions.VariablyDimensioned{}.Grad, 257 }, 258 x: []float64{1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001}, 259 }, 260 } 261 262 var cgTests = []unconstrainedTest{ 263 { 264 name: "BiggsEXP4", 265 p: Problem{ 266 Func: functions.BiggsEXP4{}.Func, 267 Grad: functions.BiggsEXP4{}.Grad, 268 }, 269 x: []float64{1, 2, 1, 1}, 270 }, 271 { 272 name: "BiggsEXP4", 273 p: Problem{ 274 Func: functions.BiggsEXP4{}.Func, 275 Grad: functions.BiggsEXP4{}.Grad, 276 }, 277 x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, 278 }, 279 { 280 name: "BiggsEXP5", 281 p: Problem{ 282 Func: functions.BiggsEXP5{}.Func, 283 Grad: functions.BiggsEXP5{}.Grad, 284 }, 285 x: []float64{1, 2, 1, 1, 1}, 286 gradTol: 1e-7, 287 }, 288 { 289 name: "BiggsEXP5", 290 p: Problem{ 291 Func: functions.BiggsEXP5{}.Func, 292 Grad: functions.BiggsEXP5{}.Grad, 293 }, 294 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, 295 }, 296 { 297 name: "BiggsEXP6", 298 p: Problem{ 299 Func: functions.BiggsEXP6{}.Func, 300 Grad: functions.BiggsEXP6{}.Grad, 301 }, 302 x: []float64{1, 2, 1, 1, 1, 1}, 303 gradTol: 1e-7, 304 }, 305 { 306 name: "BiggsEXP6", 307 p: Problem{ 308 Func: functions.BiggsEXP6{}.Func, 309 Grad: functions.BiggsEXP6{}.Grad, 310 }, 311 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, 312 gradTol: 1e-8, 313 }, 314 { 315 name: "Box3D", 316 p: Problem{ 317 Func: functions.Box3D{}.Func, 318 Grad: functions.Box3D{}.Grad, 319 }, 320 x: []float64{0, 10, 20}, 321 }, 322 { 323 name: "Box3D", 324 p: Problem{ 325 Func: functions.Box3D{}.Func, 326 Grad: functions.Box3D{}.Grad, 327 }, 328 x: []float64{1.00001, 10.00001, 1.00001}, 329 }, 330 { 331 name: "Box3D", 332 p: Problem{ 333 Func: functions.Box3D{}.Func, 334 Grad: functions.Box3D{}.Grad, 335 }, 336 x: []float64{100.00001, 100.00001, 0.00001}, 337 }, 338 { 339 name: "ExtendedPowellSingular", 340 p: Problem{ 341 Func: functions.ExtendedPowellSingular{}.Func, 342 Grad: functions.ExtendedPowellSingular{}.Grad, 343 }, 344 x: []float64{3, -1, 0, 3}, 345 }, 346 { 347 name: "ExtendedPowellSingular", 348 p: Problem{ 349 Func: functions.ExtendedPowellSingular{}.Func, 350 Grad: functions.ExtendedPowellSingular{}.Grad, 351 }, 352 x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, 353 }, 354 { 355 name: "ExtendedPowellSingular", 356 p: Problem{ 357 Func: functions.ExtendedPowellSingular{}.Func, 358 Grad: functions.ExtendedPowellSingular{}.Grad, 359 }, 360 x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, 361 gradTol: 1e-8, 362 }, 363 { 364 name: "ExtendedPowellSingular", 365 p: Problem{ 366 Func: functions.ExtendedPowellSingular{}.Func, 367 Grad: functions.ExtendedPowellSingular{}.Grad, 368 }, 369 x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, 370 }, 371 { 372 name: "ExtendedRosenbrock", 373 p: Problem{ 374 Func: functions.ExtendedRosenbrock{}.Func, 375 Grad: functions.ExtendedRosenbrock{}.Grad, 376 }, 377 x: []float64{-1.2, 1, -1.2, 1}, 378 }, 379 { 380 name: "ExtendedRosenbrock", 381 p: Problem{ 382 Func: functions.ExtendedRosenbrock{}.Func, 383 Grad: functions.ExtendedRosenbrock{}.Grad, 384 }, 385 x: []float64{1e4, 1e4}, 386 gradTol: 1e-10, 387 }, 388 { 389 name: "ExtendedRosenbrock", 390 p: Problem{ 391 Func: functions.ExtendedRosenbrock{}.Func, 392 Grad: functions.ExtendedRosenbrock{}.Grad, 393 }, 394 x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, 395 gradTol: 1e-10, 396 }, 397 { 398 name: "PenaltyI", 399 p: Problem{ 400 Func: functions.PenaltyI{}.Func, 401 Grad: functions.PenaltyI{}.Grad, 402 }, 403 x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 404 gradTol: 1e-9, 405 }, 406 { 407 name: "PenaltyI", 408 p: Problem{ 409 Func: functions.PenaltyI{}.Func, 410 Grad: functions.PenaltyI{}.Grad, 411 }, 412 x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, 413 gradTol: 1e-10, 414 }, 415 { 416 name: "PenaltyI", 417 p: Problem{ 418 Func: functions.PenaltyI{}.Func, 419 Grad: functions.PenaltyI{}.Grad, 420 }, 421 x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 422 0.1581, 0.1581, 0.1581, 0.1581}, 423 gradTol: 1e-10, 424 }, 425 { 426 name: "PenaltyII", 427 p: Problem{ 428 Func: functions.PenaltyII{}.Func, 429 Grad: functions.PenaltyII{}.Grad, 430 }, 431 x: []float64{0.5, 0.5, 0.5, 0.5}, 432 gradTol: 1e-8, 433 }, 434 { 435 name: "PenaltyII", 436 p: Problem{ 437 Func: functions.PenaltyII{}.Func, 438 Grad: functions.PenaltyII{}.Grad, 439 }, 440 x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, 441 gradTol: 1e-8, 442 }, 443 { 444 name: "PenaltyII", 445 p: Problem{ 446 Func: functions.PenaltyII{}.Func, 447 Grad: functions.PenaltyII{}.Grad, 448 }, 449 x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, 450 0.11862, 0.19214, 0.34732, 0.36916}, 451 gradTol: 1e-6, 452 }, 453 { 454 name: "PowellBadlyScaled", 455 p: Problem{ 456 Func: functions.PowellBadlyScaled{}.Func, 457 Grad: functions.PowellBadlyScaled{}.Grad, 458 }, 459 x: []float64{1.09815e-05, 9.10614}, 460 gradTol: 1e-8, 461 }, 462 newVariablyDimensioned(100, 1e-10), 463 newVariablyDimensioned(1000, 1e-7), 464 newVariablyDimensioned(10000, 1e-4), 465 { 466 name: "Watson", 467 p: Problem{ 468 Func: functions.Watson{}.Func, 469 Grad: functions.Watson{}.Grad, 470 }, 471 x: []float64{0, 0, 0, 0, 0, 0}, 472 gradTol: 1e-6, 473 }, 474 { 475 name: "Watson", 476 p: Problem{ 477 Func: functions.Watson{}.Func, 478 Grad: functions.Watson{}.Grad, 479 }, 480 x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, 481 gradTol: 1e-6, 482 }, 483 { 484 name: "Watson", 485 p: Problem{ 486 Func: functions.Watson{}.Func, 487 Grad: functions.Watson{}.Grad, 488 }, 489 x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 490 gradTol: 1e-6, 491 long: true, 492 }, 493 { 494 name: "Watson", 495 p: Problem{ 496 Func: functions.Watson{}.Func, 497 Grad: functions.Watson{}.Grad, 498 }, 499 x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, 500 -2.61773, 4.10440, -3.14361, 1.05262}, 501 gradTol: 1e-6, 502 }, 503 { 504 name: "Wood", 505 p: Problem{ 506 Func: functions.Wood{}.Func, 507 Grad: functions.Wood{}.Grad, 508 }, 509 x: []float64{-3, -1, -3, -1}, 510 gradTol: 1e-6, 511 }, 512 } 513 514 var quasiNewtonTests = []unconstrainedTest{ 515 { 516 name: "BiggsEXP4", 517 p: Problem{ 518 Func: functions.BiggsEXP4{}.Func, 519 Grad: functions.BiggsEXP4{}.Grad, 520 }, 521 x: []float64{1, 2, 1, 1}, 522 }, 523 { 524 name: "BiggsEXP4", 525 p: Problem{ 526 Func: functions.BiggsEXP4{}.Func, 527 Grad: functions.BiggsEXP4{}.Grad, 528 }, 529 x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, 530 }, 531 { 532 name: "BiggsEXP5", 533 p: Problem{ 534 Func: functions.BiggsEXP5{}.Func, 535 Grad: functions.BiggsEXP5{}.Grad, 536 }, 537 x: []float64{1, 2, 1, 1, 1}, 538 gradTol: 1e-10, 539 }, 540 { 541 name: "BiggsEXP5", 542 p: Problem{ 543 Func: functions.BiggsEXP5{}.Func, 544 Grad: functions.BiggsEXP5{}.Grad, 545 }, 546 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, 547 }, 548 { 549 name: "BiggsEXP6", 550 p: Problem{ 551 Func: functions.BiggsEXP6{}.Func, 552 Grad: functions.BiggsEXP6{}.Grad, 553 }, 554 x: []float64{1, 2, 1, 1, 1, 1}, 555 gradTol: 1e-8, 556 }, 557 { 558 name: "BiggsEXP6", 559 p: Problem{ 560 Func: functions.BiggsEXP6{}.Func, 561 Grad: functions.BiggsEXP6{}.Grad, 562 }, 563 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, 564 gradTol: 1e-8, 565 }, 566 { 567 name: "Box3D", 568 p: Problem{ 569 Func: functions.Box3D{}.Func, 570 Grad: functions.Box3D{}.Grad, 571 }, 572 x: []float64{0, 10, 20}, 573 }, 574 { 575 name: "Box3D", 576 p: Problem{ 577 Func: functions.Box3D{}.Func, 578 Grad: functions.Box3D{}.Grad, 579 }, 580 x: []float64{1.00001, 10.00001, 1.00001}, 581 }, 582 { 583 name: "Box3D", 584 p: Problem{ 585 Func: functions.Box3D{}.Func, 586 Grad: functions.Box3D{}.Grad, 587 }, 588 x: []float64{100.00001, 100.00001, 0.00001}, 589 }, 590 { 591 name: "BrownBadlyScaled", 592 p: Problem{ 593 Func: functions.BrownBadlyScaled{}.Func, 594 Grad: functions.BrownBadlyScaled{}.Grad, 595 }, 596 x: []float64{1, 1}, 597 gradTol: 1e-9, 598 }, 599 { 600 name: "BrownBadlyScaled", 601 p: Problem{ 602 Func: functions.BrownBadlyScaled{}.Func, 603 Grad: functions.BrownBadlyScaled{}.Grad, 604 }, 605 x: []float64{1.000001e6, 2.01e-6}, 606 }, 607 { 608 name: "ExtendedPowellSingular", 609 p: Problem{ 610 Func: functions.ExtendedPowellSingular{}.Func, 611 Grad: functions.ExtendedPowellSingular{}.Grad, 612 }, 613 x: []float64{3, -1, 0, 3}, 614 }, 615 { 616 name: "ExtendedPowellSingular", 617 p: Problem{ 618 Func: functions.ExtendedPowellSingular{}.Func, 619 Grad: functions.ExtendedPowellSingular{}.Grad, 620 }, 621 x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, 622 }, 623 { 624 name: "ExtendedPowellSingular", 625 p: Problem{ 626 Func: functions.ExtendedPowellSingular{}.Func, 627 Grad: functions.ExtendedPowellSingular{}.Grad, 628 }, 629 x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, 630 }, 631 { 632 name: "ExtendedPowellSingular", 633 p: Problem{ 634 Func: functions.ExtendedPowellSingular{}.Func, 635 Grad: functions.ExtendedPowellSingular{}.Grad, 636 }, 637 x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, 638 }, 639 { 640 name: "ExtendedRosenbrock", 641 p: Problem{ 642 Func: functions.ExtendedRosenbrock{}.Func, 643 Grad: functions.ExtendedRosenbrock{}.Grad, 644 }, 645 x: []float64{-1.2, 1, -1.2, 1}, 646 }, 647 { 648 name: "ExtendedRosenbrock", 649 p: Problem{ 650 Func: functions.ExtendedRosenbrock{}.Func, 651 Grad: functions.ExtendedRosenbrock{}.Grad, 652 }, 653 x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, 654 }, 655 { 656 name: "Gaussian", 657 p: Problem{ 658 Func: functions.Gaussian{}.Func, 659 Grad: functions.Gaussian{}.Grad, 660 }, 661 x: []float64{0.4, 1, 0}, 662 gradTol: 1e-11, 663 }, 664 { 665 name: "GulfResearchAndDevelopment", 666 p: Problem{ 667 Func: functions.GulfResearchAndDevelopment{}.Func, 668 Grad: functions.GulfResearchAndDevelopment{}.Grad, 669 }, 670 x: []float64{5, 2.5, 0.15}, 671 }, 672 { 673 name: "GulfResearchAndDevelopment", 674 p: Problem{ 675 Func: functions.GulfResearchAndDevelopment{}.Func, 676 Grad: functions.GulfResearchAndDevelopment{}.Grad, 677 }, 678 x: []float64{50.00001, 25.00001, 1.50001}, 679 }, 680 { 681 name: "GulfResearchAndDevelopment", 682 p: Problem{ 683 Func: functions.GulfResearchAndDevelopment{}.Func, 684 Grad: functions.GulfResearchAndDevelopment{}.Grad, 685 }, 686 x: []float64{99.89529, 60.61453, 9.16124}, 687 }, 688 { 689 name: "GulfResearchAndDevelopment", 690 p: Problem{ 691 Func: functions.GulfResearchAndDevelopment{}.Func, 692 Grad: functions.GulfResearchAndDevelopment{}.Grad, 693 }, 694 x: []float64{201.66258, 60.61633, 10.22489}, 695 }, 696 { 697 name: "PenaltyI", 698 p: Problem{ 699 Func: functions.PenaltyI{}.Func, 700 Grad: functions.PenaltyI{}.Grad, 701 }, 702 x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 703 }, 704 { 705 name: "PenaltyI", 706 p: Problem{ 707 Func: functions.PenaltyI{}.Func, 708 Grad: functions.PenaltyI{}.Grad, 709 }, 710 x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, 711 gradTol: 1e-9, 712 }, 713 { 714 name: "PenaltyI", 715 p: Problem{ 716 Func: functions.PenaltyI{}.Func, 717 Grad: functions.PenaltyI{}.Grad, 718 }, 719 x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 720 0.1581, 0.1581, 0.1581, 0.1581}, 721 }, 722 { 723 name: "PenaltyII", 724 p: Problem{ 725 Func: functions.PenaltyII{}.Func, 726 Grad: functions.PenaltyII{}.Grad, 727 }, 728 x: []float64{0.5, 0.5, 0.5, 0.5}, 729 gradTol: 1e-10, 730 }, 731 { 732 name: "PenaltyII", 733 p: Problem{ 734 Func: functions.PenaltyII{}.Func, 735 Grad: functions.PenaltyII{}.Grad, 736 }, 737 x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, 738 gradTol: 1e-10, 739 }, 740 { 741 name: "PenaltyII", 742 p: Problem{ 743 Func: functions.PenaltyII{}.Func, 744 Grad: functions.PenaltyII{}.Grad, 745 }, 746 x: []float64{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, 747 gradTol: 1e-9, 748 }, 749 { 750 name: "PenaltyII", 751 p: Problem{ 752 Func: functions.PenaltyII{}.Func, 753 Grad: functions.PenaltyII{}.Grad, 754 }, 755 x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, 756 0.11862, 0.19214, 0.34732, 0.36916}, 757 gradTol: 1e-9, 758 }, 759 { 760 name: "PowellBadlyScaled", 761 p: Problem{ 762 Func: functions.PowellBadlyScaled{}.Func, 763 Grad: functions.PowellBadlyScaled{}.Grad, 764 }, 765 x: []float64{0, 1}, 766 gradTol: 1e-10, 767 }, 768 { 769 name: "PowellBadlyScaled", 770 p: Problem{ 771 Func: functions.PowellBadlyScaled{}.Func, 772 Grad: functions.PowellBadlyScaled{}.Grad, 773 }, 774 x: []float64{1.09815e-05, 9.10614}, 775 gradTol: 1e-10, 776 }, 777 newVariablyDimensioned(100, 1e-10), 778 { 779 name: "Watson", 780 p: Problem{ 781 Func: functions.Watson{}.Func, 782 Grad: functions.Watson{}.Grad, 783 }, 784 x: []float64{0, 0, 0, 0, 0, 0}, 785 gradTol: 1e-7, 786 }, 787 { 788 name: "Watson", 789 p: Problem{ 790 Func: functions.Watson{}.Func, 791 Grad: functions.Watson{}.Grad, 792 }, 793 x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, 794 gradTol: 1e-7, 795 }, 796 { 797 name: "Watson", 798 p: Problem{ 799 Func: functions.Watson{}.Func, 800 Grad: functions.Watson{}.Grad, 801 }, 802 x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, 803 gradTol: 1e-8, 804 }, 805 { 806 name: "Watson", 807 p: Problem{ 808 Func: functions.Watson{}.Func, 809 Grad: functions.Watson{}.Grad, 810 }, 811 x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, 812 -2.61773, 4.10440, -3.14361, 1.05262}, 813 gradTol: 1e-8, 814 }, 815 } 816 817 var bfgsTests = []unconstrainedTest{ 818 { 819 name: "BiggsEXP6", 820 p: Problem{ 821 Func: functions.BiggsEXP6{}.Func, 822 Grad: functions.BiggsEXP6{}.Grad, 823 }, 824 x: []float64{1, 2, 1, 1, 1, 1}, 825 gradTol: 1e-10, 826 }, 827 { 828 name: "BiggsEXP6", 829 p: Problem{ 830 Func: functions.BiggsEXP6{}.Func, 831 Grad: functions.BiggsEXP6{}.Grad, 832 }, 833 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, 834 gradTol: 1e-10, 835 }, 836 { 837 name: "BrownAndDennis", 838 p: Problem{ 839 Func: functions.BrownAndDennis{}.Func, 840 Grad: functions.BrownAndDennis{}.Grad, 841 }, 842 x: []float64{25, 5, -5, -1}, 843 gradTol: 1e-3, 844 }, 845 { 846 name: "ExtendedRosenbrock", 847 p: Problem{ 848 Func: functions.ExtendedRosenbrock{}.Func, 849 Grad: functions.ExtendedRosenbrock{}.Grad, 850 }, 851 x: []float64{1e5, 1e5}, 852 gradTol: 1e-10, 853 }, 854 { 855 name: "Gaussian", 856 p: Problem{ 857 Func: functions.Gaussian{}.Func, 858 Grad: functions.Gaussian{}.Grad, 859 }, 860 x: []float64{0.398, 1, 0}, 861 gradTol: 1e-11, 862 }, 863 { 864 name: "Wood", 865 p: Problem{ 866 Func: functions.Wood{}.Func, 867 Grad: functions.Wood{}.Grad, 868 }, 869 x: []float64{-3, -1, -3, -1}, 870 }, 871 } 872 873 var lbfgsTests = []unconstrainedTest{ 874 { 875 name: "BiggsEXP6", 876 p: Problem{ 877 Func: functions.BiggsEXP6{}.Func, 878 Grad: functions.BiggsEXP6{}.Grad, 879 }, 880 x: []float64{1, 2, 1, 1, 1, 1}, 881 gradTol: 1e-8, 882 }, 883 { 884 name: "BiggsEXP6", 885 p: Problem{ 886 Func: functions.BiggsEXP6{}.Func, 887 Grad: functions.BiggsEXP6{}.Grad, 888 }, 889 x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, 890 gradTol: 1e-8, 891 }, 892 { 893 name: "ExtendedRosenbrock", 894 p: Problem{ 895 Func: functions.ExtendedRosenbrock{}.Func, 896 Grad: functions.ExtendedRosenbrock{}.Grad, 897 }, 898 x: []float64{1e7, 1e6}, 899 gradTol: 1e-10, 900 }, 901 { 902 name: "Gaussian", 903 p: Problem{ 904 Func: functions.Gaussian{}.Func, 905 Grad: functions.Gaussian{}.Grad, 906 }, 907 x: []float64{0.398, 1, 0}, 908 gradTol: 1e-10, 909 }, 910 newVariablyDimensioned(1000, 1e-8), 911 newVariablyDimensioned(10000, 1e-5), 912 } 913 914 var newtonTests = []unconstrainedTest{ 915 { 916 name: "Beale", 917 p: Problem{ 918 Func: functions.Beale{}.Func, 919 Grad: functions.Beale{}.Grad, 920 Hess: functions.Beale{}.Hess, 921 }, 922 x: []float64{1, 1}, 923 }, 924 { 925 name: "BrownAndDennis", 926 p: Problem{ 927 Func: functions.BrownAndDennis{}.Func, 928 Grad: functions.BrownAndDennis{}.Grad, 929 Hess: functions.BrownAndDennis{}.Hess, 930 }, 931 x: []float64{25, 5, -5, -1}, 932 gradTol: 1e-10, 933 }, 934 { 935 name: "BrownBadlyScaled", 936 p: Problem{ 937 Func: functions.BrownBadlyScaled{}.Func, 938 Grad: functions.BrownBadlyScaled{}.Grad, 939 Hess: functions.BrownBadlyScaled{}.Hess, 940 }, 941 x: []float64{1, 1}, 942 gradTol: 1e-9, 943 }, 944 { 945 name: "PowellBadlyScaled", 946 p: Problem{ 947 Func: functions.PowellBadlyScaled{}.Func, 948 Grad: functions.PowellBadlyScaled{}.Grad, 949 Hess: functions.PowellBadlyScaled{}.Hess, 950 }, 951 x: []float64{0, 1}, 952 gradTol: 1e-10, 953 }, 954 { 955 name: "Watson", 956 p: Problem{ 957 Func: functions.Watson{}.Func, 958 Grad: functions.Watson{}.Grad, 959 Hess: functions.Watson{}.Hess, 960 }, 961 x: []float64{0, 0, 0, 0, 0, 0}, 962 }, 963 { 964 name: "Watson", 965 p: Problem{ 966 Func: functions.Watson{}.Func, 967 Grad: functions.Watson{}.Grad, 968 Hess: functions.Watson{}.Hess, 969 }, 970 x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 971 }, 972 { 973 name: "Wood", 974 p: Problem{ 975 Func: functions.Wood{}.Func, 976 Grad: functions.Wood{}.Grad, 977 Hess: functions.Wood{}.Hess, 978 }, 979 x: []float64{-3, -1, -3, -1}, 980 }, 981 } 982 983 func newVariablyDimensioned(dim int, gradTol float64) unconstrainedTest { 984 x := make([]float64, dim) 985 for i := range x { 986 x[i] = float64(dim-i-1) / float64(dim) 987 } 988 return unconstrainedTest{ 989 name: "VariablyDimensioned", 990 p: Problem{ 991 Func: functions.VariablyDimensioned{}.Func, 992 Grad: functions.VariablyDimensioned{}.Grad, 993 }, 994 x: x, 995 gradTol: gradTol, 996 } 997 } 998 999 func TestLocal(t *testing.T) { 1000 t.Parallel() 1001 var tests []unconstrainedTest 1002 // Mix of functions with and without Grad method. 1003 tests = append(tests, gradFreeTests...) 1004 tests = append(tests, gradientDescentTests...) 1005 testLocal(t, tests, nil) 1006 } 1007 1008 func TestNelderMead(t *testing.T) { 1009 t.Parallel() 1010 var tests []unconstrainedTest 1011 // Mix of functions with and without Grad method. 1012 tests = append(tests, gradFreeTests...) 1013 tests = append(tests, gradientDescentTests...) 1014 testLocal(t, tests, &NelderMead{}) 1015 } 1016 1017 func TestGradientDescent(t *testing.T) { 1018 t.Parallel() 1019 testLocal(t, gradientDescentTests, &GradientDescent{}) 1020 } 1021 1022 func TestGradientDescentBacktracking(t *testing.T) { 1023 t.Parallel() 1024 testLocal(t, gradientDescentTests, &GradientDescent{ 1025 Linesearcher: &Backtracking{ 1026 DecreaseFactor: 0.1, 1027 }, 1028 }) 1029 } 1030 1031 func TestGradientDescentBisection(t *testing.T) { 1032 t.Parallel() 1033 testLocal(t, gradientDescentTests, &GradientDescent{ 1034 Linesearcher: &Bisection{}, 1035 }) 1036 } 1037 1038 func TestCG(t *testing.T) { 1039 t.Parallel() 1040 var tests []unconstrainedTest 1041 tests = append(tests, gradientDescentTests...) 1042 tests = append(tests, cgTests...) 1043 testLocal(t, tests, &CG{}) 1044 } 1045 1046 func TestFletcherReevesQuadStep(t *testing.T) { 1047 t.Parallel() 1048 var tests []unconstrainedTest 1049 tests = append(tests, gradientDescentTests...) 1050 tests = append(tests, cgTests...) 1051 testLocal(t, tests, &CG{ 1052 Variant: &FletcherReeves{}, 1053 InitialStep: &QuadraticStepSize{}, 1054 }) 1055 } 1056 1057 func TestFletcherReevesFirstOrderStep(t *testing.T) { 1058 t.Parallel() 1059 var tests []unconstrainedTest 1060 tests = append(tests, gradientDescentTests...) 1061 tests = append(tests, cgTests...) 1062 testLocal(t, tests, &CG{ 1063 Variant: &FletcherReeves{}, 1064 InitialStep: &FirstOrderStepSize{}, 1065 }) 1066 } 1067 1068 func TestHestenesStiefelQuadStep(t *testing.T) { 1069 t.Parallel() 1070 var tests []unconstrainedTest 1071 tests = append(tests, gradientDescentTests...) 1072 tests = append(tests, cgTests...) 1073 testLocal(t, tests, &CG{ 1074 Variant: &HestenesStiefel{}, 1075 InitialStep: &QuadraticStepSize{}, 1076 }) 1077 } 1078 1079 func TestHestenesStiefelFirstOrderStep(t *testing.T) { 1080 t.Parallel() 1081 var tests []unconstrainedTest 1082 tests = append(tests, gradientDescentTests...) 1083 tests = append(tests, cgTests...) 1084 testLocal(t, tests, &CG{ 1085 Variant: &HestenesStiefel{}, 1086 InitialStep: &FirstOrderStepSize{}, 1087 }) 1088 } 1089 1090 func TestPolakRibiereQuadStep(t *testing.T) { 1091 t.Parallel() 1092 var tests []unconstrainedTest 1093 tests = append(tests, gradientDescentTests...) 1094 tests = append(tests, cgTests...) 1095 testLocal(t, tests, &CG{ 1096 Variant: &PolakRibierePolyak{}, 1097 InitialStep: &QuadraticStepSize{}, 1098 }) 1099 } 1100 1101 func TestPolakRibiereFirstOrderStep(t *testing.T) { 1102 t.Parallel() 1103 var tests []unconstrainedTest 1104 tests = append(tests, gradientDescentTests...) 1105 tests = append(tests, cgTests...) 1106 testLocal(t, tests, &CG{ 1107 Variant: &PolakRibierePolyak{}, 1108 InitialStep: &FirstOrderStepSize{}, 1109 }) 1110 } 1111 1112 func TestDaiYuanQuadStep(t *testing.T) { 1113 t.Parallel() 1114 var tests []unconstrainedTest 1115 tests = append(tests, gradientDescentTests...) 1116 tests = append(tests, cgTests...) 1117 testLocal(t, tests, &CG{ 1118 Variant: &DaiYuan{}, 1119 InitialStep: &QuadraticStepSize{}, 1120 }) 1121 } 1122 1123 func TestDaiYuanFirstOrderStep(t *testing.T) { 1124 t.Parallel() 1125 var tests []unconstrainedTest 1126 tests = append(tests, gradientDescentTests...) 1127 tests = append(tests, cgTests...) 1128 testLocal(t, tests, &CG{ 1129 Variant: &DaiYuan{}, 1130 InitialStep: &FirstOrderStepSize{}, 1131 }) 1132 } 1133 1134 func TestHagerZhangQuadStep(t *testing.T) { 1135 t.Parallel() 1136 var tests []unconstrainedTest 1137 tests = append(tests, gradientDescentTests...) 1138 tests = append(tests, cgTests...) 1139 testLocal(t, tests, &CG{ 1140 Variant: &HagerZhang{}, 1141 InitialStep: &QuadraticStepSize{}, 1142 }) 1143 } 1144 1145 func TestHagerZhangFirstOrderStep(t *testing.T) { 1146 t.Parallel() 1147 var tests []unconstrainedTest 1148 tests = append(tests, gradientDescentTests...) 1149 tests = append(tests, cgTests...) 1150 testLocal(t, tests, &CG{ 1151 Variant: &HagerZhang{}, 1152 InitialStep: &FirstOrderStepSize{}, 1153 }) 1154 } 1155 1156 func TestBFGS(t *testing.T) { 1157 t.Parallel() 1158 var tests []unconstrainedTest 1159 tests = append(tests, gradientDescentTests...) 1160 tests = append(tests, quasiNewtonTests...) 1161 tests = append(tests, bfgsTests...) 1162 testLocal(t, tests, &BFGS{}) 1163 } 1164 1165 func TestLBFGS(t *testing.T) { 1166 t.Parallel() 1167 var tests []unconstrainedTest 1168 tests = append(tests, gradientDescentTests...) 1169 tests = append(tests, quasiNewtonTests...) 1170 tests = append(tests, lbfgsTests...) 1171 testLocal(t, tests, &LBFGS{}) 1172 } 1173 1174 func TestNewton(t *testing.T) { 1175 t.Parallel() 1176 testLocal(t, newtonTests, &Newton{}) 1177 } 1178 1179 func testLocal(t *testing.T, tests []unconstrainedTest, method Method) { 1180 for cas, test := range tests { 1181 if test.long && testing.Short() { 1182 continue 1183 } 1184 1185 settings := &Settings{} 1186 settings.Converger = defaultFunctionConverge() 1187 var uses Available 1188 if method != nil { 1189 var err error 1190 has := availFromProblem(test.p) 1191 uses, err = method.Uses(has) 1192 if err != nil { 1193 t.Errorf("problem and method mismatch: %v", err) 1194 continue 1195 } 1196 } 1197 if method != nil { 1198 // Turn off function convergence checks for gradient-based methods. 1199 if uses.Grad { 1200 settings.Converger = NeverTerminate{} 1201 } 1202 } else { 1203 if test.fIter == 0 { 1204 test.fIter = 20 1205 } 1206 c := settings.Converger.(*FunctionConverge) 1207 c.Iterations = test.fIter 1208 if test.fAbsTol == 0 { 1209 test.fAbsTol = 1e-12 1210 } 1211 c.Absolute = test.fAbsTol 1212 settings.Converger = c 1213 } 1214 if test.gradTol == 0 { 1215 test.gradTol = 1e-12 1216 } 1217 settings.GradientThreshold = test.gradTol 1218 1219 result, err := Minimize(test.p, test.x, settings, method) 1220 if err != nil { 1221 t.Errorf("Case %d: error finding minimum (%v) for:\n%v", cas, err, test) 1222 continue 1223 } 1224 if result == nil { 1225 t.Errorf("Case %d: nil result without error for:\n%v", cas, test) 1226 continue 1227 } 1228 1229 // Check that the function value at the found optimum location is 1230 // equal to result.F. 1231 optF := test.p.Func(result.X) 1232 if optF != result.F { 1233 t.Errorf("Case %d: Function value at the optimum location %v not equal to the returned value %v for:\n%v", 1234 cas, optF, result.F, test) 1235 } 1236 if result.Gradient != nil { 1237 // Evaluate the norm of the gradient at the found optimum location. 1238 g := make([]float64, len(test.x)) 1239 test.p.Grad(g, result.X) 1240 1241 if !floats.Equal(result.Gradient, g) { 1242 t.Errorf("Case %d: Gradient at the optimum location not equal to the returned value for:\n%v", cas, test) 1243 } 1244 1245 optNorm := floats.Norm(g, math.Inf(1)) 1246 // Check that the norm of the gradient at the found optimum location is 1247 // smaller than the tolerance. 1248 if optNorm >= settings.GradientThreshold { 1249 t.Errorf("Case %d: Norm of the gradient at the optimum location %v not smaller than tolerance %v for:\n%v", 1250 cas, optNorm, settings.GradientThreshold, test) 1251 } 1252 } 1253 1254 if method == nil { 1255 // The tests below make sense only if the method used is known. 1256 continue 1257 } 1258 1259 if !uses.Grad && !uses.Hess { 1260 // Gradient-free tests can correctly terminate only with 1261 // FunctionConvergence status. 1262 if result.Status != FunctionConvergence { 1263 t.Errorf("Status not %v, %v instead", FunctionConvergence, result.Status) 1264 } 1265 } 1266 1267 // We are going to restart the solution using known initial data, so 1268 // evaluate them. 1269 settings.InitValues = &Location{} 1270 settings.InitValues.F = test.p.Func(test.x) 1271 if uses.Grad { 1272 settings.InitValues.Gradient = resize(settings.InitValues.Gradient, len(test.x)) 1273 test.p.Grad(settings.InitValues.Gradient, test.x) 1274 } 1275 if uses.Hess { 1276 settings.InitValues.Hessian = mat.NewSymDense(len(test.x), nil) 1277 test.p.Hess(settings.InitValues.Hessian, test.x) 1278 } 1279 1280 // Rerun the test again to make sure that it gets the same answer with 1281 // the same starting condition. Moreover, we are using the initial data. 1282 result2, err2 := Minimize(test.p, test.x, settings, method) 1283 if err2 != nil { 1284 t.Errorf("error finding minimum second time (%v) for:\n%v", err2, test) 1285 continue 1286 } 1287 if result2 == nil { 1288 t.Errorf("second time nil result without error for:\n%v", test) 1289 continue 1290 } 1291 1292 // At the moment all the optimizers are deterministic, so check that we 1293 // get _exactly_ the same answer second time as well. 1294 if result.F != result2.F || !floats.Equal(result.X, result2.X) { 1295 t.Errorf("Different minimum second time for:\n%v", test) 1296 } 1297 1298 // Check that providing initial data reduces the number of evaluations exactly by one. 1299 if result.FuncEvaluations != result2.FuncEvaluations+1 { 1300 t.Errorf("Providing initial data does not reduce the number of Func calls for:\n%v", test) 1301 continue 1302 } 1303 if uses.Grad { 1304 if result.GradEvaluations != result2.GradEvaluations+1 { 1305 t.Errorf("Providing initial data does not reduce the number of Grad calls for:\n%v", test) 1306 continue 1307 } 1308 } 1309 if uses.Hess { 1310 if result.HessEvaluations != result2.HessEvaluations+1 { 1311 t.Errorf("Providing initial data does not reduce the number of Hess calls for:\n%v", test) 1312 continue 1313 } 1314 } 1315 } 1316 } 1317 1318 func TestIssue76(t *testing.T) { 1319 t.Parallel() 1320 p := Problem{ 1321 Func: functions.BrownAndDennis{}.Func, 1322 Grad: functions.BrownAndDennis{}.Grad, 1323 } 1324 // Location very close to the minimum. 1325 x := []float64{-11.594439904886773, 13.203630051265385, -0.40343948776868443, 0.2367787746745986} 1326 s := &Settings{ 1327 MajorIterations: 1000000, 1328 } 1329 m := &GradientDescent{ 1330 GradStopThreshold: 1e-14, 1331 Linesearcher: &Backtracking{}, 1332 } 1333 // We are not interested in the error, only in the returned status. 1334 r, _ := Minimize(p, x, s, m) 1335 // With the above stringent tolerance, the optimizer will never 1336 // successfully reach the minimum. Check if it terminated in a finite 1337 // number of steps. 1338 if r.Status == IterationLimit { 1339 t.Error("Issue https://github.com/gonum/optimize/issues/76 not fixed") 1340 } 1341 } 1342 1343 func TestNelderMeadOneD(t *testing.T) { 1344 t.Parallel() 1345 p := Problem{ 1346 Func: func(x []float64) float64 { return x[0] * x[0] }, 1347 } 1348 x := []float64{10} 1349 m := &NelderMead{} 1350 var s *Settings 1351 result, err := Minimize(p, x, s, m) 1352 if err != nil { 1353 t.Errorf(err.Error()) 1354 } 1355 if !floats.EqualApprox(result.X, []float64{0}, 1e-10) { 1356 t.Errorf("Minimum not found") 1357 } 1358 if m.reflection != 1 { 1359 t.Errorf("Wrong value of reflection") 1360 } 1361 if m.expansion != 2 { 1362 t.Errorf("Wrong value of expansion") 1363 } 1364 if m.contraction != 0.5 { 1365 t.Errorf("Wrong value of contraction") 1366 } 1367 if m.shrink != 0.5 { 1368 t.Errorf("Wrong value of shrink") 1369 } 1370 }