33
44import numpy as np
55
6- from .._get_minq_installation import get_minq_installation
6+ # from .._get_minq_installation import get_minq_installation
77from .bqmin import bqmin
88
9+ from scipy .optimize import minimize
10+
911
1012@lru_cache (maxsize = 1 )
1113def _get_minqsw ():
12- required_minq_SHA , minq_installation = get_minq_installation ()
14+ # required_minq_SHA, minq_installation = get_minq_installation()
1315
14- if not minq_installation ["is_valid" ]:
15- msg = f"Please set MINQ clone to git commit { required_minq_SHA } .\n See User Guide (https://ibcdfo.readthedocs.io) for more information and instructions."
16- sys .exit (msg )
16+ # if not minq_installation["is_valid"]:
17+ # msg = f"Please set MINQ clone to git commit {required_minq_SHA}.\nSee User Guide (https://ibcdfo.readthedocs.io) for more information and instructions."
18+ # sys.exit(msg)
1719
1820 from minqsw import minqsw
1921
2022 return minqsw
2123
24+ def objective_for_lbfgsb (y , hfun , hfun_d , Fx , G , H , compute_grad = False , regularizer = 0.0 ):
25+
26+ n , m = np .shape (G )
27+ My = np .zeros (m )
28+ if compute_grad :
29+ Jy = np .zeros ((n , m ))
30+
31+ yG = y @ G
32+
33+ for i in range (m ): # this can certainly be vectorized, I just want it readable for debugging.
34+ My [i ] = Fx [i ] + yG [i ] + 0.5 * y @ H [:, :, i ] @ y .T
35+ if compute_grad :
36+ Jy [:, i ] = G [:, i ] + H [:, :, i ] @ y .T
37+
38+ if compute_grad :
39+ hfundMy = hfun_d (My )
40+ grad = Jy @ hfundMy + regularizer * y .T
41+ return grad
42+ else :
43+ hfunMy = hfun (My ) + 0.5 * regularizer * (y @ y .T )
44+ return hfunMy
45+
46+
47+ def run_lbfgsb (hfun , hfun_d , Fx , G , H , L , U , initial_point = None , regularize = False , regularizer = None ):
48+
49+ if not regularize :
50+ regularizer = 0.0
51+
52+ # create wrapper functions (sooooo stupid, but i want to use scipy for now because i trust LBFGS-B)
53+ def obj (y ):
54+ hFy = objective_for_lbfgsb (y , hfun , hfun_d , Fx , G , H , compute_grad = False , regularizer = regularizer )
55+ return hFy
56+
57+ def jac (y ):
58+ gradhFy = objective_for_lbfgsb (y , hfun , hfun_d , Fx , G , H , compute_grad = True , regularizer = regularizer )
59+ return gradhFy
60+
61+ n , m = np .shape (G )
62+
63+ if initial_point is None :
64+ x0 = np .zeros (n )
65+ else :
66+ x0 = initial_point
2267
23- def solve_trsp (H , G , Low , Upp , xk , delta , spsolver , n ):
68+ hFx0 = obj (x0 )
69+
70+ bounds = [(L [i ], U [i ]) for i in range (n )]
71+ options = {"gtol" : 1e-12 , "ftol" : 1e-12 }
72+ #print("Remember: You turned off gradients for now until you fix them.")
73+ out = minimize (obj , x0 , method = 'L-BFGS-B' , bounds = bounds , options = options , jac = jac )
74+ Xsp = out .x
75+ success = out .success
76+ fval = obj (Xsp )
77+ mdec = fval - hFx0
78+ return Xsp , mdec , success
79+
80+
81+ def solve_trsp (H , G , Cres , Hres , Gres , hfun , hfun_d , Low , Upp , xk , delta , spsolver , n ):
2482 """
2583 Solve the bound-constrained trust-region subproblem.
2684
2785 min G.T * s + 0.5 * s.T * H * s
2886 s.t. max(Low - xk, -delta) <= s <= min(Upp - xk, delta)
2987 """
88+
3089 Lows = np .maximum (Low - xk , - delta * np .ones (np .shape (Low )))
3190 Upps = np .minimum (Upp - xk , delta * np .ones (np .shape (Upp )))
3291
@@ -41,4 +100,38 @@ def solve_trsp(H, G, Low, Upp, xk, delta, spsolver, n):
41100 return Xsp , mdec , - 4
42101 return Xsp , mdec , 0
43102
103+ if spsolver == 3 :
104+ Xsp , mdec , success = run_lbfgsb (hfun , hfun_d , Cres , Gres , Hres , Lows .T , Upps .T , initial_point = None )
105+ # need to go check docs for error codes on LBFGSB, return error flag if something went very wrong
106+ return Xsp , mdec , success
107+
108+ if spsolver == 4 :
109+ Xsp , mdec , success = run_lbfgsb (hfun , hfun_d , Cres , Gres , np .zeros_like (Hres ), Lows .T , Upps .T ,
110+ initial_point = None )
111+ # need to go check docs for error codes on LBFGSB, return error flag if something went very wrong
112+ return Xsp , mdec , success
113+
114+ if spsolver == 5 :
115+ # This is what the theory says we should be doing.
116+ # hardcoded for now (values taken from Conn, Scheinberg, Zhang)
117+ kappa1 = 1.0
118+ kappa2 = 1.0
119+ kappa3 = 0.01
120+
121+ c = hfun (Cres ) ** 2
122+ regularize = False
123+
124+ normg = np .linalg .norm (G )
125+ if normg >= kappa1 :
126+ Hres = np .zeros_like (Hres )
127+ elif normg < kappa1 and c < kappa2 * normg :
128+ Hres = np .zeros_like (Hres )
129+ regularize = True
130+
131+ Xsp , mdec , success = run_lbfgsb (hfun , hfun_d , Cres , Gres , Hres , Lows .T , Upps .T ,
132+ initial_point = None , regularize = regularize , regularizer = (kappa3 * np .sqrt (hfun (Cres ))))
133+ # need to go check docs for error codes on LBFGSB, return error flag if something went very wrong
134+ return Xsp , mdec , success
135+
136+
44137 raise ValueError (f"Unknown trust-region subproblem solver: { spsolver } " )
0 commit comments