def algorithm_4(f_obs, F, phase_source, max_cycles=100, auto_converge_eps=1.e-7, use_cpp=True): """ Phased simultaneous search (alg4) """ fc, f_masks = F[0], F[1:] fc = fc.deep_copy() F = [fc] + F[1:] # C++ version if (use_cpp): return mosaic_ext.alg4([f.data() for f in F], f_obs.data(), phase_source.data(), max_cycles, auto_converge_eps) # Python version (1.2-3 times slower, but much more readable!) cntr = 0 x_prev = None while True: f_obs_cmpl = f_obs.phase_transfer(phase_source=phase_source) A = [] b = [] for j, Fj in enumerate(F): A_rows = [] for n, Fn in enumerate(F): Gjn = flex.real(Fj.data() * flex.conj(Fn.data())) A_rows.append(flex.sum(Gjn)) Hj = flex.real(Fj.data() * flex.conj(f_obs_cmpl.data())) b.append(flex.sum(Hj)) A.extend(A_rows) A = matrix.sqr(A) A_1 = A.inverse() b = matrix.col(b) x = A_1 * b # fc_d = flex.complex_double(phase_source.indices().size(), 0) for i, f in enumerate(F): fc_d += f.data() * x[i] phase_source = phase_source.customized_copy(data=fc_d) x_ = x[:] # cntr += 1 if (cntr > max_cycles): break if (x_prev is None): x_prev = x_[:] else: max_diff = flex.max( flex.abs(flex.double(x_prev) - flex.double(x_))) if (max_diff <= auto_converge_eps): break x_prev = x_[:] return x_
def update_target_and_grads(self, x): self.x = x s = 1 #180/math.pi i_model = flex.double(self.i_obs.data().size(), 0) for n, kn in enumerate(self.x): for m, km in enumerate(self.x): tmp = self.F[n].data() * flex.conj(self.F[m].data()) i_model += kn * km * flex.real(tmp) #pn = self.F[n].phases().data()*s #pm = self.F[m].phases().data()*s #Fn = flex.abs(self.F[n].data()) #Fm = flex.abs(self.F[m].data()) #i_model += kn*km*Fn*Fm*flex.cos(pn-pm) diff = i_model - self.i_obs.data() t = flex.sum(diff * diff) / 4 # g = flex.double() for j in range(len(self.F)): tmp = flex.double(self.i_obs.data().size(), 0) for m, km in enumerate(self.x): tmp += km * flex.real( self.F[j].data() * flex.conj(self.F[m].data())) #pj = self.F[j].phases().data()*s #pm = self.F[m].phases().data()*s #Fj = flex.abs(self.F[j].data()) #Fm = flex.abs(self.F[m].data()) #tmp += km * Fj*Fm*flex.cos(pj-pm) g.append(flex.sum(diff * tmp)) self.t = t self.g = g # if self.use_curvatures: d = flex.double() for j in range(len(self.F)): tmp1 = flex.double(self.i_obs.data().size(), 0) tmp2 = flex.double(self.i_obs.data().size(), 0) for m, km in enumerate(self.x): zz = flex.real(self.F[j].data() * flex.conj(self.F[m].data())) tmp1 += km * zz tmp2 += zz #pj = self.F[j].phases().data()*s #pm = self.F[m].phases().data()*s #Fj = flex.abs(self.F[j].data()) #Fm = flex.abs(self.F[m].data()) #tmp += km * Fj*Fm*flex.cos(pj-pm) d.append(flex.sum(tmp1 * tmp1 + tmp2)) self.d = d
def update_target_and_grads(self, x): self.x = x self.tgo.update(self.x) self.t = self.tgo.target() self.g = self.tgo.gradient() # # Reference implementation in Python # s = 1 #180/math.pi # i_model = flex.double(self.i_obs.data().size(),0) # for n, kn in enumerate(self.x): # for m, km in enumerate(self.x): # tmp = self.F[n].data()*flex.conj(self.F[m].data()) # i_model += kn*km*flex.real(tmp) # #pn = self.F[n].phases().data()*s # #pm = self.F[m].phases().data()*s # #Fn = flex.abs(self.F[n].data()) # #Fm = flex.abs(self.F[m].data()) # #i_model += kn*km*Fn*Fm*flex.cos(pn-pm) # diff = i_model - self.i_obs.data() # #print (flex.min(diff), flex.max(diff)) # t = flex.sum(diff*diff)/4 # # # g = flex.double() # for j in range(len(self.F)): # tmp = flex.double(self.i_obs.data().size(),0) # for m, km in enumerate(self.x): # tmp += km * flex.real( self.F[j].data()*flex.conj(self.F[m].data()) ) # #pj = self.F[j].phases().data()*s # #pm = self.F[m].phases().data()*s # #Fj = flex.abs(self.F[j].data()) # #Fm = flex.abs(self.F[m].data()) # #tmp += km * Fj*Fm*flex.cos(pj-pm) # g.append(flex.sum(diff*tmp)) # self.t = t/self.sum_i_obs # self.g = g/self.sum_i_obs # #print (self.t,t1) # #print (list(self.g)) # #print (list(g1)) # #print () # #assert approx_equal(self.t, t1, 5) # #assert approx_equal(self.g, g1, 1.e-6) # if self.use_curvatures: d = flex.double() for j in range(len(self.F)): tmp1 = flex.double(self.i_obs.data().size(), 0) tmp2 = flex.double(self.i_obs.data().size(), 0) for m, km in enumerate(self.x): zz = flex.real(self.F[j].data() * flex.conj(self.F[m].data())) tmp1 += km * zz tmp2 += zz #pj = self.F[j].phases().data()*s #pm = self.F[m].phases().data()*s #Fj = flex.abs(self.F[j].data()) #Fm = flex.abs(self.F[m].data()) #tmp += km * Fj*Fm*flex.cos(pj-pm) d.append(flex.sum(tmp1 * tmp1 + tmp2)) self.d = d
def algorithm_4(f_obs, F, max_cycles=100, auto_converge_eps=1.e-7): """ Phased simultaneous search """ fc, f_masks = F[0], F[1:] fc = fc.deep_copy() F = [fc] + F[1:] x_res = None cntr = 0 x_prev = None while True: f_obs_cmpl = f_obs.phase_transfer(phase_source=fc) A = [] b = [] for j, Fj in enumerate(F): A_rows = [] for n, Fn in enumerate(F): Gjn = flex.real(Fj.data() * flex.conj(Fn.data())) A_rows.append(flex.sum(Gjn)) Hj = flex.real(Fj.data() * flex.conj(f_obs_cmpl.data())) b.append(flex.sum(Hj)) A.extend(A_rows) A = matrix.sqr(A) A_1 = A.inverse() b = matrix.col(b) x = A_1 * b if x_res is None: x_res = flex.double(x) else: x_res += flex.double(x) x_ = [x[0]] + list(x_res[1:]) #print "iteration:", cntr, " ".join(["%10.6f"%i for i in x_]) # fc_d = fc.data() for i, f in enumerate(F): if i == 0: continue fc_d += x[i] * f.data() fc = fc.customized_copy(data=fc_d) cntr += 1 if (cntr > max_cycles): break if (x_prev is None): x_prev = x_[:] else: max_diff = flex.max( flex.abs(flex.double(x_prev) - flex.double(x_))) if (max_diff <= auto_converge_eps): break x_prev = x_[:] return x_
def algorithm_3(i_obs, fc, f_masks): """ Unphased two-step search """ F = [fc] + f_masks Gnm = [] cs = {} cntr = 0 nm = [] # Compute and store Gnm for n, Fn in enumerate(F): for m, Fm in enumerate(F): if m < n: continue Gnm.append(flex.real(Fn.data() * flex.conj(Fm.data()))) cs[(n, m)] = cntr cntr += 1 nm.append((n, m)) # Keep track of indices for "upper triangular matrix vs full" for k, v in zip(list(cs.keys()), list(cs.values())): i, j = k if i == j: continue else: cs[(j, i)] = v # Generate and solve system Ax=b, x = A_1*b A = [] b = [] for u, Gnm_u in enumerate(Gnm): for v, Gnm_v in enumerate(Gnm): scale = 2 n, m = nm[v] if n == m: scale = 1 A.append(flex.sum(Gnm_u * Gnm_v) * scale) b.append(flex.sum(Gnm_u * i_obs.data())) A = matrix.sqr(A) A_1 = A.inverse() b = matrix.col(b) x = A_1 * b # Expand Xmn from solution x Xmn = [] for n, Fn in enumerate(F): rows = [] for m, Fm in enumerate(F): x_ = x[cs[(n, m)]] rows.append(x_) Xmn.append(rows) # Do formula (19) lnK = [] for j, Fj in enumerate(F): t1 = flex.sum(flex.log(flex.double(Xmn[j]))) t2 = 0 for n, Fn in enumerate(F): for m, Fm in enumerate(F): t2 += math.log(Xmn[n][m]) t2 = t2 / (2 * len(F)) lnK.append(1 / len(F) * (t1 - t2)) return [math.exp(x) for x in lnK]