SlideShare una empresa de Scribd logo
Acerca de los algoritmos de mezcla en cajeros automáticos.
I. Introducción:
Como parte del desarrollo de los aplicativos para los cajeros automáticos de Telmex y Banamex
tuve la necesidad de implementar diversos algoritmos para el despacho y entrega de efectivo
tanto en billetes como en monedas. El primero de ellos fue para una máquina receptora de pagos
de Telmex la cual solo entregaba efectivo en monedas; la solución requería el dar el mínimo
número de monedas y aunado a que una de las denominaciones era de $1 redundo en un fácil y
sencillo desarrollo.
Por razones que no vienen al caso mencionar, tuve la necesidad de implementar este algoritmo en
los cajeros Diebold instalados en Banamex. La primera complicación, respecto a lo desarrollado
para Telmex, consistió en que aquí no se contaba con una denominación unitaria con que cubrir el
potencial remanente entre lo requerido y lo proporcionado por la mezcla con las otras
denominaciones.
Adicionalmente, también en Banamex, se requirió del desarrollo de otro algoritmo cuya mezcla
fuese una cantidad más o menos igual de billetes de cada una de las denominaciones; una virtud
de tal algoritmo consiste en que, tratándose de billetes, esta mezcla es preferida por el cliente;
otra es que si la dotación inicial consiste del mismo número de billetes para cada una de las
denominaciones, en principio (y solo en principio), los casetes se vaciaran más o menos al mismo
tiempo; sin embargo la realidad es un poco más compleja, por ejemplo, esto no ocurrirá con una
denominación alta en una zona donde el monto promedio de retiros sea menor al valor de esta (la
determinación de denominaciones por zona no es materia de los algoritmos de mezcla, pero un
buen emulador que implemente los distintos algoritmos ayuda en tal determinación). Haciendo
abstracción de esta última problemática, es necesario reiterar que el vaciado simultáneo de los
casetes solo opera cuando el número de billetes de cada denominación es el mismo.
Un tercer algoritmo que desarrollé para Banamex fue el "Balanceado por existencias", en este se
intenta despachar más billetes de la denominación que más billetes tenga en el momento del
despacho, pero respetando, en la medida de lo posible, el máximo de denominaciones. A
diferencia de los algoritmos anteriores, cuya mezcla siempre es la misma para un monto
determinado, en esta la mezcla varia de despacho en despacho.
La motivación esencial del desarrollo de este algoritmo fue que un determinado modelo de los
cajeros fabricados por Diebold cuentan con 5 casetes para el para el despacho de billetes, pero lo
mayoría de los clientes utilizan solo 3 o 4 denominaciones para dotar sus cajeros y aunque las
denominaciones legales en México son 6, no es esperable que en un cajero en particular se
utilicen más de 4, las razones son:
1. La denominación $1,000 es de muy baja circulación.
2. La denominación de $20 puede ser adecuada para zonas populares, pero en estas
mismas es probable que no lo sea la de $500
3. En zonas medias y altas no resulta adecuada la denominación de $20
Ahora bien, para acomodar 4 denominaciones en 5 casetes es necesario que dos de ellos carguen
la misma denominación y si a cada casete se le dota de un mismo número de billetes es obvio que
tal denominación tendrá el doble de piezas que las otras. Aplicar el algoritmo de "máximo de
denominaciones" en estas condiciones implica que al agotarse las denominaciones con un solo
casete, de la denominación repetida quedará un casete lleno o dos medio vacíos si se utiliza la
técnica de despacho alternado.
Cabe aclarar que este algoritmo no solo se aplica a cajeros con 5 casetes, de hecho en los bancos
es práctica común el cargar solo 3 denominaciones en 4 o 5 casetes e incluso en cajeros con casete
por denominación el despacho se mejora al minimizar las diferencias que surgen en el algoritmo
de "Máximo de denominaciones" y con ello el vaciado simultáneo es más preciso.
Actualmente estos algoritmos los tengo implementados en un componente ActiveX desarrollado
en Visual Studio 2010 en un proyecto "MFC ActiveX Control" de Visual C++. También los tengo
implementado en un componente .NET con C#.
También he desarrollado un programa de prueba, en VB.NET, donde se puede utilizar cualquiera
de los componentes anteriores (solo hay que sustituir la referencia correspondiente).
II. Consideraciones teóricas
Aquí describo algunos tópicos matemáticos que sustentan la implementación de los algoritmos y
para ello usaré la siguiente …
1. Notación
D = {d1, d2,..., dn} Es el conjunto de denominaciones ordenadas ascendentemente:
d1 < d2 ... < dn.
MCD(D) Es el máximo común divisor del conjunto D
mcd(a, b) Es el máximo común divisor de las cantidades a y b.
X | Y Significa que X divide a Y
Las mezclas las designaremos en la forma:
[Ni - di, Nj - dj , ..., Nm - dm], por ejemplo: [1 - $50, 2 - $200, 5 - $500]
Para las operaciones aritméticas se usara la sintaxis del lenguaje "C".
2. Planteamiento matemático
Sea M el monto a mezclar y D el conjunto de denominaciones {d1, d2,..., dn}, donde el monto y las
denominaciones son enteros mayores que cero; obtener una mezcla equivale a resolver la
ecuación:
(1) M = d1 * X1 + d2 * X2 ... + dn * Xn
Con la restricción de que cada Xi debe ser mayor o igual a cero.
La ecuación (1) se conoce como "diofántica lineal" y es bien sabido que solo tiene solución cuando
el máximo común divisor del conjunto D es un divisor de M.
Erróneamente algunos creen que para M sea miscible en D es necesario que M sea
divisible por alguna denominación de D y aun cuando esta condición es suficiente en
realidad no es necesaria como se demuestra en el ejemplo siguiente:
Si D = {20, 50} y M = 70; evidentemente ni 20 ni 50 dividen a 70 y sin embargo 70 = 50 + 20
es la mezcla buscada.
Por otro lado, como buscamos mezclas con enteros positivos, no basta que el máximo común
divisor de D divida M; el caso M = 30 así lo demuestra pues obviamente 10 lo divide pero no existe
mezcla posible con enteros positivos.
Un hecho relevante de las ecuaciones diofánticas lineales es la llamada identidad de Bézout, que
dice:
Si a y b son números enteros (no ambos cero) y d = mcd(a, b) entonces existen números
enteros (no necesariamente positivos) X0 e Y0 tales que:
(2) d = a * X0 + b * Y0
Una solución de (2) se obtiene mediante el "algoritmo extendido de Euclides" al cual los
remitimos. Sin embargo también se puede resolver por tanteos (fuerza bruta) y eventualmente,
por tratarse de un pequeño conjunto de números pequeños, puede resultar una solución "más
barata".
En nuestro ejemplo:
10 = 20 * x + 50 * y
Con x = 1, tenemos
10 = 20 + 50 * y  -10 = 50 * y  y = - 10 / 50
Que evidentemente no es un entero, pero con x = 3, ahora tenemos:
10 = 60 + 50 * y  -50 = 50 * y  y = -1,
La cual si es una solución con números enteros.
La solución de la ecuación (2) no es única, de hecho partiendo de una fácilmente se construye una
infinidad de ellas, basta con definirlas como:
x = X0 + c * b / d
y = Y0 - c * a / d
He aquí la demostración:
d = a * (X0 + c * b / d) + b * (Y0 - c * a / d)
= a * X0 + a *c * b / d + b * Y0 - b * c * a / d
= a * X0 + b * Y0
Otra propiedad del máximo común divisor, que emplearemos para obtener soluciones con enteros
positivos para la ecuación de mezcla, es que a través de él podemos fácilmente convertir piezas de
una denominación en el equivalente de otra:
Si a, b son enteros positivos y d = mcd(a, b) entonces tanto p = a / d como q = b / d son
enteros positivos. Despejando d de estas dos últimas expresiones:
d = a / p = b / q
y por tanto:
(3) q * a = p * b
Es decir q-cosas "a" equivalen a p-cosas "b".
En nuestro primer ejemplo con D = {20, 50} donde mcd(20, 50) = 10, tenemos que p = 2 y q = 5,
5 * 20 = 2 * 50
5 billetes de 20 equivalen a 2 billetes de 50 y esto aunque parezca trivial constituye una
herramienta importante para la programación; simplemente trate de obtenerlo, por programa, sin
calcular el mcd.
Regresando al problema de la mezcla, el caso particular de dos denominaciones es el resolver la
ecuación:
(4) M = d1 * X1 + d2 * X2
Para ello primero dividimos M entre d = mcd(d1, d2) y como, por hipótesis, M es divisible por esta
cantidad entonces: q = M / d, como ya dijimos, es un número entero. Multiplicando por q la
ecuación (2), tenemos:
q * d = q *(d1 * X0 + d2 * Y0) = d1 * q * X0 + d2 * q * Y0
Pero q * d = M, es decir que una solución es: X1 = q * X0 e Y1 = q * Y0, sin embargo no
necesariamente es con enteros positivos.
Siguiendo nuestro ejemplo:
10 = 20 * X0 + 50 * Y0
Si hacemos X0 = -2, tenemos que Y0 = 1 satisface la ecuación y esta queda como:
10 = - 2 * 20 + 1 * 50
Ahora si queremos mezclar la cantidad de 70, basta multiplicar esta última por 7 y tenemos:
70 = 7 * (- 2 * 20 + 50)
= -14 * 20 + 7 * 50
Esto -14(??) billetes de 20 y 7 billetes de 50.
Para anular el número negativo de la denominación 20 procedemos a la conversión que como ya
sabemos 2 billetes de 50 equivalen a 5 de 20 y en consecuencia 6 billetes de 50 equivalen a 15 de
20.
Así que:
70 = - 14 * 20 + 6 * 50 + 50
= - 14 * 20 + 15 * 20 + 50
= 20 + 50
Y esta es la mezcla buscada.
Programáticamente el dato "6" se obtiene utilizando la función "ceil" de C y C++ (ceiling en VB6,
Math.ceiling en C# y VB.net, etc.) esta función calcula el mínimo entero mayor o igual al
argumento, esta función la invocamos en la formula siguiente:
ceil(14 / 5) * 2
Donde 14 es el número de billetes de 20 que queremos convertir, 5 y 2 son los factores de
conversión de la ecuación obtenidos de la expresión (3).
Por otro lado al pretender mezclar la cantidad 30 tenemos:
30 = 3 * (- 2 * 20 + 50)
= -6 * 20 + 3 * 50
Pero como
ceil(6 / 5) * 2 = 2 * 2 = 4
Es decir, que para anular los 6 billetes negativos de 20 se requieren 4 billetes de 50 pero la mezcla
solo tiene 3 de tales billetes lo cual implica que no es posible la mezcla con cantidades positivas.
Finalmente aun cuando se puede resolver la ecuación general (1) por procedimientos de la
matemática discreta que reducen el caso general de la solución de las n incógnitas a la de 2,
resultan ser demasiado complejos para nuestro objetivo que es el encontrar solo tres soluciones:
Mínimo de piezas, Máximo de denominaciones y Balanceado por existencias.
III. Los algoritmos
En todos los casos los casos se debe de cumplir que el monto a mezclar sea divisible entre
el mcd del conjunto de denominaciones y, obviamente, deberá de ser mayor o igual a la
mínima denominación.
1. Mezcla por mínimo de piezas:
Cuando la denominación más baja (d1) es también el máximo común divisor del conjunto de
denominaciones el algoritmo es relativamente sencillo: basta con dividir la cantidad M entre la
denominación más alta y al residuo dividirlo entre la siguiente denominación y así sucesivamente
hasta que el residuo sea cero lo cual siempre ocurrirá por la condición d1 = MCD(D).
Ejemplo:
Sea D = {50, 100, 200, 500} y M = 1750
Q1 = 1750 / 500 = 3, R1 = 250
Q2 = 250 / 200 = 1, R2 = 50
Q3 = 50 / 100 = 0, R3 = 50
Q4 = 50 / 50 = 1, R4 = 0
Y como R4 = 0 la mezcla es exitosa: [1 - $50, 1 - $200, 3 - $500]
En caso de que d1 ≠ MCD(D), por ejemplo D = {20, 50, 100} y M = 1010, aplicamos el siguiente
método:
 Dividimos M / d1:
Q1 = 1010 / 20 = 50, R1 = 10
 Buscamos una denominación que al dividirla entre d1 su cociente sea menor o igual a Q1 y
su residuo igual a R1. Si tal denominación no existe, entonces M no es miscible en el
conjunto D. En el ejemplo la denominación buscada es 50:
50 / 20 = 2; 50 % 20 = 10
 Obtenemos: P1 = dk / d1
Donde dk es la denominación encontrada. Evidentemente, dado que así lo elegimos, la
división anterior deja un residuo igual a R1.
P1 = 50 / 20 = 2, R1' = 10
 Calculamos: Q1’ = Q1 - P1 y obviamente, también por elección, Q1' >= 0.
Q1' = 50 - 2 = 48
 Trivialmente obtenemos la mezcla: [Q1' - d1, 1 - dk]
En el ejemplo: [48 - $20, 1 - $50]
Sin embargo aún falta un paso adicional, puesto que la mezcla se compone de denominaciones
bajas habrá que convertirlas en altas para que sea la mezcla con el mínimo número de piezas. En el
ejemplo convertiremos 45 billetes de 20 en 9 billetes de 100:
48 * 20 = 960 = 9 * 100 + 60
La mezcla definitiva es: [3 - $20, 1 - $50, 9 - $100].
2. Mezcla por máximo número de denominaciones.
La idea de esta implementación es que partiendo de las denominaciones reales se genera una
tabla de denominaciones virtuales que son la suma de cada denominación real con cero o un
billete de las otras denominaciones, un ejemplo nos permitirá aclarar conceptos:
Sea DR = {50, 100, 200, 500} el conjunto de denominaciones reales entonces
DV = {50, 100, 150 = 100 + 50, 200, 250 = 200 + 50, 300 = 200 + 100, 350 = 200 + 100 + 50,
500, 550 = 500 + 50, 600 = 500 + 100, 650 = 500 + 100 + 50, 700 = 500 + 200,
750 = 500 + 200 + 50, 800 = 500 + 200 + 100, 850 = 500 + 200 + 100 + 50}
Es la tabla de denominaciones virtuales, en este caso el tamaño de la tabla es 15; en
general si tenemos un conjunto de n denominaciones reales la tabla virtual será de
tamaño 2n
- 1.
Una vez obtenida la tabla virtual se clasifica de acuerdo al "peso" (número de denominaciones
reales que intervienen en la denominación virtual) y con esta tabla se mezcla el monto utilizando
el primer método del algoritmo mínimo de piezas, es decir: dividir la cantidad M entre la
denominación virtual "más alta" y al residuo dividirlo entre la siguiente denominación y así
sucesivamente hasta que el residuo sea cero o hasta que se acaben las denominaciones. En este
contexto la denominación "más alta" es la de mayor peso y valor, es decir la última de acuerdo a la
clasificación. En el ejemplo la clasificación seria:
Peso 1:
50,
100,
200,
500,
Peso 2:
150 = 100 + 50,
250 = 200 + 50,
300 = 200 + 100,
550 = 500 + 50,
600 = 500 + 100,
700 = 500 + 200,
Peso 3:
350 = 200 + 100 + 50,
650 = 500 + 100 + 50,
750 = 500 + 200 + 50,
800 = 500 + 200 + 100,
Peso 4:
850 = 500 + 200 + 100 + 50
Ahora si queremos mezclar M = 3050, calculamos:
Q1 = 3050 / 850 = 3, R1 = 500
Q2 = 500 / 350 = 1, R2 = 150
Q3 = 150 / 150 = 1, R3 = 0
Y la mezcla virtual será:
3 billetes virtuales de 850 = 3 * (500, 200, 100, 50) reales
1 billete virtual de 350 = 1 * ( 200, 100, 50) "
1 billete virtual de 150 = 1 * ( 100, 50) "
Y en consecuencia la mezcla real será: [5 - $50, 5 - $100, 4 - $200, 3 - $500].
En caso de no llegar a un residuo cero en la última división se busca una denominación de la
mezcla que sumada al residuo se pueda mezclar con el algoritmo mínimo de piezas pero sacando
dicha denominación del conjunto. Si tal denominación se encuentra, a la mezcla original se le saca
un billete de tal denominación y se le suma la mezcla que se obtuvo con el residuo y dicha
denominación.
3. Mezcla balanceada por suministros.
Con la implementación del algoritmo anterior, este resulta ridículamente simple:
1. Aplíquese el algoritmo de máximo de denominaciones
2. Convierta los billetes que menos existencias tengan en billetes con más existencias.
IV. Resultados muestra
06/01/15 07:44:40 Inicia despacho: Algoritmo: Mínimo de piezas, Modelo: Aleatorio, Monto
máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros = 5,000
06/01/15 07:44:40 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00
- 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD =
50.
06/01/15 07:44:42 0550: Se modificaron las denominaciones: [$50.00 - 2216, $100.00 - 2275,
$200.00 - 4535]
06/01/15 07:44:43 0932: Se modificaron las denominaciones: [$50.00 - 2024, $100.00 - 2065]
06/01/15 07:44:44 1026: Se modificaron las denominaciones: [$50.00 - 1949]
06/01/15 07:44:44 Total despachos = 1,101 (164 con solo billetes de $50.00), monto total =
$2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500,
$200.00 - 5000, $500.00 - 2500.
06/01/15 07:44:57 Inicia despacho: Algoritmo: Máximo de denominaciones, Modelo: Aleatorio,
Monto máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros =
5,000
06/01/15 07:44:57 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00
- 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD =
50.
06/01/15 07:44:59 0675: Se modificaron las denominaciones: [$100.00 - 164, $200.00 - 2921,
$500.00 - 681]
06/01/15 07:44:59 0726: Se modificaron las denominaciones: [$200.00 - 2762, $500.00 - 548]
06/01/15 07:45:00 0903: Se modificaron las denominaciones: [$200.00 - 1889]
06/01/15 07:45:00 Total despachos = 1,056 (157 con solo billetes de $200.00), monto total =
$2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500,
$200.00 - 5000, $500.00 - 2500.
06/01/15 07:45:16 Inicia despacho: Algoritmo: Balanceada por existencias, Modelo: Aleatorio,
Monto máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros =
5,000
06/01/15 07:45:16 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00
- 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD =
50.
06/01/15 07:45:19 1062: Se modificaron las denominaciones: [$200.00 - 2, $500.00 - 4]
06/01/15 07:45:19 1063: Se modificaron las denominaciones: [$500.00 - 3]
06/01/15 07:45:19 Total despachos = 1,064 (1 con solo billetes de $500.00), monto total =
$2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500,
$200.00 - 5000, $500.00 - 2500.
Los resultados anteriores corresponden una corrida del emulador donde la ejecución de cada
algoritmo se realizó bajo los mismos parámetros. Como era de esperar, en el algoritmo “Mínimo
de piezas”, se rezagan los billetes de baja denominación, mientras que en el de “Máximo de
denominaciones” los que se quedan son los que inician con el doble de existencias y en el
“Balanceado por existencias” virtualmente se agotan al mismo tiempo.
Agustín Ortiz Valdiviezo.
Enero 2012.

Más contenido relacionado

Similar a Acerca de los algoritmos de mezcla en cajeros automáticos

Investigacion
InvestigacionInvestigacion
Investigacion
Jeanc24
 
sistema numérico binario y todos sus componentes.
sistema numérico binario y todos sus componentes.sistema numérico binario y todos sus componentes.
sistema numérico binario y todos sus componentes.
garcialopezfelixr
 
Ecuaciones de segundo_grado
Ecuaciones de segundo_gradoEcuaciones de segundo_grado
Ecuaciones de segundo_grado
fernando10rocha
 
Matlab
MatlabMatlab
Matlab
Juan Morales
 
Matlab
MatlabMatlab
Matlab
Juan Morales
 
Matlab
MatlabMatlab
Matlab
Juan Morales
 
Matlab
MatlabMatlab
Matlab
MatlabMatlab
Matlab
Juan Morales
 
Propiedades de las operaciones y sus aplicaciones
Propiedades de las operaciones y sus aplicacionesPropiedades de las operaciones y sus aplicaciones
Propiedades de las operaciones y sus aplicaciones
Fedra Vanesa Muñoz Valencia
 
Matlab (1)
Matlab (1)Matlab (1)
Matlab (1)
Carlos chambi
 
Presentacion analisis numerico
Presentacion analisis numericoPresentacion analisis numerico
Presentacion analisis numerico
Luis Alberto Serrano Loyo
 
Analisis numerico (1)
Analisis numerico (1)Analisis numerico (1)
Analisis numerico (1)
jessdayana3
 
dqwrwer
dqwrwerdqwrwer
dqwrwer
guest567878
 
Ecuaciones Cuadraticas
Ecuaciones CuadraticasEcuaciones Cuadraticas
Ecuaciones Cuadraticas
eccutpl
 
El Problema del Agente Viajero_f.pptx
El Problema del Agente Viajero_f.pptxEl Problema del Agente Viajero_f.pptx
El Problema del Agente Viajero_f.pptx
CarlosTarquiGuillen
 
cap10.pdf
cap10.pdfcap10.pdf
cap10.pdf
Gonzalo Fano
 
Matlab principios
Matlab principiosMatlab principios
Matlab principios
Gerardo Arce
 
T9
T9T9
Matemática general - 2da magistral 2013
Matemática general - 2da magistral 2013Matemática general - 2da magistral 2013
Matemática general - 2da magistral 2013
jdsolor
 
Modulo tema-3-metodos-de-resolucion
Modulo tema-3-metodos-de-resolucionModulo tema-3-metodos-de-resolucion
Modulo tema-3-metodos-de-resolucion
Enrike1601
 

Similar a Acerca de los algoritmos de mezcla en cajeros automáticos (20)

Investigacion
InvestigacionInvestigacion
Investigacion
 
sistema numérico binario y todos sus componentes.
sistema numérico binario y todos sus componentes.sistema numérico binario y todos sus componentes.
sistema numérico binario y todos sus componentes.
 
Ecuaciones de segundo_grado
Ecuaciones de segundo_gradoEcuaciones de segundo_grado
Ecuaciones de segundo_grado
 
Matlab
MatlabMatlab
Matlab
 
Matlab
MatlabMatlab
Matlab
 
Matlab
MatlabMatlab
Matlab
 
Matlab
MatlabMatlab
Matlab
 
Matlab
MatlabMatlab
Matlab
 
Propiedades de las operaciones y sus aplicaciones
Propiedades de las operaciones y sus aplicacionesPropiedades de las operaciones y sus aplicaciones
Propiedades de las operaciones y sus aplicaciones
 
Matlab (1)
Matlab (1)Matlab (1)
Matlab (1)
 
Presentacion analisis numerico
Presentacion analisis numericoPresentacion analisis numerico
Presentacion analisis numerico
 
Analisis numerico (1)
Analisis numerico (1)Analisis numerico (1)
Analisis numerico (1)
 
dqwrwer
dqwrwerdqwrwer
dqwrwer
 
Ecuaciones Cuadraticas
Ecuaciones CuadraticasEcuaciones Cuadraticas
Ecuaciones Cuadraticas
 
El Problema del Agente Viajero_f.pptx
El Problema del Agente Viajero_f.pptxEl Problema del Agente Viajero_f.pptx
El Problema del Agente Viajero_f.pptx
 
cap10.pdf
cap10.pdfcap10.pdf
cap10.pdf
 
Matlab principios
Matlab principiosMatlab principios
Matlab principios
 
T9
T9T9
T9
 
Matemática general - 2da magistral 2013
Matemática general - 2da magistral 2013Matemática general - 2da magistral 2013
Matemática general - 2da magistral 2013
 
Modulo tema-3-metodos-de-resolucion
Modulo tema-3-metodos-de-resolucionModulo tema-3-metodos-de-resolucion
Modulo tema-3-metodos-de-resolucion
 

Acerca de los algoritmos de mezcla en cajeros automáticos

  • 1. Acerca de los algoritmos de mezcla en cajeros automáticos. I. Introducción: Como parte del desarrollo de los aplicativos para los cajeros automáticos de Telmex y Banamex tuve la necesidad de implementar diversos algoritmos para el despacho y entrega de efectivo tanto en billetes como en monedas. El primero de ellos fue para una máquina receptora de pagos de Telmex la cual solo entregaba efectivo en monedas; la solución requería el dar el mínimo número de monedas y aunado a que una de las denominaciones era de $1 redundo en un fácil y sencillo desarrollo. Por razones que no vienen al caso mencionar, tuve la necesidad de implementar este algoritmo en los cajeros Diebold instalados en Banamex. La primera complicación, respecto a lo desarrollado para Telmex, consistió en que aquí no se contaba con una denominación unitaria con que cubrir el potencial remanente entre lo requerido y lo proporcionado por la mezcla con las otras denominaciones. Adicionalmente, también en Banamex, se requirió del desarrollo de otro algoritmo cuya mezcla fuese una cantidad más o menos igual de billetes de cada una de las denominaciones; una virtud de tal algoritmo consiste en que, tratándose de billetes, esta mezcla es preferida por el cliente; otra es que si la dotación inicial consiste del mismo número de billetes para cada una de las denominaciones, en principio (y solo en principio), los casetes se vaciaran más o menos al mismo tiempo; sin embargo la realidad es un poco más compleja, por ejemplo, esto no ocurrirá con una denominación alta en una zona donde el monto promedio de retiros sea menor al valor de esta (la determinación de denominaciones por zona no es materia de los algoritmos de mezcla, pero un buen emulador que implemente los distintos algoritmos ayuda en tal determinación). Haciendo abstracción de esta última problemática, es necesario reiterar que el vaciado simultáneo de los casetes solo opera cuando el número de billetes de cada denominación es el mismo. Un tercer algoritmo que desarrollé para Banamex fue el "Balanceado por existencias", en este se intenta despachar más billetes de la denominación que más billetes tenga en el momento del despacho, pero respetando, en la medida de lo posible, el máximo de denominaciones. A diferencia de los algoritmos anteriores, cuya mezcla siempre es la misma para un monto determinado, en esta la mezcla varia de despacho en despacho. La motivación esencial del desarrollo de este algoritmo fue que un determinado modelo de los cajeros fabricados por Diebold cuentan con 5 casetes para el para el despacho de billetes, pero lo mayoría de los clientes utilizan solo 3 o 4 denominaciones para dotar sus cajeros y aunque las denominaciones legales en México son 6, no es esperable que en un cajero en particular se utilicen más de 4, las razones son:
  • 2. 1. La denominación $1,000 es de muy baja circulación. 2. La denominación de $20 puede ser adecuada para zonas populares, pero en estas mismas es probable que no lo sea la de $500 3. En zonas medias y altas no resulta adecuada la denominación de $20 Ahora bien, para acomodar 4 denominaciones en 5 casetes es necesario que dos de ellos carguen la misma denominación y si a cada casete se le dota de un mismo número de billetes es obvio que tal denominación tendrá el doble de piezas que las otras. Aplicar el algoritmo de "máximo de denominaciones" en estas condiciones implica que al agotarse las denominaciones con un solo casete, de la denominación repetida quedará un casete lleno o dos medio vacíos si se utiliza la técnica de despacho alternado. Cabe aclarar que este algoritmo no solo se aplica a cajeros con 5 casetes, de hecho en los bancos es práctica común el cargar solo 3 denominaciones en 4 o 5 casetes e incluso en cajeros con casete por denominación el despacho se mejora al minimizar las diferencias que surgen en el algoritmo de "Máximo de denominaciones" y con ello el vaciado simultáneo es más preciso. Actualmente estos algoritmos los tengo implementados en un componente ActiveX desarrollado en Visual Studio 2010 en un proyecto "MFC ActiveX Control" de Visual C++. También los tengo implementado en un componente .NET con C#. También he desarrollado un programa de prueba, en VB.NET, donde se puede utilizar cualquiera de los componentes anteriores (solo hay que sustituir la referencia correspondiente).
  • 3. II. Consideraciones teóricas Aquí describo algunos tópicos matemáticos que sustentan la implementación de los algoritmos y para ello usaré la siguiente … 1. Notación D = {d1, d2,..., dn} Es el conjunto de denominaciones ordenadas ascendentemente: d1 < d2 ... < dn. MCD(D) Es el máximo común divisor del conjunto D mcd(a, b) Es el máximo común divisor de las cantidades a y b. X | Y Significa que X divide a Y Las mezclas las designaremos en la forma: [Ni - di, Nj - dj , ..., Nm - dm], por ejemplo: [1 - $50, 2 - $200, 5 - $500] Para las operaciones aritméticas se usara la sintaxis del lenguaje "C". 2. Planteamiento matemático Sea M el monto a mezclar y D el conjunto de denominaciones {d1, d2,..., dn}, donde el monto y las denominaciones son enteros mayores que cero; obtener una mezcla equivale a resolver la ecuación: (1) M = d1 * X1 + d2 * X2 ... + dn * Xn Con la restricción de que cada Xi debe ser mayor o igual a cero. La ecuación (1) se conoce como "diofántica lineal" y es bien sabido que solo tiene solución cuando el máximo común divisor del conjunto D es un divisor de M. Erróneamente algunos creen que para M sea miscible en D es necesario que M sea divisible por alguna denominación de D y aun cuando esta condición es suficiente en realidad no es necesaria como se demuestra en el ejemplo siguiente: Si D = {20, 50} y M = 70; evidentemente ni 20 ni 50 dividen a 70 y sin embargo 70 = 50 + 20 es la mezcla buscada. Por otro lado, como buscamos mezclas con enteros positivos, no basta que el máximo común divisor de D divida M; el caso M = 30 así lo demuestra pues obviamente 10 lo divide pero no existe mezcla posible con enteros positivos.
  • 4. Un hecho relevante de las ecuaciones diofánticas lineales es la llamada identidad de Bézout, que dice: Si a y b son números enteros (no ambos cero) y d = mcd(a, b) entonces existen números enteros (no necesariamente positivos) X0 e Y0 tales que: (2) d = a * X0 + b * Y0 Una solución de (2) se obtiene mediante el "algoritmo extendido de Euclides" al cual los remitimos. Sin embargo también se puede resolver por tanteos (fuerza bruta) y eventualmente, por tratarse de un pequeño conjunto de números pequeños, puede resultar una solución "más barata". En nuestro ejemplo: 10 = 20 * x + 50 * y Con x = 1, tenemos 10 = 20 + 50 * y  -10 = 50 * y  y = - 10 / 50 Que evidentemente no es un entero, pero con x = 3, ahora tenemos: 10 = 60 + 50 * y  -50 = 50 * y  y = -1, La cual si es una solución con números enteros. La solución de la ecuación (2) no es única, de hecho partiendo de una fácilmente se construye una infinidad de ellas, basta con definirlas como: x = X0 + c * b / d y = Y0 - c * a / d He aquí la demostración: d = a * (X0 + c * b / d) + b * (Y0 - c * a / d) = a * X0 + a *c * b / d + b * Y0 - b * c * a / d = a * X0 + b * Y0 Otra propiedad del máximo común divisor, que emplearemos para obtener soluciones con enteros positivos para la ecuación de mezcla, es que a través de él podemos fácilmente convertir piezas de una denominación en el equivalente de otra: Si a, b son enteros positivos y d = mcd(a, b) entonces tanto p = a / d como q = b / d son enteros positivos. Despejando d de estas dos últimas expresiones: d = a / p = b / q
  • 5. y por tanto: (3) q * a = p * b Es decir q-cosas "a" equivalen a p-cosas "b". En nuestro primer ejemplo con D = {20, 50} donde mcd(20, 50) = 10, tenemos que p = 2 y q = 5, 5 * 20 = 2 * 50 5 billetes de 20 equivalen a 2 billetes de 50 y esto aunque parezca trivial constituye una herramienta importante para la programación; simplemente trate de obtenerlo, por programa, sin calcular el mcd. Regresando al problema de la mezcla, el caso particular de dos denominaciones es el resolver la ecuación: (4) M = d1 * X1 + d2 * X2 Para ello primero dividimos M entre d = mcd(d1, d2) y como, por hipótesis, M es divisible por esta cantidad entonces: q = M / d, como ya dijimos, es un número entero. Multiplicando por q la ecuación (2), tenemos: q * d = q *(d1 * X0 + d2 * Y0) = d1 * q * X0 + d2 * q * Y0 Pero q * d = M, es decir que una solución es: X1 = q * X0 e Y1 = q * Y0, sin embargo no necesariamente es con enteros positivos. Siguiendo nuestro ejemplo: 10 = 20 * X0 + 50 * Y0 Si hacemos X0 = -2, tenemos que Y0 = 1 satisface la ecuación y esta queda como: 10 = - 2 * 20 + 1 * 50 Ahora si queremos mezclar la cantidad de 70, basta multiplicar esta última por 7 y tenemos: 70 = 7 * (- 2 * 20 + 50) = -14 * 20 + 7 * 50 Esto -14(??) billetes de 20 y 7 billetes de 50. Para anular el número negativo de la denominación 20 procedemos a la conversión que como ya sabemos 2 billetes de 50 equivalen a 5 de 20 y en consecuencia 6 billetes de 50 equivalen a 15 de 20.
  • 6. Así que: 70 = - 14 * 20 + 6 * 50 + 50 = - 14 * 20 + 15 * 20 + 50 = 20 + 50 Y esta es la mezcla buscada. Programáticamente el dato "6" se obtiene utilizando la función "ceil" de C y C++ (ceiling en VB6, Math.ceiling en C# y VB.net, etc.) esta función calcula el mínimo entero mayor o igual al argumento, esta función la invocamos en la formula siguiente: ceil(14 / 5) * 2 Donde 14 es el número de billetes de 20 que queremos convertir, 5 y 2 son los factores de conversión de la ecuación obtenidos de la expresión (3). Por otro lado al pretender mezclar la cantidad 30 tenemos: 30 = 3 * (- 2 * 20 + 50) = -6 * 20 + 3 * 50 Pero como ceil(6 / 5) * 2 = 2 * 2 = 4 Es decir, que para anular los 6 billetes negativos de 20 se requieren 4 billetes de 50 pero la mezcla solo tiene 3 de tales billetes lo cual implica que no es posible la mezcla con cantidades positivas. Finalmente aun cuando se puede resolver la ecuación general (1) por procedimientos de la matemática discreta que reducen el caso general de la solución de las n incógnitas a la de 2, resultan ser demasiado complejos para nuestro objetivo que es el encontrar solo tres soluciones: Mínimo de piezas, Máximo de denominaciones y Balanceado por existencias.
  • 7. III. Los algoritmos En todos los casos los casos se debe de cumplir que el monto a mezclar sea divisible entre el mcd del conjunto de denominaciones y, obviamente, deberá de ser mayor o igual a la mínima denominación. 1. Mezcla por mínimo de piezas: Cuando la denominación más baja (d1) es también el máximo común divisor del conjunto de denominaciones el algoritmo es relativamente sencillo: basta con dividir la cantidad M entre la denominación más alta y al residuo dividirlo entre la siguiente denominación y así sucesivamente hasta que el residuo sea cero lo cual siempre ocurrirá por la condición d1 = MCD(D). Ejemplo: Sea D = {50, 100, 200, 500} y M = 1750 Q1 = 1750 / 500 = 3, R1 = 250 Q2 = 250 / 200 = 1, R2 = 50 Q3 = 50 / 100 = 0, R3 = 50 Q4 = 50 / 50 = 1, R4 = 0 Y como R4 = 0 la mezcla es exitosa: [1 - $50, 1 - $200, 3 - $500] En caso de que d1 ≠ MCD(D), por ejemplo D = {20, 50, 100} y M = 1010, aplicamos el siguiente método:  Dividimos M / d1: Q1 = 1010 / 20 = 50, R1 = 10  Buscamos una denominación que al dividirla entre d1 su cociente sea menor o igual a Q1 y su residuo igual a R1. Si tal denominación no existe, entonces M no es miscible en el conjunto D. En el ejemplo la denominación buscada es 50: 50 / 20 = 2; 50 % 20 = 10  Obtenemos: P1 = dk / d1 Donde dk es la denominación encontrada. Evidentemente, dado que así lo elegimos, la división anterior deja un residuo igual a R1. P1 = 50 / 20 = 2, R1' = 10  Calculamos: Q1’ = Q1 - P1 y obviamente, también por elección, Q1' >= 0. Q1' = 50 - 2 = 48
  • 8.  Trivialmente obtenemos la mezcla: [Q1' - d1, 1 - dk] En el ejemplo: [48 - $20, 1 - $50] Sin embargo aún falta un paso adicional, puesto que la mezcla se compone de denominaciones bajas habrá que convertirlas en altas para que sea la mezcla con el mínimo número de piezas. En el ejemplo convertiremos 45 billetes de 20 en 9 billetes de 100: 48 * 20 = 960 = 9 * 100 + 60 La mezcla definitiva es: [3 - $20, 1 - $50, 9 - $100]. 2. Mezcla por máximo número de denominaciones. La idea de esta implementación es que partiendo de las denominaciones reales se genera una tabla de denominaciones virtuales que son la suma de cada denominación real con cero o un billete de las otras denominaciones, un ejemplo nos permitirá aclarar conceptos: Sea DR = {50, 100, 200, 500} el conjunto de denominaciones reales entonces DV = {50, 100, 150 = 100 + 50, 200, 250 = 200 + 50, 300 = 200 + 100, 350 = 200 + 100 + 50, 500, 550 = 500 + 50, 600 = 500 + 100, 650 = 500 + 100 + 50, 700 = 500 + 200, 750 = 500 + 200 + 50, 800 = 500 + 200 + 100, 850 = 500 + 200 + 100 + 50} Es la tabla de denominaciones virtuales, en este caso el tamaño de la tabla es 15; en general si tenemos un conjunto de n denominaciones reales la tabla virtual será de tamaño 2n - 1. Una vez obtenida la tabla virtual se clasifica de acuerdo al "peso" (número de denominaciones reales que intervienen en la denominación virtual) y con esta tabla se mezcla el monto utilizando el primer método del algoritmo mínimo de piezas, es decir: dividir la cantidad M entre la denominación virtual "más alta" y al residuo dividirlo entre la siguiente denominación y así sucesivamente hasta que el residuo sea cero o hasta que se acaben las denominaciones. En este contexto la denominación "más alta" es la de mayor peso y valor, es decir la última de acuerdo a la clasificación. En el ejemplo la clasificación seria: Peso 1: 50, 100, 200, 500,
  • 9. Peso 2: 150 = 100 + 50, 250 = 200 + 50, 300 = 200 + 100, 550 = 500 + 50, 600 = 500 + 100, 700 = 500 + 200, Peso 3: 350 = 200 + 100 + 50, 650 = 500 + 100 + 50, 750 = 500 + 200 + 50, 800 = 500 + 200 + 100, Peso 4: 850 = 500 + 200 + 100 + 50 Ahora si queremos mezclar M = 3050, calculamos: Q1 = 3050 / 850 = 3, R1 = 500 Q2 = 500 / 350 = 1, R2 = 150 Q3 = 150 / 150 = 1, R3 = 0 Y la mezcla virtual será: 3 billetes virtuales de 850 = 3 * (500, 200, 100, 50) reales 1 billete virtual de 350 = 1 * ( 200, 100, 50) " 1 billete virtual de 150 = 1 * ( 100, 50) " Y en consecuencia la mezcla real será: [5 - $50, 5 - $100, 4 - $200, 3 - $500]. En caso de no llegar a un residuo cero en la última división se busca una denominación de la mezcla que sumada al residuo se pueda mezclar con el algoritmo mínimo de piezas pero sacando dicha denominación del conjunto. Si tal denominación se encuentra, a la mezcla original se le saca un billete de tal denominación y se le suma la mezcla que se obtuvo con el residuo y dicha denominación. 3. Mezcla balanceada por suministros. Con la implementación del algoritmo anterior, este resulta ridículamente simple: 1. Aplíquese el algoritmo de máximo de denominaciones 2. Convierta los billetes que menos existencias tengan en billetes con más existencias.
  • 10. IV. Resultados muestra 06/01/15 07:44:40 Inicia despacho: Algoritmo: Mínimo de piezas, Modelo: Aleatorio, Monto máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros = 5,000 06/01/15 07:44:40 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD = 50. 06/01/15 07:44:42 0550: Se modificaron las denominaciones: [$50.00 - 2216, $100.00 - 2275, $200.00 - 4535] 06/01/15 07:44:43 0932: Se modificaron las denominaciones: [$50.00 - 2024, $100.00 - 2065] 06/01/15 07:44:44 1026: Se modificaron las denominaciones: [$50.00 - 1949] 06/01/15 07:44:44 Total despachos = 1,101 (164 con solo billetes de $50.00), monto total = $2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500. 06/01/15 07:44:57 Inicia despacho: Algoritmo: Máximo de denominaciones, Modelo: Aleatorio, Monto máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros = 5,000 06/01/15 07:44:57 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD = 50. 06/01/15 07:44:59 0675: Se modificaron las denominaciones: [$100.00 - 164, $200.00 - 2921, $500.00 - 681] 06/01/15 07:44:59 0726: Se modificaron las denominaciones: [$200.00 - 2762, $500.00 - 548] 06/01/15 07:45:00 0903: Se modificaron las denominaciones: [$200.00 - 1889] 06/01/15 07:45:00 Total despachos = 1,056 (157 con solo billetes de $200.00), monto total = $2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500. 06/01/15 07:45:16 Inicia despacho: Algoritmo: Balanceada por existencias, Modelo: Aleatorio, Monto máximo = $5,000.00, Máximo de billetes por retiro = 50, Número máximo de retiros = 5,000 06/01/15 07:45:16 Posición inicial: [$50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500], Denominaciones: 4, Número de billetes: 10,000, Disponible = $2,625,000.00 . MCD = 50. 06/01/15 07:45:19 1062: Se modificaron las denominaciones: [$200.00 - 2, $500.00 - 4] 06/01/15 07:45:19 1063: Se modificaron las denominaciones: [$500.00 - 3] 06/01/15 07:45:19 Total despachos = 1,064 (1 con solo billetes de $500.00), monto total = $2,625,000.00, número de billetes = 12,500. Denominaciones: $50.00 - 2500, $100.00 - 2500, $200.00 - 5000, $500.00 - 2500. Los resultados anteriores corresponden una corrida del emulador donde la ejecución de cada algoritmo se realizó bajo los mismos parámetros. Como era de esperar, en el algoritmo “Mínimo de piezas”, se rezagan los billetes de baja denominación, mientras que en el de “Máximo de denominaciones” los que se quedan son los que inician con el doble de existencias y en el “Balanceado por existencias” virtualmente se agotan al mismo tiempo. Agustín Ortiz Valdiviezo. Enero 2012.