def test_negative_massey_and_cf(self): """ negative test - there is no polynomial logic behind the pi CF sequence. """ with mpmath.workdps(1000): rhs = SimpleContinuedFraction.from_irrational_constant( mpmath.pi, 200) shift_reg = massey.slow_massey(rhs.a_, 5657) self.assertTrue(len(shift_reg) > 99)
def test_alternating_sign_simple_cf(self): f_sym = e / (e - 1) shift_reg_cmp = [1, 0, -2, 0, 1] f_const = lambdify((), f_sym, modules="mpmath") with mpmath.workdps(self.precision): lhs = f_sym rhs = GeneralizedContinuedFraction.from_irrational_constant( f_const, [1, -1] * (self.precision // 10)) self.compare(lhs, rhs, self.precision // 20) shift_reg = massey.slow_massey(rhs.a_, 199) self.assertEqual(len(shift_reg), len(shift_reg_cmp)) for i in range(len(shift_reg)): self.assertEqual(shift_reg[i], shift_reg_cmp[i])
def test_massey_and_creation_of_simple_continued_fractions(self): """ unittests for our regular continued fractions """ rcf_constants = { 'e': e, 'bessel_ratio': besseli(1, 2) / besseli(0, 2), 'phi': phi } with mpmath.workdps(self.precision): for c in rcf_constants: with self.subTest(test_constant=c): lhs = rcf_constants[c] rhs = SimpleContinuedFraction.from_irrational_constant( lambdify((), lhs, modules="mpmath"), self.precision // 5) shift_reg = massey.slow_massey(rhs.a_, 199) self.assertLessEqual(len(shift_reg), 20) self.compare(lhs, rhs, self.precision // 20)
def find_signed_rcf_conj(self): """ Builds the final domain. Iterates throgh the domain: extraction->massey->check->save. Additional checks are performed to exclude degenerated cases. If a generic enumeration is given will use it instead of enumerating. """ inter_results = [] redundant_cycles = set() # Enumerate: if self.custom_enum is None: lhs = self.create_rational_variations_enum() else: if self.do_print: print("Substituting " + str(self.const_sym) + ' into generic LHS:') strt = time() lhs = [var.subs({sympy.symbols('x'): self.const_sym}) for var in self.custom_enum] if self.do_print: print("Took {} sec".format(time() - strt)) sign_seqs = [] for cyc_len in range(self.min_cycle_len, self.max_cycle_len + 1): sign_seqs = sign_seqs + list(itertools.product([-1, 1], repeat=cyc_len)) domain_size = len(lhs) * len(sign_seqs) if self.do_print: print("De-Facto Domain Size is: {}\n Starting preliminary search...".format(domain_size)) checkpoint = max(domain_size // 20, 5) count = 0 start = time() # Iterate bad_variation = [] for instance in itertools.product(lhs, sign_seqs): count += 1 var, sign_period = instance[0], list(instance[1]) if var == bad_variation: continue bad_variation = [] if ''.join([str(c) for c in sign_period]) in redundant_cycles: continue # if this cycle was not redundant it renders some future cycles redundant: for i in range(2, (self.max_cycle_len // len(sign_period)) + 1): redun = sign_period * i redundant_cycles.add(''.join([str(c) for c in redun])) var_gen = lambdify((), var, modules="mpmath") seq_len = len(sign_period) if (count % checkpoint == 0) and (self.do_print): print("\n{}% of domain searched.".format(round(100 * count / domain_size, 2))) print("{} possible results found".format(len(inter_results))) print("{} minutes passed.\n".format(round((time() - start) / 60, 2))) b_ = (sign_period * ((self.depth // seq_len) + 1)) # Concatenate periods to form sequence. b_ = b_[:self.depth] # Cut to proper size. with mpmath.workdps(self.enum_dps): try: signed_rcf = GeneralizedContinuedFraction.from_irrational_constant(const_gen=var_gen, b_=b_) except ZeroDivisionError: if self.do_print: print('lhs:') sympy.pprint(var) bad_variation = var continue a_ = signed_rcf.a_ if 0 in a_: continue if len(a_) < self.depth: continue a_lfsr = list(slow_massey(a_, self.prime)) clear_end_zeros(a_lfsr) if len(a_lfsr) < self.beauty_standard: inter_results.append([var, sign_period, a_[:(len(a_lfsr)-1)], a_lfsr]) return inter_results