checkbreak.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. '''
  2. This module checks whether to break out of the solver loop.
  3. Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA.
  4. Dedicated to late Professor M. J. D. Powell FRS (1936--2015).
  5. Python translation by Nickolai Belakovski.
  6. '''
  7. from .infos import INFO_DEFAULT, NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED
  8. import numpy as np
  9. def checkbreak_unc(maxfun, nf, f, ftarget, x):
  10. '''
  11. This module checks whether to break out of the solver loop in the unconstrained case.
  12. '''
  13. # Outputs
  14. info = INFO_DEFAULT
  15. # Local variables
  16. srname = "CHECKbreak_UNC"
  17. # Preconditions
  18. assert INFO_DEFAULT not in [NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED], f'NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, and MAXFUN_REACHED differ from INFO_DFT {srname}'
  19. # X does not contain NaN if the initial X does not contain NaN and the subroutines generating
  20. # trust-region/geometry steps work properly so that they never produce a step containing NaN/Inf.
  21. assert not any(np.isnan(x)), f'X does not contain NaN {srname}'
  22. # With the moderated extreme barrier, F cannot be NaN/+Inf.
  23. assert not (any(np.isnan(f)) or any(np.isposinf(f))), f'F is not NaN/+Inf {srname}'
  24. #====================#
  25. # Calculation starts #
  26. #====================#
  27. # Although X should not contain NaN unless there is a bug, we include the following for security.
  28. # X can be Inf, as finite + finite can be Inf numerically.
  29. if any(np.isnan(x)) or any(np.isinf(x)):
  30. info = NAN_INF_X
  31. # Although NAN_INF_F should not happen unless there is a bug, we include the following for security.
  32. if any(np.isnan(f)) or any(np.isposinf(f)):
  33. info = NAN_INF_F
  34. if f <= ftarget:
  35. info = FTARGET_ACHIEVED
  36. if nf >= maxfun:
  37. info = MAXFUN_REACHED
  38. return info
  39. def checkbreak_con(maxfun, nf, cstrv, ctol, f, ftarget, x):
  40. '''
  41. This module checks whether to break out of the solver loop in the constrained case.
  42. '''
  43. # Outputs
  44. info = INFO_DEFAULT
  45. # Local variables
  46. srname = "CHECKbreak_CON"
  47. # Preconditions
  48. assert INFO_DEFAULT not in [NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED], f'NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, and MAXFUN_REACHED differ from INFO_DFT {srname}'
  49. # X does not contain NaN if the initial X does not contain NaN and the subroutines generating
  50. # trust-region/geometry steps work properly so that they never produce a step containing NaN/Inf.
  51. assert not any(np.isnan(x)), f'X does not contain NaN {srname}'
  52. # With the moderated extreme barrier, F or CSTRV cannot be NaN/+Inf.
  53. assert not (np.isnan(f) or np.isposinf(f) or np.isnan(cstrv) or np.isposinf(cstrv)), f'F or CSTRV is not NaN/+Inf {srname}'
  54. #====================#
  55. # Calculation starts #
  56. #====================#
  57. # Although X should not contain NaN unless there is a bug, we include the following for security.
  58. # X can be Inf, as finite + finite can be Inf numerically.
  59. if any(np.isnan(x)) or any(np.isinf(x)):
  60. info = NAN_INF_X
  61. # Although NAN_INF_F should not happen unless there is a bug, we include the following for security.
  62. if np.isnan(f) or np.isposinf(f) or np.isnan(cstrv) or np.isposinf(cstrv):
  63. info = NAN_INF_F
  64. if cstrv <= ctol and f <= ftarget:
  65. info = FTARGET_ACHIEVED
  66. if nf >= maxfun:
  67. info = MAXFUN_REACHED
  68. return info