def __find_bounds(self, dir_vec, ptope, bund): 'Find the generator of the parallelotope.' genFun = ptope.getGeneratorRep() 'Create subsitutions tuples.' var_sub = [] for var_ind, var in enumerate(self.vars): var_sub.append((var, genFun[var_ind])) #print(f"Variable Sub for {dir_vec}: {var_sub}") Timer.start('Functional Composition') fog = [func.subs(var_sub, simultaneous=True) for func in self.f] Timer.stop('Functional Composition') 'Perform functional composition with exact transformation from unitbox to parallelotope.' bound_polyu = 0 for coeff_idx, coeff in enumerate(dir_vec): bound_polyu += coeff * fog[coeff_idx] 'Calculate min/max Bernstein coefficients.' Timer.start('Bound Computation') ub, lb = OptProd(bound_polyu, bund).getBounds() Timer.stop('Bound Computation') return ub, -1 * lb
def getGeneratorRep(self): Timer.start('Generator Procedure') base_vertex = self._computeBaseVertex() gen_list = self._computeGenerators(base_vertex) 'Create list representing the linear transformation q + \sum_{j} a_j* g_j' expr_list = base_vertex for var_ind, var in enumerate(self.vars): for i in range(self.dim): expr_list[i] += gen_list[var_ind][i] * var Timer.stop('Generator Procedure') return expr_list
def plot2DPhase(self, x, y, separate=False, lims=None): assert len( self.flowpipes ) != 0, "Plot Object must have at least one flowpipe to plot for 2DPhase." Timer.start('Phase') dim = self.model.dim figure = plt.figure(figsize=PlotSettings.fig_size) phase_ax = figure.add_subplot(1, 2, 1) vol_ax = figure.add_subplot(1, 2, 2) for flow_idx, (flow_label, flowpipe) in enumerate(self.flowpipes): self.__halfspace_inter_plot(flowpipe, flow_idx, flow_label, x, y, phase_ax, separate) #self.__support_plot(flowpipe, flow_idx, flow_label, x, y, ax) self.__plot_trajs(x, y, phase_ax) self.__phase_plot_legend(x, y, phase_ax, lims) 'Add volume data' self.__plot_volume(vol_ax) figure_name = "Kaa{}Phase{}.png".format(flowpipe.model.name, self.__create_var_str([x, y])) self.__plot_figure(figure, figure_name) phase_time = Timer.stop('Phase') print("Plotting phase for dimensions {}, {} done -- Time Spent: {}". format(x_var, y_var, phase_time))
def plot2DPhase(self, x, y): Timer.start('Phase') x_var, y_var = self.vars[x], self.vars[y] 'Define the following projected normal vectors.' norm_vecs = np.zeros([6, self.dim_sys]) norm_vecs[0][x] = 1 norm_vecs[1][y] = 1 norm_vecs[2][x] = -1 norm_vecs[3][y] = -1 norm_vecs[4][x] = 1 norm_vecs[4][y] = 1 norm_vecs[5][x] = -1 norm_vecs[5][y] = -1 fig, ax = plt.subplots(1) comple_dim = [i for i in range(self.dim_sys) if i not in [x, y]] 'Initialize objective function for Chebyshev intersection LP routine.' c = [0 for _ in range(self.dim_sys + 1)] c[-1] = 1 for bund in self.flowpipe: bund_A, bund_b = bund.getIntersect() 'Compute the normal vector offsets' bund_off = np.empty([len(norm_vecs), 1]) for i in range(len(norm_vecs)): bund_off[i] = minLinProg(np.negative(norm_vecs[i]), bund_A, bund_b).fun 'Remove irrelevant dimensions. Mostly doing this to make HalfspaceIntersection happy.' phase_intersect = np.hstack((norm_vecs, bund_off)) phase_intersect = np.delete(phase_intersect, comple_dim, axis=1) 'Compute Chebyshev center of intersection.' row_norm = np.reshape(np.linalg.norm(norm_vecs, axis=1), (norm_vecs.shape[0], 1)) center_A = np.hstack((norm_vecs, row_norm)) neg_bund_off = np.negative(bund_off) center_pt = maxLinProg(c, center_A, list(neg_bund_off.flat)).x center_pt = np.asarray( [b for b_i, b in enumerate(center_pt) if b_i in [x, y]]) 'Run scipy.spatial.HalfspaceIntersection.' hs = HalfspaceIntersection(phase_intersect, center_pt) inter_x, inter_y = zip(*hs.intersections) ax.set_xlabel('{}'.format(x_var)) ax.set_ylabel('{}'.format(y_var)) ax.fill(inter_x, inter_y, 'b') fig.show() phase_time = Timer.stop('Phase') print("Plotting phase for dimensions {}, {} done -- Time Spent: {}". format(x_var, y_var, phase_time))
def get2DProj(self, var_ind): pipe_len = len(self.flowpipe) Timer.start('Proj') curr_var = self.vars[var_ind] 'Vector of minimum and maximum points of the polytope represented by parallelotope bundle.' y_min, y_max = np.empty(pipe_len), np.empty(pipe_len) 'Initialize objective function' y_obj = [0 for _ in self.vars] y_obj[var_ind] = 1 'Calculate the minimum and maximum points through LPs for every iteration of the bundle.' for bund_ind, bund in enumerate(self.flowpipe): bund_sys = bund.getIntersect() y_min[bund_ind] = bund_sys.max_opt(y_obj).fun y_max[bund_ind] = bund_sys.min_opt(y_obj).fun Timer.stop("Proj") return y_min, y_max
def computeReachSet(self, time_steps): initial_set = self.model.bund transformer = BundleTransformer(self.model.f) flowpipe = [initial_set] for ind in range(time_steps): Timer.start('Reachable Set Computation') trans_bund = transformer.transform(flowpipe[ind]) reach_time = Timer.stop('Reachable Set Computation') print("Computed Step {0} -- Time Elapsed: {1} sec".format( ind, reach_time)) flowpipe.append(trans_bund) return FlowPipe(flowpipe, self.model.vars)
def plot2DProj(self, *vars_tup): num_var = len(vars_tup) pipe_len = len(self.flowpipe) fig, ax = plt.subplots(1, num_var) ax = [ax] if num_var == 1 else ax 'Time step vector for plotting' t = np.arange(0, pipe_len, 1) for ax_ind, var_ind in enumerate(vars_tup): Timer.start('Proj') curr_var = self.vars[var_ind] 'Vector of minimum and maximum points of the polytope represented by parallelotope bundle.' y_min, y_max = np.empty(pipe_len), np.empty(pipe_len) 'Initialize objective function' y_obj = [0 for _ in self.vars] y_obj[var_ind] = 1 'Calculate the minimum and maximum points through LPs for every iteration of the bundle.' for bund_ind, bund in enumerate(self.flowpipe): bund_A, bund_b = bund.getIntersect() y_min[bund_ind] = minLinProg(y_obj, bund_A, bund_b).fun y_max[bund_ind] = maxLinProg(y_obj, bund_A, bund_b).fun ax[ax_ind].fill_between(t, y_min, y_max) ax[ax_ind].set_xlabel("t: time steps") ax[ax_ind].set_ylabel("Reachable Set for {}".format(curr_var)) plot_time = Timer.stop('Proj') print( "Plotting projection for dimension {} done -- Time Spent: {}". format(curr_var, plot_time)) fig.show()
def computeReachSet(self, time_steps, tempstrat=None, transmode=BundleMode.AFO): initial_set = self.model.bund transformer = BundleTransformer(self.model, transmode) strat = tempstrat if tempstrat is not None else DefaultStrat( self.model) flowpipe = [initial_set] for ind in range(time_steps): Timer.start('Reachable Set Computation') starting_bund = copy.deepcopy(flowpipe[ind]) #print("Open: L: {} \n T: {}".format(starting_bund.L, starting_bund.T)) #print("Open: Offu: {} \n Offl{}".format(starting_bund.offu, starting_bund.offl)) strat.open_strat(starting_bund) trans_bund = transformer.transform(starting_bund) strat.close_strat(trans_bund) #print("Close: L: {} \n T: {}".format(trans_bund.L, trans_bund.T)) #print("Close: Offu: {} Offl{}".format(trans_bund.offu, trans_bund.offl)) reach_time = Timer.stop('Reachable Set Computation') 'TODO: Revamp Kaa.log to be output sink handling all output formatting.' if not KaaSettings.SuppressOutput: print("Computed Step {} -- Time Elapsed: {} sec".format( bolden(ind), bolden(reach_time))) flowpipe.append(trans_bund) return FlowPipe(flowpipe, self.model, strat)