- import math
- import numpy as np
- from scipy.optimize import fmin
- N = 6
- x0 = 1
- # Ranges:
- # x in [0, ..., N)
- # u in [0, ..., N - 1)
- # v in [0, ..., N)
- def get_state_values(u: np.ndarray) -> np.ndarray:
- x = np.zeros((N))
- x[0] = x0
- for i in range(1, N):
- x[i] = 2 * x[i - 1] + u[i - 1]
- return x
- def constrained_f(u: np.ndarray, v: np.ndarray, t: float) -> float:
- x = get_state_values(u)
- f = 0
- for i in range(N - 1):
- f += math.pow(x[i], 2) + 2 * math.pow(u[i], 2)
- cost = 0
- # Constraint imposed on control value:
- for i in range(N - 1):
- cost += (u[i] - v[i, 0]) * max(0, u[i] - v[i, 0])
- cost += (-u[i] - v[i, 1]) * max(0, -u[i] - v[i, 1])
- # Constraint imposed on the final state value:
- cost += math.pow((x[N-1] - v[N - 1, 0]), 2)
- return f + (t/2) * cost
- def main():
- alpha = 2
- beta = 2
- epsilon = 0.1
- t = 0.1
- c = 0.1
- x = np.zeros((N))
- u = np.zeros((N - 1))
- v = np.zeros((N, 2))
- lower = 1
- upper = 3
- last = 20
- for i in range(N - 1):
- v[i, 0] = upper
- v[i, 1] = lower
- v[N - 1][0] = last
- while True:
- f_old = constrained_f(u, v, t)
- u = fmin(constrained_f, u, args=(v, t), disp=False)
- f_new = constrained_f(u, v, t)
- r = np.zeros((N, 2))
- for i in range(N - 1):
- r[i, 0] = u[i] - upper
- r[i, 1] = -u[i] - lower
- r[N - 1, 0] = x[N - 1] - last
- gamma = np.zeros((N, 2))
- for i in range(N - 1):
- gamma[i, 0] = v[i, 0] + r[i, 0] - upper
- gamma[i, 1] = v[i, 1] + r[i, 1] - lower
- gamma[N - 1, 0] = x[N - 1] + r[N - 1, 0] - last
- gamma_sum = np.sum(gamma)
- if gamma_sum <= epsilon:
- if np.abs(r[N - 1, 0]) <= np.abs(gamma[N - 1, 0])
- and np.abs(f_old - f_new) <= epsilon:
- break
- else:
- if gamma_sum < c:
- for i in range(N - 1):
- v[i, 0] = upper - r[i, 0]
- v[i, 1] = lower - r[i, 1]
- v[N - 1, 0] = last - r[N - 1, 0]
- c = alpha * gamma_sum
- else:
- t = beta * t
- for i in range(N - 1):
- v[i, 0] = upper - r[i, 0] / beta
- v[i, 1] = lower - r[i, 1] / beta
- v[N - 1, 0] = last - r[N - 1, 0] / beta
- print(u)
- print(get_state_values(u))
- print(f_new)
- if __name__ == '__main__':
- main()