# bubble-economy / nearness.py

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202``` ```#!/usr/bin/env python # encoding: utf-8 """ nearness.py Various functions do do with wrangling indices, vector lengths and distributions thereof Created by dan mackinlay on 2010-10-26. Copyright (c) 2010 __MyCompanyName__. All rights reserved. """ # TODO: index wrapping functions for adjacency matrices # # Python implementations of index wrapping functions from scipy.spatial.distance.squareform # # actual imp: (M is the squareform matrix, v the condensed vector, n the side of M, i.e. how many objet have their distances measured) # # void dist_to_squareform_from_vector(double *M, const double *v, int n) { # double *it; # const double *cit; # int i, j; # cit = v; # for (i = 0; i < n - 1; i++) { # it = M + (i * n) + i + 1; # for (j = i + 1; j < n; j++, it++, cit++) { # *it = *cit; # } # } # } # # void dist_to_vector_from_squareform(const double *M, double *v, int n) { # double *it; # const double *cit; # int i, j; # it = v; # for (i = 0; i < n - 1; i++) { # cit = M + (i * n) + i + 1; # for (j = i + 1; j < n; j++, it++, cit++) { # *it = *cit; # } # } # } # # vector offset = i*n+i+1 +j with and 0<=i<=n-1, i 0.5""" return nsphere_volume_p_norm( radius, dimensions, norm_order) def max_distance( dimensions=100, norm_order=1.): """What's the furthest two paints may be apart?""" return np.linalg.norm(np.ones(dimensions), norm_order) def normalise_lengths(M, norm_order=2., length=1.): """normalise the lengths of some stacked row vectors w/respect to a given norm and desired length. Modifies the matrix in-place. only works with float arrays. """ scale_factor = sp.apply_along_axis( lambda v: linalg.norm(v, ord=norm_order), 1, M, ).reshape(-1,1) scale_factor /= length M /= scale_factor def variable_normalise_lengths(M, target, norm_order=2.): """normalise the lengths of some stacked row vectors w/respect to a given norm and desired length. Modifies the matrix in-place. Only works with float arrays. """ scale_factor = sp.apply_along_axis( lambda v: linalg.norm(v, ord=norm_order), 1, M, ).reshape(-1,1) scale_factor /= target.reshape(-1,1) M /= scale_factor def isotropic_vector_axis_quantile(q, dims): """Distribution of axial projection of vectors isotopic on the surface of the n-sphere""" q = np.asarray(q) q_scaled = 2*q -1 return \ np.sign(q_scaled) * \ isotropic_vector_axis_half_quantile( 1 - np.abs(q_scaled), dims) def isotropic_vector_axis_half_quantile(q, dims): """We have a half quantile function given in terms of the F-distribution quantile function, but we know it is symmetric, so this can be used to get the full one""" g = stats.f.ppf(q, dims-1, 1) return 1.0/np.sqrt(g*(dims-1)+1) def random_unit_vectors(rows, columns, norm_order=2., length=1.): """general a matrix of isotropically-distributed unit row vectors""" #the normal distribution is isotropic(!) vectors = sp.random.normal(0., 1., (rows, columns)) normalise_lengths(vectors, norm_order, length) return vectors def wrapped_p_norm_raised(V1, V2, norm_order=2.): """p-norm in pac-man-space - periodic boundary conditions""" V1 = np.remainder(V1, 1) V2 = np.remainder(V2, 1) diffs = np.abs(V2-V1) wrapped_diffs = 1-diffs wrapped_coords = np.where(diffs