Gradient of the cost function
(x, rv)
| 300 | return rv |
| 301 | |
| 302 | def grad(x, rv) -> None: |
| 303 | """ |
| 304 | Gradient of the cost function |
| 305 | """ |
| 306 | |
| 307 | rv[:] = 0 |
| 308 | |
| 309 | for i, ((e1, e2), kind, val) in enumerate(constraints): |
| 310 | |
| 311 | cost = costs[kind] |
| 312 | |
| 313 | # build arguments for the specific constraint |
| 314 | x1 = x[ixs[e1] : ixs[e1 + 1]] |
| 315 | args = [x1.copy(), geoms[e1], x0s[e1]] |
| 316 | if e2 is not None: |
| 317 | x2 = x[ixs[e2] : ixs[e2 + 1]] |
| 318 | args += [x2.copy(), geoms[e2], x0s[e2]] |
| 319 | |
| 320 | # evaluate |
| 321 | tmp = cost(*args, val) |
| 322 | |
| 323 | for j, k in enumerate(range(ixs[e1], ixs[e1 + 1])): |
| 324 | args[0][j] += DIFF_EPS |
| 325 | tmp1 = cost(*args, val) |
| 326 | rv[k] += 2 * tmp * (tmp1 - tmp) / DIFF_EPS |
| 327 | args[0][j] = x1[j] |
| 328 | |
| 329 | if e2 is not None: |
| 330 | for j, k in enumerate(range(ixs[e2], ixs[e2 + 1])): |
| 331 | args[3][j] += DIFF_EPS |
| 332 | tmp2 = cost(*args, val) |
| 333 | rv[k] += 2 * tmp * (tmp2 - tmp) / DIFF_EPS |
| 334 | args[3][j] = x2[j] |
| 335 | |
| 336 | # generate lower and upper bounds for optimization |
| 337 | lb = full(ixs[-1], -inf) |