<jupyter_start><jupyter_text>iBP e Algebra Geométrica ConformeUsando a Algebra Geométrica Conforme, vamos ver como gerar árvore de busca do iBP, sem fazer amostragem.<jupyter_code>from cowboy import *
import math<jupyter_output><empty_output><jupyter_text>O ponto no modelo euclidiano pode ser representado por $$X_i = \alpha_1 e_1 + \alpha_2 e_2 + \alpha_3 e_3,$$ onde $e_1, e_2, e_3$ são as bases do espaço Euclidiano, e os pontos $X_i$ representam o centro do atomo de uma molecula de proteina.Iremos utilizar o modelo conforme da Algebra Geométrica para representarmos as circufenrencias, planos e ponto.Nesse modelo os pontos são representados por $$x_i = e_0 + X_i + \frac{1}{2}\parallel X_i \parallel^2e_{\infty},$$ onde $X_i$ representa o ponto no modelo euclidiano. Assim teremos, $x_1, x_2, x_3, x_4$, os quatro primeiros pontos que representam o centro do quatro primeiros atomos da molecula. Para o primeiro ponto $x_1$ podemos fixar ele na origem do nosso sistema de coordenadas.<jupyter_code>e1 = MultiVetor([[1, 2**0]])
e2 = MultiVetor([[1, 2**1]])
e3 = MultiVetor([[1, 2**2]])
emais = MultiVetor([[1, 2**3]])
emenos = MultiVetor([[1, 2**4]])
e0 = 0.5 * (emenos + emais)
einf = emenos - emais
def ponto_conforme(x):
    x_conforme = e0 + x + 0.5*(x*x)*einf
    return x_conforme
# Modelo Euclidiano
x2 = -1*e1
x3 = -1.5*e1 + (math.sqrt(3)/2)*e2
x4 = -1.311*e1 + 1.552*e2 + 0.702*e3

# Modelo Conforme
x1 = e0
x2 = e0 + x2 + 0.5*(x2*x2)*einf
x3 = e0 + x3 + 0.5*(x3*x3)*einf
x4 = e0 + x4 + 0.5*(x4*x4)*einf<jupyter_output><empty_output><jupyter_text>Neste problema são conhecidas as distancias entre atomos que fazem ligação, entretanto as distancias entre atomos que não fazem ligações são fornenecidas pelo experimento de Ressonancia Magnetica Nuclear, onde geralmente essas distancias são imprecisas. Para o nosso exemplo temos as distancias $$d_{i-1, i} = 1, \\ d_{i-2, i} = \sqrt{3}, \\ d_{1, 4} = 2.15, \\ d_{2, 5} \in [2.2, 2.6], \\ d_{1, 5} \in [2.45, 2.55]$$<jupyter_code>raio = {'i-1': 1, 'i-2': math.sqrt(3), '1,4': 2.15, '2,5': [2.2, 2.6], '1,5': [2.45, 2.55]}<jupyter_output><empty_output><jupyter_text>Uma esfera no $\mathbb{R}^3$, centrada em C, e com raio r, pode ser representada no $\mathbb{R}^{4,1}$ como:$$S = C - \frac{r^2}{2}e_{\infty} $$<jupyter_code>def esfera(x, raio):
    #transforma para um ponto no modelo conforme
    conforme = False
    for blade in x.componentes:
        if blade[1] == 2**4 or blade[1] == 2**3:
           conforme = True 

    if not conforme:
        x = e0 + x + 0.5*(x*x)*einf
    
    return x - (0.5*(raio**2)*einf)<jupyter_output><empty_output><jupyter_text>Para realizar a extração dos pontos iremos fazer o produto externo entre as esferas $S_{i-1}, S_{i-2}, S_{i-3}$. Assim temos que o par de pontos pode ser obtido por: $$pp = S_{i-1} \wedge S_{i-2} \wedge S_{i-3},$$ e o seu dual por: 
