def rotate_in_place(a: np.array): """ Rotate for N*N array, the result is equivalent to numpy.rot90(a, 3) :array: N*N numpy array :return: rotated numpy array Complexity: Time : O(rc) Space : O(rc) """ # 4-way edge swap if not a.all(): raise ArgError() row_num, col_num = a.shape if row_num != col_num: raise ArgError("only support N*N array") dim = row_num layers = dim // 2 for layer in range(layers): start = layer end = dim - 1 - layer for offset in range(end - start): tmp = a[start, start + offset] a[start, start + offset] = a[end - offset, start] a[end - offset, start] = a[end, end - offset] a[end, end - offset] = a[start + offset, end] a[start + offset, end] = tmp return a
def safe_log(x: np.array): """ Returns the log of x. If x contains a zero value, adds 1 to all values """ assert type(x) == np.ndarray, f'x is of type {type(x)}' if x.all(): y = np.log(x) else: y = np.log(x + 1) assert not np.isinf(y).any(), f'Infinite values found in y!' return y
def rotate(a: np.array, *, dtype=int): """ Rotate for M*N array, this is equivalent to numpy.rot90(a, 3) :array: M*N numpy array :return: rotated numpy array Complexity: Time : O(rc) Space : O(rc) """ if not a.all(): raise ArgError() row_num, col_num = a.shape[::-1] rotated_array = np.empty(shape=[row_num, col_num], dtype=dtype) for index, v in np.ndenumerate(a): r, c = index rotated_array[c, col_num - 1 - r] = v return rotated_array
def property_function(bin_str: np.array) -> float: """Compute measure based on Lempel_Ziv complexity. Same measure as in Dingle, Camargo, and Louis (2018), 'Input–output maps are strongly biased towards simple outputs', See Supplementary Note 1, p. 10. Args: bin_str: A numpy array of shape (1,) with Boolean values. Represents the meaning (extension) of an expression. Entry i represents whether the expression is true in model i (the i'th model in the enumeration of models in the universe). Returns: A single number (float). """ expr_len = len(bin_str) if bin_str.all() or np.invert(bin_str).all(): return log2(expr_len) lz_expr = lz(bin_str.tobytes()) lz_rev_expr = lz(np.flip(bin_str).tobytes()) return log2(expr_len) * (lz_expr + lz_rev_expr) / 2
def get_ensemble_knots(self, n_i_knots: int, spline_data: np.array, observed: np.array, spline_options: Dict, terminal_days: int = 4) -> List[np.array]: # # number of submodels # N = n_i_knots * 4 # N = max(28, N) N = 40 # where are our fixed outer points if observed.sum() < 100: #start_boundary_pctile = terminal_days / 100 end_boundary_pctile = 1. - (terminal_days / 100) min_interval = terminal_days / 100 else: # start_boundary_pctile, end_boundary_pctile = self.find_pctile( spline_data[observed], terminal_days, spline_options['spline_knots_type']) min_interval = terminal_days / observed.sum() start_boundary_pctile = 0. # fix first and last interior knots as specified n_intervals = n_i_knots + 1 k_start = 0. k_end = 1. if n_i_knots >= 3: if np.quantile(spline_data[observed], start_boundary_pctile) > spline_data.min(): n_intervals -= 1 k_start = start_boundary_pctile + min_interval if np.quantile(spline_data[observed], end_boundary_pctile) < spline_data.max(): n_intervals -= 1 k_end = end_boundary_pctile - min_interval # sample - force first 50% of knots to be in placed first 50% of domain; same of second (for speed) b = np.array([[k_start, k_end / 2]] * ((n_intervals - 1) - int((n_intervals - 1) / 2)) + \ [[k_end / 2, k_end]] * int((n_intervals - 1) / 2)) d = np.array([[min_interval, 1]] * n_intervals) ensemble_knots = utils.sample_knots(n_intervals, b=b, d=d, N=N) if k_start > 0.: ensemble_knots = np.insert(ensemble_knots, 1, start_boundary_pctile, 1) if k_end < 1.: ensemble_knots = np.insert(ensemble_knots, -1, end_boundary_pctile, 1) # rescale to observed if not observed.all(): if spline_options['spline_knots_type'] != 'domain': raise ValueError( 'Expecting `spline_knots_type` domain for knot rescaling (stage 2 model).' ) ensemble_knots = rescale_k(spline_data[observed], spline_data, ensemble_knots) # make sure we have unique knots if spline_options['spline_knots_type'] == 'frequency': _ensemble_knots = [] for knots in ensemble_knots: if np.unique(np.quantile(spline_data, knots)).size == knots.size: _ensemble_knots.append(knots) ensemble_knots = np.vstack(_ensemble_knots) # flag if no fully unique knot options (i.e., entries w/ duplicates eliminated in previous step) if ensemble_knots.size == 0: raise ValueError( 'Knot options do not find unique data values (frequency).') return ensemble_knots