def expand_Q_from(Q, P): ''' Q : k * 3 P : k+1 * 3 return Q : k+1 * 3 ''' nr_points = Q.shape[0] lengths = q_config[(nr_points - 2) % 3]["side_lengths"] rad = q_config[(nr_points - 2) % 3]["rad"] # center of circle of possible next points center_para = lengths[1] * np.cos(rad) / lengths[0] center_of_next_Q = Q[-1] * (1 - center_para) + Q[-2] * center_para proj_para = np.dot(P[-1] - Q[-1], Q[-1] - Q[-2]) / (lengths[0] * lengths[0]) proj = Q[-1] + proj_para * (Q[-1] - Q[-2]) new_q_point = center_of_next_Q + ( P[-1] - proj) * lengths[1] * np.sin(rad) / np.linalg.norm(P[-1] - proj) Q = np.vstack([Q, new_q_point]) Q = kabsched_Q(Q, P) return Q
def start_intensively_optimal_construct_Q_from(P, internal=5, rounds=5): ''' construct a init Q for further refinement ''' lengths = q_config[0]["side_lengths"] p0 = P[0] p1 = P[1] q1 = p0 + (p1 - p0) / np.linalg.norm(p1 - p0) * lengths[0] Q = np.array([P[0], q1]) Q = kabsched_Q(Q, P[0:2]) for i in range(2, P.shape[0]): print 'now: ', i tmp_p = P[0:i + 1] Q = expand_Q_from(Q, tmp_p) for _ in range(5): Q = expand_Q_from(Q[0:-1], tmp_p) if i < 500: Q = optimize(Q, tmp_p, 5) elif i % internal == 0: Q = optimize(Q, tmp_p, rounds) print rmsd(Q, P) print "lower bound: ", lower_bound(Q, P) return Q
def randomly_expand_Q_from(Q, P): nr_points = Q.shape[0] lengths = q_config[(nr_points - 2) % 3]["side_lengths"] rad = q_config[(nr_points - 2) % 3]["rad"] center_para = lengths[1] * np.cos(rad) / lengths[0] center_of_next_Q = Q[-1] * (1 - center_para) + Q[-2] * center_para u1 = (Q[-1] - Q[-2]) u1 = u1 / np.linalg.norm(u1) u2 = np.array([1, 0, 0]) if np.abs(u1[1]) < np.abs(u1[0]): u2 = np.array([0, 1, 0]) u2 = np.cross(u1, u2) # u2 = np.array([u1[1] * u2[2] - u1[2] * u2[1], u1[2] * u2[0] - u1[0] * u2[2], u1[0] * u2[1] - u1[1] * u2[0]]) u2 = u2 / np.linalg.norm(u2) # u3 = np.array([u1[1] * u2[2] - u1[2] * u2[1], u1[2] * u2[0] - u1[0] * u2[2], u1[0] * u2[1] - u1[1] * u2[0]]) u3 = np.cross(u1, u2) U = np.array([u1, u2, u3]) next_rad = random.random() * np.pi * 2 radius = lengths[1] * np.sin(rad) next_Q_point_in_U = np.array( [0, radius * np.sin(next_rad), radius * np.cos(next_rad)]) next_Q_point = np.dot(next_Q_point_in_U, U) + center_of_next_Q Q = np.vstack([Q, next_Q_point]) Q = kabsched_Q(Q, P) return Q
def optimize_structure_by_pos(Q_origin, P_origin, k_pos): assert k_pos > 1 assert k_pos < P_origin.shape[0] - 1 nr_P_row = P_origin.shape[0] P = np.copy(P_origin) Q = np.copy(Q_origin) k = k_pos v1 = (Q[k] - Q[k - 1]) u1 = v1 / np.linalg.norm(v1) u2 = np.array([1, 0, 0]) if np.abs(u1[1]) < np.abs(u1[0]): u2 = np.array([0, 1, 0]) u2 = np.cross(u1, u2) # u2 = np.array([u1[1] * u2[2] - u1[2] * u2[1], u1[2] * u2[0] - u1[0] * u2[2], u1[0] * u2[1] - u1[1] * u2[0]]) u2 = u2 / np.linalg.norm(u2) # u3 = np.array([u1[1] * u2[2] - u1[2] * u2[1], u1[2] * u2[0] - u1[0] * u2[2], u1[0] * u2[1] - u1[1] * u2[0]]) u3 = np.cross(u1, u2) U = np.array([u1, u2, u3]) Qk = Q[k + 1:nr_P_row] Pk = P[k + 1:nr_P_row] q_point_k_wrap = np.copy(np.array([Q[k]])) Qk = Qk - np.repeat(q_point_k_wrap, [Qk.shape[0]], axis=0) Pk = Pk - np.repeat(q_point_k_wrap, [Qk.shape[0]], axis=0) Qk_U = np.dot(Qk, U.transpose()) Pk_U = np.dot(Pk, U.transpose()) alpha = np.dot(Qk_U[:, 1], Pk_U[:, 2]) - np.dot(Qk_U[:, 2], Pk_U[:, 1]) beta = np.dot(Qk_U[:, 1], Pk_U[:, 1]) + np.dot(Qk_U[:, 2], Pk_U[:, 2]) cos_theta = beta / np.sqrt(alpha**2 + beta**2) sin_theta = alpha / np.sqrt(alpha**2 + beta**2) pre_A = np.array([[1, 0, 0], [0, cos_theta, sin_theta], [0, -sin_theta, cos_theta]]) A = np.dot(np.dot(U.transpose(), pre_A), U) Qk = np.dot(Qk, A) Qk = Qk + np.repeat(q_point_k_wrap, [Qk.shape[0]], axis=0) Q[k + 1:nr_P_row] = Qk Q = kabsched_Q(Q, P) return Q
def randomly_construct_Q_from(P): ''' randomly generate initial state to test if the original algrithm can get the optimal result ''' lengths = q_config[0]["side_lengths"] p0 = P[0] p1 = P[1] q1 = p0 + (p1 - p0) / np.linalg.norm(p1 - p0) * lengths[0] Q = np.array([P[0], q1]) Q = kabsched_Q(Q, P[0:2]) for i in range(2, P.shape[0]): tmp_p = P[0:i + 1] Q = randomly_expand_Q_from(Q, tmp_p) print rmsd(Q, P) return Q
def construct_Q_from(P): ''' construct a init Q for further refinement ''' lengths = q_config[0]["side_lengths"] p0 = P[0] p1 = P[1] q1 = p0 + (p1 - p0) / np.linalg.norm(p1 - p0) * lengths[0] Q = np.array([P[0], q1]) Q = kabsched_Q(Q, P[0:2]) for i in range(2, P.shape[0]): tmp_p = P[0:i + 1] Q = expand_Q_from(Q, tmp_p) for _ in range(5): Q = expand_Q_from(Q[0:-1], tmp_p) print rmsd(Q, P) print "lower bound: ", lower_bound(Q, P) return Q