$$pp^{*} = S_{i-1} \wedge S_{i-2} \wedge S_{i-3} \rfloor (-1)\cdot(e_0 \wedge e_1 \wedge e_2 \wedge e_3 \wedge e_{\infty})$$
e a extração do ponto é feita por:
$$x_i = \frac{\sqrt{|pp^* \rfloor pp^*|} + pp^*}{(-1)\cdot(e_\infty \rfloor pp^*)}$$
caso $\Delta = pp^* \rfloor pp^*  0$ ela intersecta em mais de um ponto<jupyter_code>def analise(mult):
    mult_new = list()
    soma = 0

    for blade in mult.componentes:
        if abs(blade[0]) > 0.0000001:
            mult_new.append(blade)
        if blade[1] == 2**3:
            soma = soma + blade[0]
        elif blade[1] == 2**4:
            soma = soma + blade[0]

    mult_new = MultiVetor(mult_new)

    mult_new = (1/soma)*mult_new

    return mult_new

def extracao_ponto(s1, s2, s3):
    i = e0^e1^e2^e3^einf
    pp = s1^s2^s3
    dualpp = pp<<(-1*i)

    # EXTRACAO
    x4_a = (1*math.sqrt(float(abs(dualpp<<dualpp))) + dualpp) / -1*(einf<<dualpp)
    x4_b = (-1*math.sqrt(float(abs(dualpp<<dualpp))) + dualpp) / -1*(einf<<dualpp)

    return analise(x4_a), analise(x4_b)
a, b = extracao_ponto(esfera(x2, raio['2,5'][0]), esfera(x3, raio['i-2']), esfera(x4, raio['i-1']))
print(f'a = {a} \nb = {b} \n')

c, d = extracao_ponto(esfera(x2, raio['2,5'][1]), esfera(x3, raio['i-2']), esfera(x4, raio['i-1']))
print(f'c = {c} \nd = {d}')
z = (x3^x4^einf)<<(-1*(e0^e1^e2^e3^einf))

r = rotor(z, 1.453)
x5_a = r*a*inverso(r)

r = rotor(z, -1.453)
x5_b = r*b*inverso(r)

print(f" X_5(1.453) = {analise(x5_a)} \n X_5(-1.453) = {analise(x5_b)}")<jupyter_output>X_5(1.453) = -0.4545103617082674*e1 + 1.5184688468969887*e2 + 1.217073937673492*e3 - 1.496798138830456*e4 + 2.496798138830456*e5 
 X_5(-1.453) = -0.8567679105762847*e1 + 1.2862253427744788*e2 + 1.5523158475028107*e3 - 1.8990556876984739*e4 + 2.899055687698474*e5<jupyter_text>Assim nos temos os dois rotores associado aos arcos de possiveis soluções para $X_{5}$, como nos sabemos a distancia de $d_{1, 5} \in [2.45, 2.55]$, nos podemos fazer a extração dos pontos: $$pp = S_{1, 5} \wedge S_{3} \wedge S_{4},$$ onde $S_{1, 5}$ é a esfera de centro $X_{1}$ e raio $d_{1, 5} \in [2.45, 2.55]$, como nos temos um intervalo de distancia, iremos pegar os extremos desse invervalo assim temos $\underline{d_{1,5}} = min(d_{1, 5})$ e $\overline{d_{1,5}}  = max(d_{1, 5})$<jupyter_code>A_a, A_b = extracao_ponto(esfera(x3, raio['i-2']), esfera(x4, raio['i-1']), esfera(x1, raio['1,5'][0]))
A_c, A_d = extracao_ponto(esfera(x3, raio['i-2']), esfera(x4, raio['i-1']), esfera(x1, raio['1,5'][1]))

