def object_cost_function(obj_a, obj_b): """ Evaluates the rotor cost function between two objects """ if grade_obj(obj_a) != grade_obj(obj_b): return np.finfo(float).max R = rotor_between_objects(obj_a, obj_b) return np.abs(val_rotor_cost_sparse(R.value))
def average_estimator(reference_model, query_model): """ Estimates the rotor that takes one set of objects to another by estimating the rotor between the average objects """ r_av = sum(reference_model)(grade_obj(reference_model[0])) q_av = sum(query_model)(grade_obj(reference_model[0])) return rotor_between_objects(q_av, r_av)
def interp_objects_root(C1, C2, alpha): """ Hadfield and Lasenby, Direct Linear Interpolation of Geometric Objects, AGACSE2018 Directly linearly interpolates conformal objects Return a valid object from the addition result C """ C = (1 - alpha) * C1 + alpha*C2 C3 = normalised(neg_twiddle_root(C)[0]) if cf.grade_obj(C1, 0.00001) != cf.grade_obj(C3, 0.00001): raise ValueError('Created object is not same grade') return C3
def interp_objects_root(C1, C2, alpha): """ Hadfield and Lasenby, Direct Linear Interpolation of Geometric Objects, AGACSE2018 Directly linearly interpolates conformal objects Return a valid object from the addition result C """ C = (1 - alpha) * C1 + alpha * C2 C3 = normalised(neg_twiddle_root(C)[0]) if cf.grade_obj(C1, 0.00001) != cf.grade_obj(C3, 0.00001): raise ValueError('Created object is not same grade') return C3
def sequential_object_rotor_estimation(reference_model, query_model, n_iterations=500, cost_tolerance=10 * (10**-16), random_sequence=False, object_type='generic', motor=True): """ Performs a sequential rotor update based on the rotors between individual objects Exits when a full rotation through all objects produces a very small update of rotor """ grade_list = [grade_obj(ob) for ob in query_model] R_total = 1.0 + 0.0 * e1 for j in range(n_iterations): r_set = 1.0 + 0.0 * e1 if random_sequence: indices = random.sample(range(len(query_model)), len(query_model)) else: indices = range(len(query_model)) for i in indices: grade = grade_list[i] new_obj = normalised(apply_rotor(query_model[i], R_total)(grade)) C1 = normalised(new_obj) C2 = normalised(reference_model[i]) if abs(C1 + C2) < 0.0001: C1 = -C1 if object_type == 'lines': rroot = normalised( square_roots_of_rotor((rotor_between_objects(C1, C2)))[0]) else: if motor: if grade_obj(C1, 0.00001) == 4: rroot = normalised( square_roots_of_rotor(rotor_between_objects( C1, C2))[0]) else: rroot = normalised( square_roots_of_rotor(motor_between_objects( C1, C2))[0]) else: rroot = normalised( square_roots_of_rotor(rotor_between_objects(C1, C2))[0]) r_set = normalised((rroot * r_set)(0, 2, 4)) R_total = normalised((rroot * R_total)(0, 2, 4)) if rotor_cost(r_set) < cost_tolerance: exit_flag = 0 return R_total, exit_flag exit_flag = 1 return R_total, exit_flag
def average_objects(obj_list, weights=[], check_grades=True): """ Hadfield and Lasenby, Direct Linear Interpolation of Geometric Objects, AGACSE2018 Directly averages conformal objects Return a valid object from the addition result C """ if len(weights) == len(obj_list): C = sum([o * w for o, w in zip(obj_list, weights)]) else: C = sum(obj_list) / len(obj_list) C3 = normalised(neg_twiddle_root(C)[0]) if check_grades: if cf.grade_obj(obj_list[0], 0.00001) != cf.grade_obj(C3, 0.00001): raise ValueError('Created object is not same grade') return C3
def test_grade_obj(self): algebras = [Cl(i) for i in [3, 4]] + [conformalize(Cl(3)[0])] for alg in algebras: layout = alg[0] for i in range(len(layout.sig)+1): mv = layout.randomMV()(i) assert i == grade_obj(mv)
def estimate_rotor_objects(reference_model, query_model, maxfev=20000, print_res=False, object_type='generic', motor=False, symmetric=False): """ Estimates the rotor that takes one set of objects to another """ grade_list = [grade_obj(q) for q in query_model] x0 = np.finfo(float).eps * np.random.rand(6) def minimisation_func(x): R = rotorconversion(x) query_model_remapped = [normalised((apply_rotor(l, R))(grade_list[i])) for i,l in enumerate(query_model)] return object_set_cost_sum(reference_model, query_model_remapped, object_type=object_type, motor=motor, symmetric=symmetric) res = minimize(minimisation_func, x0, method='SLSQP', options={'ftol': 10.0 ** (-16), \ 'maxiter': 1000, \ 'disp': False}) if print_res: print(res) res = minimize(minimisation_func, res.x, method='L-BFGS-B', options={'ftol':10.0**(-16), \ 'maxiter':1000, \ 'disp': False, \ 'maxls':40}) if print_res: print(res) rotor = rotorconversion(res.x) query_model_remapped = [normalised((apply_rotor(l, rotor))(grade_list[i])) for i,l in enumerate(query_model)] cost = object_set_cost_sum(reference_model, query_model_remapped, object_type=object_type, motor=motor, symmetric=symmetric) return rotor, cost
def sequential_object_rotor_estimation(reference_model, query_model, n_iterations=500, cost_tolerance=10 * (10**-16), random_sequence=False, object_type='generic'): """ Performs a sequential rotor update based on the rotors between individual objects Exits when the sum of the cost of rotor updates through the list is very small """ grade_list = [grade_obj(q) for q in query_model] R_total = 1.0 + 0.0 * e1 r_list = [] for j in range(n_iterations): cost_sum = 0.0 if random_sequence: indices = random.sample(range(len(query_model)), len(query_model)) else: indices = range(len(query_model)) for i in indices: C1 = (apply_rotor(query_model[i], R_total)(grade_list[i])).normal() C2 = reference_model[i] if abs(C1 + C2) < 0.0001: C1 = -C1 if object_type == 'lines': rroot = (square_roots_of_rotor(rotor_between_lines( C1, C2))[0]).normal() else: try: rroot = (square_roots_of_rotor( rotor_between_objects(C1, C2))[0]).normal() except: print(C1) print(C2) print(rotor_between_objects(C1, C2)) rroot = (square_roots_of_rotor( rotor_between_objects(C1, C2))[0]).normal() r_list.append(rroot) R_total = (rroot * R_total).normal() cost_sum += rotor_cost(rroot) if cost_sum < cost_tolerance: exit_flag = 0 return R_total, r_list, exit_flag exit_flag = 1 return R_total, r_list, exit_flag
def add_point_pair(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 2: raise ValueError('Input is not a point_pair') self.add(PointPair(mv,color))
def add_sphere(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 4: raise ValueError('Input is not a sphere') self.add(Sphere(mv,color))
def add_euc_point(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 1: raise ValueError('Input is not a euc_point') self.add(EucPoint(mv, color))
def add_circle(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 3: raise ValueError('Input is not a circle') self.add(Circle(mv, color))
def add_point_pair(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 2: raise ValueError('Input is not a point_pair') self.add(PointPair(mv, color))
def add_plane(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 4: raise ValueError('Input is not a plane') self.add(Plane(mv, color))
def add_conf_point(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 1: raise ValueError('Input is not a conf_point') self.add(ConfPoint(mv, color))
def add_euc_point(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 1: raise ValueError('Input is not a euc_point') self.add(EucPoint(mv,color))
def add_line(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 3: raise ValueError('Input is not a line') self.add(Line(mv, color))
def add_conf_point(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 1: raise ValueError('Input is not a conf_point') self.add(ConfPoint(mv, color))
def add_sphere(self, mv, color='rgb(0,0,0)'): if grade_obj(mv) != 4: raise ValueError('Input is not a sphere') self.add(Sphere(mv, color))
def add_circle(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 3: raise ValueError('Input is not a circle') self.add(Circle(mv,color))
def test_grade_obj(self, algebra): layout = algebra for i in range(len(layout.sig) + 1): mv = layout.randomMV()(i) assert i == grade_obj(mv)
def add_line(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 3: raise ValueError('Input is not a line') self.add(Line(mv,color))
def add_plane(self,mv,color='rgb(0,0,0)'): if grade_obj(mv) != 4: raise ValueError('Input is not a plane') self.add(Plane(mv,color))
def test_grade_obj(self, algebra, rng): # noqa: F811 layout = algebra for i in range(len(layout.sig) + 1): mv = layout.randomMV(rng=rng)(i) assert i == grade_obj(mv)