| |
Boletín de problemas 4
Fecha de entrega: viernes
15 de marzo de 2002
Problema 1: Recursión [15%]
Los lenguajes de muchos pequeños
microprocesadores no tienen instrucciones para multiplicar. Un
algoritmo lógico es multiplicar mediante sumas
repetidas, pero con cierta inteligencia. Por ejemplo,
para multiplicar 17 por 12, primero sume 17 tres veces,
luego añada el resultado y, a continuación,
vuelva a añadir el resultado.
Escriba un algoritmo recursivo
para multiplicar rápidamente un número
entero por otro sin utilizar un operador multiplicador. Puede
escoger arbitrariamente si utilizar el primer o el segundo
número como multiplicador, esto es, el número
que controla cuántas sumas se hacen. (Tal vez
sea una buena heurística utilizar el número
más pequeño como multiplicador. ¿Intuye
el motivo? ¿Debería hacer el intercambio
en el programa llamante o en el método recursivo?;
¿Con qué frecuencia se invocaría
el intercambio?).
Utilice JOptionPanes para recibir
los números de entrada. Recuerde, no puede
utilizar el operador multiplicador (*) en ninguna parte
del programa. Su método debe ser rápido;
no debe limitarse a añadir repetidamente uno
de los números. Debería ser capaz de multiplicar,
digamos, 49.783 por 41.976 utilizando alrededor de 25
sumas.
(En un pequeño microprocesador
real, no dejaría la implementación en
forma recursiva; existen formas mecánicas de
convertir la recursión en iteración y,
en este caso, utilizaría un algoritmo iterativo.
Se basaría en la solución recursiva que
está usted escribiendo).
Fase de prueba: haga la prueba
con cero y con números negativos. No tenga en
cuenta cifras grandes o desbordamiento.
Problema 2: Gestión de
red de telecomunicaciones [85%]
Descripción del problema
Los sistemas de gestión
de redes de telecomunicaciones muestran el status y
el rendimiento de un conjunto de dispositivos de telecomunicación
en un red. Usted va a escribir un subconjunto muy
simplificado de un sistema semejante, pero que recoja
las ideas clave de software en las que se basan estos
sistemas. El sistema mostrará un conjunto
común de indicadores de estado y rendimiento
para cada dispositivo, pero existen también variables
específicas de cada dispositivo que conviene
mostrar y gestionar. Igualmente, el sistema de gestión
de la red ha de ser extensible de modo que, a
medida que se diseñen nuevos dispositivos y se
pongan en marcha la red, su estado y su rendimiento
puedan mostrarse sin tener que rescribir todo el sistema.
A continuación, le presentamos
una relación de los dispositivos y sus características. No
es necesario que estudie su significado; el enunciado
del problema facilita suficiente información
para acabar el programa. El índice de fallos
se ha exagerado en varios órdenes de magnitud
de modo que es probable que vea algunos fallos cuando
ejecute el programa con un número reducido de
dispositivos.
Todos los dispositivos de telecomunicaciones
de su sistema tendrán cuatro campos comunes:
- Cada uno tiene un número
único que es su identificador. Genere el número
de identificación (ID) con una variable static
para tener localizado el siguiente número de
dispositivo.
- Cada uno tiene un atributo de
Estado: Activo o Averiado. Se inician con el estado
Activo pero cambian a Averiado
cuando sucede alguna anomalía, en ese caso, debe
volver manualmente al modo Activo a través
del teclado, tal como se describe más abajo.
En un sistema de gestión de redes real, se
abriría una ventana de consola para el dispositivo
a fin de que se pudiesen ejecutar pruebas, cambiar
parámetros y resolver cualquier problema. En
esta versión simplificada, simplemente se escribe
en el ID del dispositivo y el problema desaparece.
- Cada uno tiene un tipo funcional:
puede ser:
- un circuito de acceso, que
conecta una entidad (MIT, por ejemplo) a la red
de telecomunicaciones de larga distancia
- un conmutador, que conecta
circuitos de acceso a circuitos de larga distancia
- un circuito de larga distancia,
que conecta conmutadores a otros conmutadores
- Cada dispositivo tiene un tipo
específico. En nuestro ejemplo, sólo
tenemos dos tipos: un circuito T1 y un circuito inalámbrico
fijo (FW). Ambos son circuitos de acceso, que
conectan un sitio (empresa o investigación)
a la red de larga distancia. Un sistema real
tendría cientos de dispositivos en cada tipo
funcional (como DSL, circuitos de módem por
marcación, ISDN, etc.)
La figura siguiente representa
un ejemplo de una red de telecomunicaciones que conecta
a laboratorios de 4 universidades, muestra los circuitos
de acceso, los conmutadores y el circuito de larga distancia.
En esta tarea sólo proyectaremos
circuitos de acceso, pero queremos tener una clase TelecomDevice
general que nos permita ampliar nuestro software de
gestión de redes para que pueda gestionar otro
tipo de dispositivos, como conmutadores, circuitos de
larga distancia y similares. La jeraquía
lógica de dispositivos compatibles con nuestro
sistema de gestión de redes se muestra en la
figura siguiente. Las 4 entidades que proyectamos
en esta tarea están en negrita; las otras se
muestran para ilustrar cómo el sistema debe ser
ampliable y compatible con dispositivos variados. (No
se preocupe por la definición de los acrónimos).
Los dos tipos de circuitos de
acceso en esta tarea son:
- Circuito T1. Tiene los siguientes
atributos:
- Número de canales:
24
- Transmisión de señales:
CAS oPRI
- Ancho de banda nominal y real=
1.5Mbps siempre
- Tasa de errores: aleatoria
uniforme entre 0 y 12 bits por 1010 bits
- Estado averiado en tasa de
errores > 10 bits por 1010 bits
- Circuito inalámbrico
fijo (FW). Tiene los siguientes atributos:
- Número de canales:
2
- Tecnología: LMDS, MMDS,
NB (distinta de la transmisión de señales
de T1)
- Ancho de banda nominal: 64kbps
- Ancho de banda real: aleatoria
uniforme entre 0% y 100% de nominal
- Tasa de errores (aleatoria
uniforme entre 0 y 100 bits por 106 bits)
- Estado averiado en tasa de
errores> 50 bits por 106 bits o en
ancho de banda real < 8 kbps (LMDS) o 16kbps(MMDS)
o 32kbps (NB)
Imagine que los campos que comparten
T1 y FW fuesen comunes a todos los circuitos de acceso.
Por ejemplo, tanto T1 como FW tienen canales, tasas
de errores, etc.; puede asumir que todos los errores
tienen canales, tasas de errores, etc. (Sólo
hay una variable específica de T1 y otra de FW
en esta tarea). Es un típico problema de
modelos al diseñar un sistema de gestión
de redes: los dispositivos que gestiona están
fabricados por proveedores diferentes y tienen muchas
características distintas, y usted debe decidir
cuáles son comunes y cuales específicas
de cada aparato, incluidos los cálculos de dispositivos
de este tipo que aún no se han inventado. Si
sus cálculos son buenos, no tendrá que
cambiar el sistema cuando lleguen al mercado.
Es conveniente que disponga las
clases de su programa para que formen una jerarquía.
Llame a la clase básica TelecomDevice y haga
que las otras hereden de ella. Debe decidir si
TelecomDevice es abstracta o concreta. (¿Tiene
sentido tener un objeto TelecomDevice?)
Es posible que las clases que hereden
inmediatamente de TelecomDevice tengan que ser también
abstractas. (De nuevo, ¿tiene sentido tener un
objeto AccessDevice?) Mientras que en este problema
sólo hay una clase AccessDevice, en general,
habrá clases LongHaulDevice, Switch y otras.
Ponga cada campo y método en la clase más
alta de la jerarquía (TelecomDevice, luego AccessDevice,
lueho T1 o FW) que tenga sentido.
Por último, deben definirse
las clases que heredan de AccessDevice, T1 y FW.
Programa
Una vez que haya decidido el enfoque
general, y haya efectuado un primer control en las definiciones
de las clases, métodos y campos, junto con las
relaciones hereditarias, hay ciertos temas que debe
tratar:
Clase TelecomDevice:
- Constructor. Debería
establecer las variables privadas de la clase TelecomDevice,
que serán instanciadas cuando una clase concreta
(T1 o FW) sea instanciada, pero TelecomDevice debe
tener un constructor al que sus clases derivadas puedan
llamar. El constructor puede crear el ID (se requiere
un poquito de lógica) y puede inicializar el
status a Activa si le interesa; un método
computeStatus en clases derivadas reinicializará
el status.
- Necesitará varios métodos
getXXX() y setXXX() para que las clases derivadas
puedan obtener e introducir parámetros en los
campos de la clase TelecomDevice. Todos los campos
de todas las clases de este ejercicio tienen que ser
privados.
- Debe tener un método
abstracto llamado computeStatus, que pedirá
a las clases derivadas que implementen un método
que determine si el status del dispositivo es activo
o inactivo. Lógicamente, no se puede
poner en práctica este método en TelecomDevice.
- Juzgará conveniente tener
un método PrintData() al que puedan llamar
las clases derivadas para mostrar los campos de TelecomDevice.
Clase AccessDevice:
- Tiene que decidir qué
campos van en la clase AccessDevice y cuáles
van en dispositivos específicos T1 o FW, como
se indicó más arriba. Todos los campos
son privados.
- Constructor. Como de costumbre,
pero debe definir el campo de tipo funcional en la
clase TelecomDevice. Invoca el constructor de la superclase.
- Escriba un método computeStatus(),
que pueda ser el método por defecto para dispositivos
de acceso. La mayoría de los estados de los
dispositivos de acceso dependerán sólo
de la tasa y del umbral de error.
- Probablemente necesitará
un método getXXX() para que las clases derivadas
puedan calcular su status.
- De nuevo, juzgará conveniente
tener un método PrintData().
Clases T1 y FW: son bastante cortas.
- Tendrán los campos específicos
de la clase (probablemente uno cada una).
- Constructor. Invoca al constructor
de la superclase, definiendo los argumentos para la
banda ancha, canales, errores, etc., sobre la base
de los parámetros en el enunciado del problema
anterior. Para los argumentos que sean números
aleatorios, utilice Math.random(). Por ejemplo,
si el ancho de banda en un enlace FW es aleatorio
uniforme entre 0 y 64kbps, el argumento de ancho de
banda real es 64.0*Math.random(). Cuando instancie
estos objetos, dibujará los números
aleatorios para caracterizarlos en este instante del
tiempo. Su constructor también define
el tipo y las variables privadas.
- Escriba un método computeStatus()
si es necesario para anular el cálculo por
defecto en la clase AccessDevice
- Será conveniente un método
PrintData().
Por último, necesitará
escribir una clase TelecomTest con un méodo main().
Es conveniente que su método principal:
- Cree un Vector o array
(usted decide) de 20 TelecomDevices.
- Instancie 12 dispositivos T1
y 8 dispositivos FW, y calcule su status. Observe
que sus constructores generarán números
aleatorios para el ancho de banda, y el método
computeStatus() generará aleatoriamente las
tasas de error. Escoja cualquier valor de tecnología
o de señales; los valores pueden ser los mismos
para todos los objetos del mismo tipo (por ejemplo,
todos CAS o todos LMDS). Observe
que, en la vida real, estos serían dispositivos
de verdad, que arrojarían datos sobre tasas
de error y status; su sistema de gestión de
redes obtendría estos datos de los dispositivos
colocados. En este ejercicio, simulamos este
proceso dibujando números aleatorios.
- Si un dispositivo está
inactivo, muestre su ID y status (utilice System.out.println).
- Entonces, en un bucle, muestre
un JOptionPane que solicite al usuario el ID del dispositivo
para arreglar el fallo. Cuando el usuario introduce
el ID, busca en el array o en el Vector
para hallar el dispositivo y definir su status como
Activo. Repita el proceso hasta que se
hayan arreglado todos los dispositivos con fallos. De
nuevo, este caso es mucho más sencillo que
si se tratase de un sistema auténtico, pero
es el mismo enfoque general. Utilice una búsqueda
exhaustiva; más avanzado el curso aprenderemos
métodos de búsqueda más eficaces.
- Una vez realizado, imprima un
mensaje que diga que todos los dispositivos de red
están activos y finalice el programa.
Pero no tema, estimado desarrollador.
La solución a todo esto son apenas 150 líneas
de código, comentarios y espacios en blanco incluidos. Se
trata más que nada de entender como funciona
la herencia y como las clases pueden compartir muchos
métodos y campos. La solución es bastante
corta si primero la planea detenidamente. Comente el
diseño con su compañero. Hable con el
ayudante técnico sobre ella. También
se hablará del ejercicio en los tutoriales.
Un par de notas adicionales:
No es necesario que muestre o que
utilice las unidades (Mbps, Gbps, kbps, etc.) o los
factores de escala (10x) en este tarea. (Piense
que los usuarios del programa tienen experiencia y conocen
las unidades y los factores de escala). Puede modelar
las tasas de error ignorando los términos 10x,
ya que se cancelan. En un sistema de verdad, tendría
que ocuparse de todas estas cosas, pero no es necesario
en esta tarea.
Utilice Math.random() para generar
los números aleatorios uniformes que necesita. Consulte
Javadoc o el libro de texto para más información.
Entrega del trabajo
Requisitos
- Problema 1: solamente por correo
electrónico. No es necesario entregarlo en
papel.
- Problemas 2 y 3: copia en papel
y copia electrónica de TODOS los códigos
fuente (todos los archivos con la extensión
.java).
- Incluya en TODOS los archivos
que presente su nombre, el nombre de usuario, la sección,
el nombre del profesor ayudante, el número
de trabajo y una relación de las personas con
las que haya comentado el boletín de problemas.
- NO entregue copias electrónicas
o en papel de código compilado (archivos .class).
Sanciones
- Por pérdida de copia
en papel: -10% de la puntuación del boletín
de problemas.
- Por pérdida de copia
electrónica: -30% de la puntuación del
boletín de problemas.
- Por entrega fuera del plazo:
-20% de la puntuación del boletín de
problemas si es un día de retraso. Por
más de un día de retraso = NO SE PUNTUARÁ
|