def add_edge_to_graph(self, lst_pt1, lst_pt2): if tuple(lst_pt1) not in self.graph.keys(): self.graph[tuple(lst_pt1)] = [] if tuple(lst_pt2) not in self.graph.keys(): self.graph[tuple(lst_pt2)] = [] if lst_pt1[0] < lst_pt2[0]: if not lst_pt2 in self.graph[tuple(lst_pt1)]: self.graph[tuple(lst_pt1)].append(lst_pt2) elif lst_pt1[0] == lst_pt2[0] and lst_pt1[1] > lst_pt2[ 1]: # Added this to enforce bottom-right node as exit if not lst_pt2 in self.graph[tuple(lst_pt1)]: self.graph[tuple(lst_pt1)].append(lst_pt2) else: if not lst_pt1 in self.graph[tuple(lst_pt2)]: self.graph[tuple(lst_pt2)].append(lst_pt1)
def predict_time_series(param_vec, Ns, Cins, Cs, C_0s): time_points = np.array([x * 1 for x in range(len(Ns))]) sol = odeint(sdot, N, time_points, tuple((param_vec, Cin, C, C_0)))[1:] pred_Ns = sol[:, 0:2] return pred_Ns
def predict_time_series(param_vec, initial_N, Cins, initial_C, initial_C0): time_points = np.array([x * 1 for x in range(len(Cins))]) sol = odeint(sdot, initial_N, time_points, tuple((param_vec, Cins, initial_C, initial_C0))) pred_Ns = sol[:, 0:2] return pred_Ns
def vjp_all(g): vjp_y = g[-1, :] vjp_t0 = 0 time_vjp_list = [] vjp_args = np.zeros(np.size(flat_args)) for i in range(T - 1, 0, -1): # Compute effect of moving measurement time. vjp_cur_t = np.dot(func(yt[i, :], t[i], *func_args), g[i, :]) time_vjp_list.append(vjp_cur_t) vjp_t0 = vjp_t0 - vjp_cur_t # Run augmented system backwards to the previous observation. aug_y0 = np.hstack((yt[i, :], vjp_y, vjp_t0, vjp_args)) aug_ans = odeint(augmented_dynamics, aug_y0, np.array([t[i], t[i - 1]]), tuple((flat_args,)), **kwargs) _, vjp_y, vjp_t0, vjp_args = unpack(aug_ans[1]) # Add gradient from current output. vjp_y = vjp_y + g[i - 1, :] time_vjp_list.append(vjp_t0) vjp_times = np.hstack(time_vjp_list)[::-1] return None, vjp_y, vjp_times, unflatten(vjp_args)
def scipy_simulate(ti_controls, sampling_times, model_parameters): """ The simulation function to be passed on to the pydex.designer. The function takes in the nominal model parameter values, and experimental candidates. Returns the predictions of the model at specified sampling times. Parameters: model : a Pyomo model instance simulator : a Pyomo simulator instance ti_controls : time-invariant controls of candidate (1D np.array) sampling_times : sampling time choices of candidate (1D np.array) model_parameters : nominal model parameter values (1D np.array) Return responses : a 2D np.array with shapes N_spt by n_r, corresponding to the model's prediction on value of the n_r number of responses at all N_spt number of sampling times. """ def scipy_model(t, ca, theta): dca_dt = -theta[0] * ca return dca_dt sol = odeint(scipy_model, args=tuple((model_parameters, )), y0=ti_controls[0], t=sampling_times, tfirst=True) return sol
def vjp_all(g, **kwargs): vjp_y = g[-1, :] vjp_t0 = 0 time_vjp_list = [] vjp_args = np.zeros(np.size(flat_args)) for i in range(T - 1, 0, -1): # Compute effect of moving current time. vjp_cur_t = np.dot(func(yt[i, :], t[i], *func_args), g[i, :]) time_vjp_list.append(vjp_cur_t) vjp_t0 = vjp_t0 - vjp_cur_t # Run augmented system backwards to the previous observation aug_y0 = np.hstack((yt[i, :], vjp_y, vjp_t0, vjp_args)) aug_ans = odeint(augmented_dynamics, aug_y0, np.array(t[i], t[i - 1]), tuple((flat_args,)), **kwargs) _, vjp_y, vjp_t0, vjp_args = unpack(aug_ans[1]) # Add gradient from current output vjp_y = vjp_y + g[i - 1, :] time_vjp_list.append(vjp_t0) vjp_times = np.hstack(time_vjp_list)[::-1] return None, vjp_y, vjp_times, unflatten(vjp_args)
def predict_time_series(self, params, S, Cins, time_points): # verified working on timeseries sol = odeint(self.sdot, S, time_points, tuple( (params, Cins)))[:] #PUT THIS BACK FOR ONLINE pred_N = sol[:, 0] #PUT THIS BACK FOR ONLINE return pred_N
def fixed_point_vjp(ans, f, a, x0, distance, tol): def rev_iter(params): a, x_star, x_star_bar = params vjp_x, _ = make_vjp(f(a))(x_star) vs = vspace(x_star) return lambda g: vs.add(vjp_x(g), x_star_bar) vjp_a, _ = make_vjp(lambda x, y: f(x)(y))(a, ans) return lambda g: vjp_a(fixed_point(rev_iter, tuple((a, ans, g)), vspace(x0).zeros(), distance, tol))
def predict(params, S, Cin): time_diff = 2 # frame skipping time_points = np.array([x * 1 for x in range(time_diff)]) sol = odeint(sdot, S, time_points, tuple((params, Cin)))[1:] pred_N = sol[-1, 0:2] return pred_N
def sdot( S, t, param_vec, Cin ): # X is population vector, t is time, R is intrinsic growth rate vector, C is the rate limiting nutrient vector, A is interaction matrix ''' Calculates and returns derivatives for the numerical solver odeint Parameters: S: current state t: current time Cin: array of the concentrations of the auxotrophic nutrients and the common carbon source params: list parameters for all the exquations num_species: the number of bacterial populations Returns: dsol: array of the derivatives for all state variables ''' # extract parmeters #A = np.reshape(param_vec[0:4],(2, 2)) A = Q_params[0] y = param_vec[4:6] y3 = param_vec[6:8] ''' y = ode_params[2] y3 = ode_params[3] ''' Rmax = param_vec[8:10] ''' Km = ode_params[5] Km3 = ode_params[6] ''' Km = param_vec[10:12] Km3 = param_vec[12:14] num_species = 2 # extract variables N = np.array(S[:num_species]) C = np.array(S[num_species:2 * num_species]) C0 = np.array(S[-1]) C0in, q = ode_params[:2] R = monod(C, C0, Rmax, Km, Km3) Cin = Cin[:num_species] # calculate derivatives dN = N * (R + np.matmul(A, N) - q) # q term takes account of the dilution dC = q * (Cin - C) - (1 / y) * R * N # sometimes dC.shape is (2,2) dC0 = q * (C0in - C0) - sum(1 / y3[i] * R[i] * N[i] for i in range(num_species)) # consstruct derivative vector for odeint dC0 = np.array([dC0]) dsol = np.append(dN, dC) dsol = np.append(dsol, dC0) return tuple(dsol)
def predict(self, params, S, Cin): ''' predicts the populations at the next time point based on the current values for the params ''' time_diff = 2 # frame skipping time_points = np.array([x *1 for x in range(time_diff)]) sol = odeint(self.sdot, S, time_points, tuple((params, Cin)))[1:] pred_N = sol[-1, 0:2] return pred_N
def predict(x, t, u, A, B): # extract params from param_vec into form used by the rest of the code time_diff = 2 # frame skipping time_points = np.array([x *1 for x in range(time_diff)]) sol = odeint(linear_model, N, time_points, tuple((u, A, B)))[1:] pred_x = sol[-1, 0:2] return pred_x
def predict(self, initial_x, u, A, B, time): # extract params from param_vec into form used by the rest of the code time_points = np.array([x *1 for x in range(time)]) sol = odeint(self.linear_model, initial_x, time_points, tuple((u, A, B)))[1:] pred_x = sol[-1, 0:2] return pred_x
def predict_series(param_vec, Ns, Cins, C, C_0): # extract params from param_vec into form used by the rest of the code time_diff = Ns.shape[0] time_points = np.array([x * 1 for x in range(time_diff)]) sol = odeint(sdot, Ns, time_points, tuple((param_vec, Cins, C, C_0)))[1:] pred_N = sol[-1, 0:2] return pred_N
def predict(param_vec, S, Cin, C, C_0): # extract params from param_vec into form used by the rest of the code time_diff = 2 # frame skipping time_points = np.array([x * 1 for x in range(time_diff)]) sol = odeint(sdot, S, time_points, tuple((param_vec, Cin, C, C_0)))[1:] pred_N = sol[-1, 0:2] return pred_N
def generate_edges(self, tri, pts): edges = [] for _, s in enumerate(tri.simplices): tri_pts = [pts[i] for i in list(s)] for i, pt in enumerate(tri_pts): if i == 0: continue elif pt == tri_pts[-1]: # Wrap around self.add_edge_to_graph(pt, tri_pts[0]) self.add_edge_to_graph(tri_pts[i - 1], pt) topl_to_topR = ([self.min_range, self.max_range], [self.max_range, self.max_range]) btml_to_btmR = ([self.min_range, self.min_range], [self.max_range, self.min_range]) for pt_pair in [topl_to_topR, btml_to_btmR]: pt1, pt2 = pt_pair if pt2 in self.graph[tuple(pt1)]: idx = self.graph[tuple(pt1)].index(pt2) del self.graph[tuple(pt1)][idx] elif pt1 in self.graph[tuple(pt2)]: idx = self.graph[tuple(pt2)].index(pt1) del self.graph[tuple(pt1)][idx] for tuple_pt, lst_pt_list in self.graph.items(): for lst_pt in lst_pt_list: # edges.append((np.asarray(tuple_pt), list(np_pt))) edges.append((list(tuple_pt), lst_pt)) return edges
def sdot( self, S, t, params, Cin ): # X is population vector, t is time, R is intrinsic growth rate vector, C is the rate limiting nutrient vector, A is interaction matrix ''' Calculates and returns derivatives for the numerical solver odeint Parameters: S: current state t: current time Cin: array of the concentrations of the auxotrophic nutrients and the common carbon source params: list parameters for all the equations num_species: the number of bacterial populations Returns: dsol: array of the derivatives for all state variables ''' # extract variables # autograd gives t as an array_box, need to convert to int if str( type(t) ) == '<class \'autograd.numpy.numpy_boxes.ArrayBox\'>': # sort this out t = t._value t = int(t) else: t = int(t) t = min(Cin.shape[0] - 1, t) # to prevent solver from going past the max time C0in = Cin[t] #C0in = Cin N = S[0] C0 = S[1] # extract parameters q = self.ode_params[0] y, Rmax = params[0:2] Km = self.ode_params[3] R = self.monod(C0, Rmax, Km) # calculate derivatives dN = N * (R.astype(float) - q) # q term takes account of the dilution dC0 = q * (C0in - C0) - 1 / y * R * N # consstruct derivative vector for odeint dC0 = np.array([dC0]) dsol = np.append(dN, dC0) return tuple(dsol)
def getDynamics(values, params, nonLinear=False, movablePts=[], runParameters=None): #returns a trajectory of this ODE_PDE if runParameters == None: (max_T, count) = getSampleParameters() else: (max_T, count) = runParameters # make the samples times = np.linspace(0., max_T, count) # run the ODE_PDE solver, returns an array [[list of values of state variables @ t0], [list of values of state variables @ t1] .....] return solveModelODEPDE(values, times, params=tuple((params, )), nonLinear=nonLinear, movablePts=movablePts)
def sdot( S, t, C0in, params ): # X is population vector, t is time, R is intrinsic growth rate vector, C is the rate limiting nutrient vector, A is interaction matrix ''' Calculates and returns derivatives for the numerical solver odeint Parameters: S: current state t: current time Cin: array of the concentrations of the auxotrophic nutrients and the common carbon source params: list parameters for all the exquations num_species: the number of bacterial populations Returns: dsol: array of the derivatives for all state variables ''' # extract variables N = S[0] C0 = S[1] # extract parameters q = ode_params[0] y, Rmax, Km = params Km = ode_params[3] R = monod(C0, Rmax, Km) # calculate derivatives dN = N * (R.astype(float) - q) # q term takes account of the dilution dC0 = q * (C0in - C0) - 1 / y * R * N # consstruct derivative vector for odeint dC0 = np.array([dC0]) dsol = np.append(dN, dC0) return tuple(dsol)
grad_C = autograd.grad(cost) #for debugging and computational simplicity, each paramater will have 3 iterations to be fitted maxiter = 3 #leanring rate set at 0.1 but can increase if needed learning_rate = 0.1 #we will modify each parameter value independently for i in range(params.size): print(i) for j in range(maxiter): # strange bug where at parameter 5 (index=4), iteration 3? a degenrate solution appears #Solve ODE using odeint sol = odeint(ODESYS, y0=np.array( [417., 0., 0., G_b, I_b, 0.0, 0.0, 0.0, 0.0, 0.0]), t=t, args=tuple([params, i])) #isolates the values of y variables Y = sol[:, :5] #cost function tracker, should observe a strictly decreasing behavior (and we do!) current_error = np.linalg.norm(Y[:, 3] - gdata, 2) print(current_error) #parameter in question is changed as needed params[i] -= learning_rate * (grad_C(Y) * sol[:, -5:]).sum() #graph newly fitted plot, technically one iteration old t = np.linspace(1, 120, 120) plt.scatter(t, gdata, marker='.', alpha=0.5, label='G') plt.scatter(t, sol[:, 3], marker='.', alpha=0.5, label='estimate') plt.legend() plt.show() print(params)
# fitnessList[startIndex: -1], # odeDeltaList[startIndex: -1, :, :], # pdeDeltaList[startIndex: -1, :, :]) # # start the optimizing iterations for the last 20% of the dynamics # (max_t, count) = (max_t*(1-stablePercent), int(count*(1-stablePercent))) # movablePts = tuple(movablePts) movablePts = [(val) for val in movablePts] print('Movable Pts: ', movablePts) bestFitness = 0 bestVesselPts = movablePts (max_t, count) = getSampleParameters() gradFitness = grad(fitnessValue) for iteration in range(0, MaxIterations): grad_pts = gradFitness(movablePts, iteration) print(grad_pts) movablePts = tuple( np.array(movablePts) + np.array(grad_pts) * StepSize) # movablePts = np.array(movablePts) + np.array(grad_pts) # # initial conditions are at the beginning of the dynamics just calcluated initialConditions = getInitialValues() # # make a random mutation # (VesselIds, movablePts, VesselCells) = randomStep(VesselIds, movablePts) # #print(movablePts) # # recompute the dynamics (dynamicsTrue, fitnessList, odeDeltaList, pdeDeltaList) = getDynamics(initialConditions, getTrueParameters(), nonLinear=True, movablePts=movablePts, runParameters=getSampleParameters()) #only the last 30% of the dynamics
b2 = 0.999 eps = 10**-8 (max_t, count) = getSampleParameters() for i in range(200): start = time.time() grad_pts = gradFitness(mvable_pts, i) m = (1 - b1) * np.array( grad_pts, dtype=np.float64) + b1 * m # First moment estimate. v = (1 - b2) * (np.array(grad_pts, dtype=np.float64)** 2) + b2 * v # Second moment estimate. mhat = m / (1 - b1**(i + 1)) # Bias correction. vhat = v / (1 - b2**(i + 1)) mvable_pts = tuple( np.array(mvable_pts, dtype=np.float64) + np.array(grad_pts, dtype=np.float64)) mvable_pts = mvable_pts + stepSize * mhat / (np.sqrt(vhat) + eps) new_pts = [] for val in mvable_pts: x = float(val[0]) y = float(val[1]) if x < 0: x = 0.0 elif x >= vas_structure.max_range: x = float(vas_structure.max_range - 1) if y < 0: y = 0.0 elif y >= vas_structure.max_range: y = float(vas_structure.max_range - 1)
def sdot(self, S, t, param_vec, Cin): # X is population vector, t is time, R is intrinsic growth rate vector, C is the rate limiting nutrient vector, A is interaction matrix ''' Calculates and returns derivatives for the numerical solver odeint Parameters: S: current state t: current time Cin: array of the concentrations of the auxotrophic nutrients and the common carbon source params: list parameters for all the exquations num_species: the number of bacterial populations Returns: dsol: array of the derivatives for all state variables ''' # extract parmeters ''' A = param_vec[5] #A = param_vec[0] y = param_vec[0] y3 = param_vec[1] Rmax = param_vec[2] Km = self.ode_params[5] Km3 = self.ode_params[6] Km = param_vec[10:12] Km3 = param_vec[12:14] ''' # autograd gives t as an array_box, need to convert to int if str(type(t)) == '<class \'autograd.numpy.numpy_boxes.ArrayBox\'>': # sort this out t = t._value t = int(t) else: t = int(t) t = min(Cin.shape[0] - 1, t) # to prevent solver from going past the max time Cin = Cin[t] print(" param vec: ", param_vec) A = np.reshape(param_vec[-4:], (2,2)) y = param_vec[4:6] y3 = param_vec[6:8] Rmax = param_vec[8:10] Km = self.ode_params[5] Km3 = self.ode_params[6] num_species = 2 # extract variables N = np.array(S[:num_species]) C = np.array(S[num_species:2*num_species]) C0 = np.array(S[-1]) C0in, q = self.ode_params[:2] R = self.monod(C, C0, Rmax, Km, Km3) Cin = Cin[:num_species] # calculate derivatives dN = N * (R + np.matmul(A,N) - q) # q term takes account of the dilution dC = q*(Cin - C) - (1/y)*R*N # sometimes dC.shape is (2,2) dC0 = q*(C0in - C0) - sum(1/y3[i]*R[i]*N[i] for i in range(num_species)) # consstruct derivative vector for odeint dC0 = np.array([dC0]) dsol = np.append(dN, dC) dsol = np.append(dsol, dC0) return tuple(dsol)
def ode_pred(params, y0, t): return odeint(nn_predict, y0, t, tuple((params, )), rtol=0.01)
def predict(self, params, S, Cin, time_points): sol = odeint(sdot, S, time_points, tuple( (Cin, params, 2)))[1:] #PUT THIS BACK FOR ONLINE return sol
def odefunc_time_dependent(inputs, params, t=tuple((1, ))): params = _hypernet(t, params) x = inputs[:, :input_dim] return _forward(x, params)
def ode_pred(params, y0, t): return odeint(nn_predict, y0, t, tuple((params,)), rtol=0.01)
# movablePts = [random_points[best_loss_idx]] # print('\n\n') # print(random_points[best_loss_idx], best_loss) # print('\n\n') # img, vesselImage, vesselPts = updateVesselImg(vesselImage, vesselSecretion, movablePts, img) grad_pts = gradFitness(movablePts, i) print(grad_pts) callback_Test(movablePts, i, '') # m = (1 - b1) * np.array(grad_pts) + b1 * m # First moment estimate. # v = (1 - b2) * (np.array(grad_pts)**2) + b2 * v # Second moment estimate. # mhat = m / (1 - b1**(i + 1)) # Bias correction. # vhat = v / (1 - b2**(i + 1)) movablePts = tuple(np.array(movablePts) + np.array(grad_pts) * .008) new_pts = [] for val in movablePts: x = float(val[0]) y = float(val[1]) if x < 0: x = 0.0 elif x >= imageSize: x = float(imageSize - 1) if y < 0: y = 0.0 elif y >= imageSize: y = float(imageSize - 1) new_pts += [[x, y]]
def system_evolve(self, Y0, method = 'RK45', params = None, system = None): '''The system_evolve method computes the time evolution of the define ordinary differential system. The method receives the inital conditions and integrates the solution with a defined numerical method. Leading to a form: dy/dt = F(x,t,params) system_evolve(Y0, method = 'RK45', params = None, system = None) Parameters ---------- Y0 : ndarray of shape (n,) Initial conditions for the system. params : ndarray of size (n,) Extra arguments the system might need. eg: constants, parameters. method : {'RK45', 'RK23', 'DOP853', 'BDF', 'LSODA'} auto : 'RK45' Numeric approximation method. Other solver methods should be available. Refer to the scipy.integrate library. system : callable, auto : None Replacement system object. Additional function to be time-evolved. Used for expanding solutions or state space dynamic systems. ''' points = int(np.floor((self.__tf-self.__t0)/self.__d_t)) self.__t = np.linspace(self.__t0, self.__tf, points) t_span = (self.__t0, self.__tf) if system is not None: evolved_system = system else: evolved_system = self.__f_x_y print("Time evolving using parameters = {}".format(params)) """Time evolution solve_ivp syntax should include a tuple([params]) to generate a tuple of an array and empty so it can be unpacked by the solve_ivp function as a single array and interpreted as a single list to the user defined function. params = np.array([1,2,3]) tuple([params]) = (array([1,2, ...]),) otherwise, multiple values will be sent, instead on only one. List should be unpacked at the user defined function.""" time_evolution = solve_ivp(evolved_system, t_span= t_span, y0 = Y0, method = method, t_eval= self.__t, args= tuple([params])) self.__Y = time_evolution.y return time_evolution
#============================================================================= #Block 3 #Generating a training data set #============================================================================= #These are our known parameters we are attempting to estimate BETA = 0.00006 GAMA = 0.2 #The inital conditions for the model start = np.array([50000, 1, 0, 0, 0, 0, 0, 0, 0]) t = np.linspace(0,29) #The model ran using odeint data = odeint(SYS, y0 = start, t = t, args = tuple([BETA, GAMA])) #plotting the results plot.scatter(t,data[:,0], marker = '.', alpha = 0.5, label = 'S') plot.scatter(t,data[:,1], marker = '.', alpha = 0.5, label = 'I') plot.scatter(t,data[:,2], marker = '.', alpha = 0.5, label = 'R') plot.show() #============================================================================= #Block 4 Cost function declaration #Object Name: Cost #Function name: error #Inputs: Y a np.array of starting conditions # t a np.linespace(start, end) # beta a float # gama a float