print(f'A_a = {analise(A_a)} \nA_b = {analise(A_b)}\n')
print(f'A_c = {analise(A_c)} \nA_d = {analise(A_d)}\n')<jupyter_output>A_a = -1.2599837919047157*e1 + 1.283189046518469*e2 + 1.6638409524448043*e3 - 2.5012499999999998*e4 + 3.5012499999999998*e5 
A_b = -0.6735069215271265*e1 + 2.29899678347644*e2 + 0.5133246694052717*e3 - 2.5012499999999998*e4 + 3.5012499999999998*e5

A_c = -1.4066508602468961*e1 + 1.3178293669474492*e2 + 1.6694786961736159*e3 - 2.7512500000000006*e4 + 3.7512500000000006*e5 
A_d = -0.7952701420775019*e1 + 2.376771833584789*e2 + 0.4701074900467275*e3 - 2.7512500000000006*e4 + 3.7512500000000006*e5<jupyter_text>Com os pontos $\overline{A_{5}^{0}}, \overline{A_{5}^{1}}, \underline{A_{5}^{0}}$ e $\underline{A_{5}^{1}}$ nos vamos definir o circulo orientado $C_5 = \underline{P_{5}^{0}} \wedge \overline{P_{5}^{0}} \wedge \overline{P_{5}^{1}}$<jupyter_code>c_5 = b ^ d ^ c<jupyter_output><empty_output><jupyter_text>Agora que conhecemos o circulo orientado $C_5$ iremos realizar os testes com os pontos $\overline{A_{5}^{0}}, \overline{A_{5}^{1}}, \underline{A_{5}^{0}}$ e $\underline{A_{5}^{1}}$<jupyter_code>t_1 = (A_b ^ d ^ c)*c_5
t_2 = (b ^ A_b ^ c)*c_5

print(f't_1 = {t_1.componentes[0][0]}\nt_2 = {t_2.componentes[0][0]}')

t_1 = (A_a ^ d ^ c)*c_5
t_2 = (b ^ A_a ^ c)*c_5

print(f't_1 = {t_1.componentes[0][0]}\nt_2 = {t_2.componentes[0][0]}')
t_1 = (A_d ^ d ^ c)*c_5
t_2 = (b ^ A_d ^ c)*c_5

print(f't_1 = {t_1.componentes[0][0]}\nt_2 = {t_2.componentes[0][0]}')
t_1 = (A_c ^ d ^ c)*c_5
t_2 = (b ^ A_c ^ c)*c_5

print(f't_1 = {t_1.componentes[0][0]}\nt_2 = {t_2.componentes[0][0]}')<jupyter_output>t_1 = 0.8734454461894969
t_2 = -1.3845390048140116<jupyter_text>Como o resultado para os arcos $\underline{P_{5}^{1}}, \overline{P_{5}^{1}}$ deram ambos $t_1$ e $t_2$ de $\overline{A_{5}^{1}}, \underline{A_{5}^{1}}$ deram positivo e negativo, isso significa que eles não intersectam o arco $\underline{P_{5}^{1}}, \overline{P_{5}^{1}}$. Entretanto, como $t_1$ e $t_2$ de $\overline{A_{5}^{0}}, \underline{A_{5}^{0}}$ deram ambos postivos o arco $\underline{P_{5}^{0}}, \overline{P_{5}^{0}}$ é reduzido para o arco $\underline{A_{5}^{0}}, \overline{A_{5}^{0}}$ com eixo de rotação definido por $$z_5 = ((\underline{A_{5}^{0}} \wedge \overline{A_{5}^{0}} \wedge \underline{P_{5}^{0}})^{*} \wedge e_{\infty})^{*}$$<jupyter_code>z_5 = dual(dual(A_b ^ A_d ^ b) ^ einf)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.19141369236631525, 'fraction_numerical': 0.1254921884923155, 'mean_word_length': 4.352821210061183, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '346895', 'license': 'MIT', 'n_tokens_mistral': 4103, 'n_tokens_neox': 3620, 'n_words': 778, 'path': 'src/exemplo.ipynb', 'repo_name': 'DilermandoQueiroz/Algebra-Geometrica', 'size': '7873'}