def transport_plan_projections_transpose(im, supp, neighbors_graph, weights_neighbors, spectrum=None, indices=None): """ Adjoint operator to :func:`transport_plan_projections` """ from numpy import zeros, squeeze, sqrt, add, repeat shap = im.shape if indices is None: nb_proj = neighbors_graph.shape[3] indices = arange(0, nb_proj) else: nb_proj = size(indices) if spectrum is None: spectrum = ones((nb_proj, )) P_out = zeros((shap[0] * shap[1], shap[0] * shap[1], nb_proj)) siz_supp = neighbors_graph.shape[0] indx = repeat(supp[:, 0], 4).reshape((siz_supp, 4)) indy = repeat(supp[:, 1], 4).reshape((siz_supp, 4)) for i in range(0, nb_proj): add.at(P_out[:,:,indices[i]],(indx,indy),spectrum[indices[i]]*weights_neighbors[:,:,indices[i]]\ *im[neighbors_graph[:,0,:,indices[i]],neighbors_graph[:,1,:,indices[i]]]) return squeeze(P_out)
def transport_plan_projections(P, shap, supp, neighbors_graph, weights_neighbors, spectrum=None, indices=None): """ Computes monochromatic components (displacement interpolation steps) from transport plan. """ from numpy import zeros, int, squeeze, add, ones if indices is None: nb_proj = neighbors_graph.shape[3] indices = arange(0, nb_proj) else: nb_proj = size(indices) if spectrum is None: spectrum = ones((nb_proj, )) im_proj = zeros((shap[0], shap[1], nb_proj)) siz_supp = neighbors_graph.shape[0] for i in range(0, nb_proj): add.at(im_proj[:,:,indices[i]],(neighbors_graph[:,0,:,indices[i]],neighbors_graph[:,1,:,indices[i]]),\ spectrum[indices[i]]*weights_neighbors[:,:,indices[i]]*P[supp[:,0],supp[:,1]].reshape((siz_supp,1)).dot(ones((1,4)))) return squeeze(im_proj)
def transport_plan_projections_transpose_2(im_stack,supp,neighbors_graph,weights_neighbors,spectrum): """ Computes the adjoint operator of the displacement inteerpolation for a given transport plan.""" from numpy import zeros,squeeze,sqrt,add,repeat shap = im_stack.shape nb_proj = neighbors_graph.shape[3] P_out = zeros((shap[0]*shap[1],shap[0]*shap[1],nb_proj)) siz_supp = neighbors_graph.shape[0] indx = repeat(supp[:,0],4).reshape((siz_supp,4)) indy = repeat(supp[:,1],4).reshape((siz_supp,4)) for i in range(0,nb_proj): add.at(P_out[:,:,i],(indx,indy),spectrum[i]*weights_neighbors[:,:,i]*im_stack[neighbors_graph[:,0,:,i],neighbors_graph[:,1,:,i],i]) return P_out
def backward(self, idx: int, accum_grad: Function.T) -> Function.T: ''' Method which turns the column shaped input to image shape ''' # Create images placeholder images = zeros(self.children[0].shape) # Separate the image sections and the batch_size (shape[0]) separated_grad = accum_grad\ .reshape(self._n_features, -1, images.shape[0])\ .transpose(2, 0, 1) # Move the batch_size at the beginning # Fill in the placeholder k, i, j = self._im2col_indices add.at(images, (slice(None), k, i, j), separated_grad) return images
def transport_plan_projections_transpose_2(im_stack, supp, neighbors_graph, weights_neighbors, spectrum): """ Computes the adjoint operator of the displacement inteerpolation for a given transport plan.""" from numpy import zeros, squeeze, sqrt, add, repeat shap = im_stack.shape nb_proj = neighbors_graph.shape[3] P_out = zeros((shap[0] * shap[1], shap[0] * shap[1], nb_proj)) siz_supp = neighbors_graph.shape[0] indx = repeat(supp[:, 0], 4).reshape((siz_supp, 4)) indy = repeat(supp[:, 1], 4).reshape((siz_supp, 4)) for i in range(0, nb_proj): add.at( P_out[:, :, i], (indx, indy), spectrum[i] * weights_neighbors[:, :, i] * im_stack[neighbors_graph[:, 0, :, i], neighbors_graph[:, 1, :, i], i]) return P_out
def transport_plan_projections(P,shap,supp,neighbors_graph,weights_neighbors,spectrum=None,indices=None): """ Computes monochromatic components (displacement interpolation steps) from transport plan. """ from numpy import zeros,int,squeeze,add,ones if indices is None: nb_proj = neighbors_graph.shape[3] indices = arange(0,nb_proj) else: nb_proj = size(indices) if spectrum is None: spectrum = ones((nb_proj,)) im_proj = zeros((shap[0],shap[1],nb_proj)) siz_supp = neighbors_graph.shape[0] for i in range(0,nb_proj): add.at(im_proj[:,:,indices[i]],(neighbors_graph[:,0,:,indices[i]],neighbors_graph[:,1,:,indices[i]]),\ spectrum[indices[i]]*weights_neighbors[:,:,indices[i]]*P[supp[:,0],supp[:,1]].reshape((siz_supp,1)).dot(ones((1,4)))) return squeeze(im_proj)
def transport_plan_projections_transpose(im,supp,neighbors_graph,weights_neighbors,spectrum=None,indices=None): """ Adjoint operator to :func:`transport_plan_projections` """ from numpy import zeros,squeeze,sqrt,add,repeat shap = im.shape if indices is None: nb_proj = neighbors_graph.shape[3] indices = arange(0,nb_proj) else: nb_proj = size(indices) if spectrum is None: spectrum = ones((nb_proj,)) P_out = zeros((shap[0]*shap[1],shap[0]*shap[1],nb_proj)) siz_supp = neighbors_graph.shape[0] indx = repeat(supp[:,0],4).reshape((siz_supp,4)) indy = repeat(supp[:,1],4).reshape((siz_supp,4)) for i in range(0,nb_proj): add.at(P_out[:,:,indices[i]],(indx,indy),spectrum[indices[i]]*weights_neighbors[:,:,indices[i]]\ *im[neighbors_graph[:,0,:,indices[i]],neighbors_graph[:,1,:,indices[i]]]) return squeeze(P_out)
def sample(bins, time, value): """ Given value[i] was observed at time[i], group them into bins i.e., *(bins[j], bins[j+1], ...)* Values for bin j are equal to the average of all value[k] and, bin[j] <= time[k] < bin[j+1]. __Arguments__ bins: _np.array_ Endpoints of the bins. For n bins it shall be of length n + 1. t: _np.array_ Times at which the values are observed. vt: _np.array_ Values for those times. __Returns__ x: _np.array_ Endspoints of all the bins. y: _np.array_ Average values in all bins. """ bin_idx = np_digitize(time, bins) - 1 value_sums = np_zeros(shape=len(bins) - 1, dtype=np_float32) value_cnts = np_zeros(shape=len(bins) - 1, dtype=np_float32) np_add.at(value_sums, bin_idx, value) np_add.at(value_cnts, bin_idx, 1) # ensure graph has no holes zeros = np_where(value_cnts == 0) assert value_cnts[0] > 0 for z in zeros: value_sums[z] = value_sums[z - 1] value_cnts[z] = value_cnts[z - 1] return bins[1:], value_sums / value_cnts
def train_document_dm_concat(model, doc_words, doctag_indexes, alpha, work=None, neu1=None, learn_doctags=True, learn_words=True, learn_hidden=True, word_vectors=None, word_locks=None, doctag_vectors=None, doctag_locks=None): """ Update distributed memory model ("PV-DM") by training on a single document, using a concatenation of the context window word vectors (rather than a sum or average). Called internally from `Doc2Vec.train()` and `Doc2Vec.infer_vector()`. The document is provided as `doc_words`, a list of word tokens which are looked up in the model's vocab dictionary, and `doctag_indexes`, which provide indexes into the doctag_vectors array. Any of `learn_doctags', `learn_words`, and `learn_hidden` may be set False to prevent learning-updates to those respective model weights, as if using the (partially-)frozen model to infer other compatible vectors. This is the non-optimized, Python version. If you have a C compiler, gensim will use the optimized version from doc2vec_inner instead. """ if word_vectors is None: word_vectors = model.syn0 if word_locks is None: word_locks = model.syn0_lockf if doctag_vectors is None: doctag_vectors = model.docvecs.doctag_syn0 if doctag_locks is None: doctag_locks = model.docvecs.doctag_syn0_lockf word_vocabs = [model.vocab[w] for w in doc_words if w in model.vocab and model.vocab[w].sample_int > model.random.rand() * 2**32] doctag_len = len(doctag_indexes) if doctag_len != model.dm_tag_count: return 0 # skip doc without expected number of doctag(s) (TODO: warn/pad?) null_word = model.vocab['\0'] pre_pad_count = model.window post_pad_count = model.window padded_document_indexes = ( (pre_pad_count * [null_word.index]) # pre-padding + [word.index for word in word_vocabs if word is not None] # elide out-of-Vocabulary words + (post_pad_count * [null_word.index]) # post-padding ) for pos in range(pre_pad_count, len(padded_document_indexes) - post_pad_count): word_context_indexes = ( padded_document_indexes[(pos - pre_pad_count): pos] # preceding words + padded_document_indexes[(pos + 1):(pos + 1 + post_pad_count)] # following words ) word_context_len = len(word_context_indexes) predict_word = model.vocab[model.index2word[padded_document_indexes[pos]]] # numpy advanced-indexing copies; concatenate, flatten to 1d l1 = concatenate((doctag_vectors[doctag_indexes], word_vectors[word_context_indexes])).ravel() neu1e = train_cbow_pair(model, predict_word, None, l1, alpha, learn_hidden=learn_hidden, learn_vectors=False) # filter by locks and shape for addition to source vectors e_locks = concatenate((doctag_locks[doctag_indexes], word_locks[word_context_indexes])) neu1e_r = (neu1e.reshape(-1, model.vector_size) * np_repeat(e_locks, model.vector_size).reshape(-1, model.vector_size)) if learn_doctags: np_add.at(doctag_vectors, doctag_indexes, neu1e_r[:doctag_len]) if learn_words: np_add.at(word_vectors, word_context_indexes, neu1e_r[doctag_len:]) return len(padded_document_indexes) - pre_pad_count - post_pad_count
def orbital_momentum(self, projection='orbital', method='onsite'): r""" Calculate orbital angular momentum on either atoms or orbitals Currently this implementation equals the Siesta implementation in that the on-site approximation is enforced thus limiting the calculated quantities to obey the following conditions: 1. Same atom 2. :math:`l>0` 3. :math:`l_\nu \equiv l_\mu` 4. :math:`m_\nu \neq m_\mu` 5. :math:`\zeta_\nu \equiv \zeta_\mu` This allows one to sum the orbital angular moments on a per atom site. Parameters ---------- projection : {'orbital', 'atom'} whether the angular momentum is resolved per atom, or per orbital method : {'onsite'} method used to calculate the angular momentum Returns ------- numpy.ndarray orbital angular momentum with the last dimension equalling the :math:`L_x`, :math:`L_y` and :math:`L_z` components """ # Check that the spin configuration is correct if not self.spin.is_spinorbit: raise ValueError( f"{self.__class__.__name__}.orbital_momentum requires a spin-orbit matrix" ) # First we calculate orb_lmZ = _a.emptyi([self.no, 3]) for atom, idx in self.geometry.atoms.iter(True): # convert to FIRST orbital index per atom oidx = self.geometry.a2o(idx) # loop orbitals for io, orb in enumerate(atom): orb_lmZ[oidx + io, :] = orb.l, orb.m, orb.Z # Now we need to calculate the stuff DM = self.copy() # The Siesta convention *only* calculates contributions # in the primary unit-cell. DM.set_nsc([1] * 3) geom = DM.geometry csr = DM._csr # The siesta moments are only *on-site* per atom. # 1. create a logical index for the matrix elements # that is true for ia-ia interaction and false # otherwise idx = repeat(_a.arangei(geom.no), csr.ncol) aidx = geom.o2a(idx) # Sparse matrix indices for data sidx = array_arange(csr.ptr[:-1], n=csr.ncol, dtype=np.int32) jdx = csr.col[sidx] ajdx = geom.o2a(jdx) # Now only take the elements that are *on-site* and which are *not* # having the same m quantum numbers (if the orbital index is the same # it means they have the same m quantum number) # # 1. on the same atom # 2. l > 0 # 3. same quantum number l # 4. different quantum number m # 5. same zeta onsite_idx = ((aidx == ajdx) & \ (orb_lmZ[idx, 0] > 0) & \ (orb_lmZ[idx, 0] == orb_lmZ[jdx, 0]) & \ (orb_lmZ[idx, 1] != orb_lmZ[jdx, 1]) & \ (orb_lmZ[idx, 2] == orb_lmZ[jdx, 2])).nonzero()[0] # clean variables we don't need del aidx, ajdx # Now reduce arrays to the orbital connections that obey the # above criteria idx = idx[onsite_idx] idx_l = orb_lmZ[idx, 0] idx_m = orb_lmZ[idx, 1] jdx = jdx[onsite_idx] jdx_m = orb_lmZ[jdx, 1] sidx = sidx[onsite_idx] # Sum the spin-box diagonal imaginary parts DM = csr._D[sidx][:, [4, 5]].sum(1) # Define functions to calculate L projections def La(idx_l, DM, sub): if len(sub) == 0: return [] return (idx_l[sub] * (idx_l[sub] + 1) * 0.5)**0.5 * DM[sub] def Lb(idx_l, DM, sub): if len(sub) == 0: return return (idx_l[sub] * (idx_l[sub] + 1) - 2)**0.5 * 0.5 * DM[sub] def Lc(idx, idx_l, DM, sub): if len(sub) == 0: return [], [] sub = sub[idx_l[sub] >= 3] if len(sub) == 0: return [], [] return idx[sub], (idx_l[sub] * (idx_l[sub] + 1) - 6)**0.5 * 0.5 * DM[sub] # construct for different m # in Siesta the spin orbital angular momentum # is calculated by swapping i and j indices. # This is somewhat confusing to me, so I reversed everything. # This will probably add to the confusion when comparing the two # Additionally Siesta calculates L for <i|L|j> and then does: # L(:) = [L(3), -L(2), -L(1)] # Here we *directly* store the quantities used. # Pre-allocate the L_xyz quantity per orbital. L = np.zeros([geom.no, 3]) L0 = L[:, 0] L1 = L[:, 1] L2 = L[:, 2] # Pre-calculate all those which have m_i + m_j == 0 b = (idx_m + jdx_m == 0).nonzero()[0] subtract.at(L2, idx[b], idx_m[b] * DM[b]) del b # mi == 0 i_m = idx_m == 0 # mj == -1 sub = logical_and(i_m, jdx_m == -1).nonzero()[0] subtract.at(L0, idx[sub], La(idx_l, DM, sub)) # mj == 1 sub = logical_and(i_m, jdx_m == 1).nonzero()[0] add.at(L1, idx[sub], La(idx_l, DM, sub)) # mi == 1 i_m = idx_m == 1 # mj == -2 sub = logical_and(i_m, jdx_m == -2).nonzero()[0] subtract.at(L0, idx[sub], Lb(idx_l, DM, sub)) # mj == 0 sub = logical_and(i_m, jdx_m == 0).nonzero()[0] subtract.at(L1, idx[sub], La(idx_l, DM, sub)) # mj == 2 sub = logical_and(i_m, jdx_m == 2).nonzero()[0] add.at(L1, idx[sub], Lb(idx_l, DM, sub)) # mi == -1 i_m = idx_m == -1 # mj == -2 sub = logical_and(i_m, jdx_m == -2).nonzero()[0] add.at(L1, idx[sub], Lb(idx_l, DM, sub)) # mj == 0 sub = logical_and(i_m, jdx_m == 0).nonzero()[0] add.at(L0, idx[sub], La(idx_l, DM, sub)) # mj == 2 sub = logical_and(i_m, jdx_m == 2).nonzero()[0] add.at(L0, idx[sub], Lb(idx_l, DM, sub)) # mi == 2 i_m = idx_m == 2 # mj == -3 sub = logical_and(i_m, jdx_m == -3).nonzero()[0] subtract.at(L0, *Lc(idx, idx_l, DM, sub)) # mj == -1 sub = logical_and(i_m, jdx_m == -1).nonzero()[0] subtract.at(L0, idx[sub], Lb(idx_l, DM, sub)) # mj == 1 sub = logical_and(i_m, jdx_m == 1).nonzero()[0] subtract.at(L1, idx[sub], Lb(idx_l, DM, sub)) # mj == 3 sub = logical_and(i_m, jdx_m == 3).nonzero()[0] add.at(L1, *Lc(idx, idx_l, DM, sub)) # mi == -2 i_m = idx_m == -2 # mj == -3 sub = logical_and(i_m, jdx_m == -3).nonzero()[0] add.at(L1, *Lc(idx, idx_l, DM, sub)) # mj == -1 sub = logical_and(i_m, jdx_m == -1).nonzero()[0] subtract.at(L1, idx[sub], Lb(idx_l, DM, sub)) # mj == 1 sub = logical_and(i_m, jdx_m == 1).nonzero()[0] add.at(L0, idx[sub], Lb(idx_l, DM, sub)) # mj == 3 sub = logical_and(i_m, jdx_m == 3).nonzero()[0] add.at(L0, *Lc(idx, idx_l, DM, sub)) # mi == -3 i_m = idx_m == -3 # mj == -2 sub = logical_and(i_m, jdx_m == -2).nonzero()[0] subtract.at(L1, *Lc(idx, idx_l, DM, sub)) # mj == 2 sub = logical_and(i_m, jdx_m == 2).nonzero()[0] add.at(L0, *Lc(idx, idx_l, DM, sub)) # mi == 3 i_m = idx_m == 3 # mj == -2 sub = logical_and(i_m, jdx_m == -2).nonzero()[0] subtract.at(L0, *Lc(idx, idx_l, DM, sub)) # mj == 2 sub = logical_and(i_m, jdx_m == 2).nonzero()[0] subtract.at(L1, *Lc(idx, idx_l, DM, sub)) if "orbital" == projection: return L elif "atom" == projection: # Now perform summation per atom l = np.zeros([geom.na, 3], dtype=L.dtype) add.at(l, geom.o2a(np.arange(geom.no)), L) return l raise ValueError( f"{self.__class__.__name__}.orbital_momentum must define projection to be 'orbital' or 'atom'." )