lunes, 7 de mayo de 2012

Clase: Ecuaciones diofánticas y su solución general (PYTHON)

Esta clase es util para resolver problemas relacionados con ecuaciones diofánticas de dos variables, si alguien sabe como generalizar a n variables me puede dejar la información ya que ahora no tengo tiempo para investigar.

Con ella también se puede sacar el M.C.D. con una función que se implementó en el módulo para alivianar el proceso.

El módulo que les dejo aún está muy incompleto y lo pienso ampliar con los conocimientos que valla aprendiendo de Matemáticas Discretas.




# -*- coding: utf-8 -*-
###############################################################
#         MATEMATICAS DISCRETAS
#   Juan Fernando Hernandez Z - Universidad de Antioquia
#
#  Clase para el manejo de matematicas discretas 
###############################################################

def mcd(a, b):
 D = Diofanticas(a, b)
 D.__calcularMCD__()
 return D.MCD

class Diofantica:
  
 #a es la constante de la x y b la de la y
 def __init__(self, a, b):
  self.__a__ , self.__b__ = a, b
  self.__c__ = int()
  
  #GLOBAL
  #Matriz nx4 (Dividedo, Divisor, cociente, residuo)
  self.__mMCD__ = []
  self.MCD = int()
  
  #CL de valores Para la Ecn
  self.CL = []
  
 
 #                  Calculo del MCD
 ####################################################################
 
 def __calcularMCD__(self):

  if(len(self.__mMCD__) != 0): self.__mMCD__.clear()
  
  a_aux, b_aux = sorted([self.__a__, self.__b__], reverse=True)
  
  div = self.__divisionA__(a_aux, b_aux)
  self.__mMCD__.append(div)
  
  #Mientras el residuo no sea cero
  while (div[3] != 0):
   div = self.__divisionA__(div[1],div[3])
   self.__mMCD__.append(div)
 
  #Retorno el ultimo divisor (Penultimo residuo)
  self.MCD = div[1]
   
 def __divisionA__(self,x, y):
  return [x,  y,  x//y,  x%y]
  
  
    #    Calculo del MCD como C.L. (AX + BY = MCD)
 ####################################################################
 # R1 = [1, -C1]
 # R2 = [0, 1] - C2*R1
 # Rn = [R(n-2)] - Cn[R(n-1)]    /n >= 3
 
 
 
 def __reverseMCD__(self):
  #Matriz nx2 para hallar la CL (A, B)
  mRegresion = []
  fMatriz = len(self.__mMCD__)
  
  # R1
  Cn = self.__mMCD__[0][2]
  Rn = [1, -Cn]
  mRegresion.append(Rn)
  
  if(self.__a__ < self.__b__): self.CL = mRegresion[fMatriz-2][::-1]
  else: self.CL = mRegresion[fMatriz-2]
  
  return 0
  
  #R2
  Cn = self.__mMCD__[1][2]
  Rn = self.__sumaV__([0 , 1] , self.__multEV__(-Cn, mRegresion[0]))
  mRegresion.append(Rn)
  if(fMatriz == 2): return Rn
  
  if(self.__a__ < self.__b__): self.CL = mRegresion[fMatriz-2][::-1]
  else: self.CL = mRegresion[fMatriz-2]
  
  return 0
  
  #R >=3  Range no me saca en lista el valor maximo
  for n in range(2, fMatriz - 1):
   Cn = self.__mMCD__[n][2]
   Rn = self.__sumaV__(mRegresion[n-2] , self.__multEV__(-Cn, mRegresion[n-1]))
   mRegresion.append(Rn)
  

  if(self.__a__ < self.__b__): self.CL = mRegresion[fMatriz-2][::-1]
  else: self.CL = mRegresion[fMatriz-2]
  
  return 0
 
 #suma de vectores(Dim = 2)
 def __sumaV__(self, V1, V2):
  return [V1[0]+V2[0] , V1[1]+V2[1]]
  
 #multiplicacion vector(Dim = 2) escalar 
 def __multEV__(self, C, V):
  return [C*V[0] , C*V[1]]


 #  Solucion Ecn diofántica 2 variables  AX + BY = C
 ####################################################################
 
 #Retorna una matriz 2x2 con la Sln general de la Ecuacion
 def __solve__(self):
  self.__calcularMCD__()
  self.__reverseMCD__()
  
  
 def solucionGeneral(self, c):
  if(len(self.CL) == 0): self.__solve__()
  self.__c__ = c
  if (self.__solucionable__(c) == False): return -1
  
  mult = c//self.MCD
  
  SlnX = [self.CL[0] * mult, self.__b__//self.MCD]
  SlnY = [self.CL[1] * mult, -(self.__a__//self.MCD)]
  
  return [SlnX, SlnY]
  
 def __solucionable__(self, c):
  prueba = c%self.MCD
  if (prueba == 0): 
   return True
  return False


Las dos funciones principales del módulo son mcd(n1, n2) que retorna el máximo común divisor entre dos números y Diofantica.solucionGeneral(c) la cual retorna una matriz 4x4 con la solucion general de la ecuación donde la primera fila corresponde a la solución en X y la segunda fila a la solución en Y.

Para hallar la C.L. implementé un algoritmo general así:

 # R1 = [1, -C1]
 # R2 = [0, 1] - C2*R1
 # Rn = [R(n-2)] - Cn[R(n-1)]    /n >= 3

Donde Rn es la combinación lineal buscada.

No hay comentarios:

Publicar un comentario