                           CUENCA FLUVIAL Y DEPURADORAS


Consideremos una cuenca fluvial en la que también se vierten ciertos cauces de
aguas residuales y en la que podemos instalar diferentes tipos de depuradoras
en determinadas ubicaciones. Modelaremos la geografía de la cuenca fluvial
mediante una estructura arbórea de exactamente N nodos, identificados con los
valores 1..N. Los nodos pueden tener 0, 1 o 2 entradas y tienen 1 salida.
Podremos instalar depuradoras (o no) en los nodos con 1 o 2 entradas, pero
nunca en los nodos con 0 entradas.

Los nodos con 0 entradas, a los que nos referiremos como "nodos origen",
representan la aparición o generación de un cauce (río o vertido) con un caudal
de c metros cúbicos por segundo y un grado de contaminación g entre 0 y
1000. Los valores c y g son números naturales y dependen de cada nodo, por
ejemplo, los nacimientos de río tendrán un valor g muy bajo o cero, mientras
que los vertidos de aguas residuales tendrán un valor g muy alto. De hecho, en
nuestro modelo no haremos ninguna distinción entre ríos y cauces de aguas
residuales, simplemente tendrán grados de contaminación diferentes.  Los nodos
con 1 entrada representan lugares en tramos de ríos donde podremos instalar una
depuradora para eliminar o reducir la contaminación de sus aguas.  Los nodos
con 2 entradas representan una confluencia de dos ríos, de dos cauces de aguas
residuales o de un río y un cauce de agua residual, y en ellos también podremos
instalar una depuradora.

Todos los nodos tienen una única salida que representa un cauce con un cierto
caudal c y un grado de contaminación g, el cual va a parar a otro nodo de la
cuenca siguiendo la dirección de las aguas, o bien al mar en el caso de un nodo
especial y único al que llamaremos "desembocadura".

Ejemplo de estructura de cuenca: los números indican los identificadores de
nodos y las líneas indican los tramos de cauces entre nodos. El nodo 10 es la
desembocadura y los nodos 1, 2, 4, 6 y 7 son nodos origen.
                         
                      
                           10
                       /        \
                     5            9
                   /   \            \              
                  3    4             8
                 /  \               / \
                1   2              6   7


Propagación de caudal y contaminación. Efecto de las depuradoras.
=================================================================

Trabajaremos con un modelo muy simplificado de una cuenca fluvial real en el
que supondremos que no existen ni filtraciones ni evaporación de agua, por lo
que el caudal de salida de un nodo será la suma de sus caudales de entrada,
excepto en el caso de los nodos origen, y este caudal llegará sin pérdidas al
siguiente nodo (o al mar).

El cálculo del grado de contaminación a la salida de un nodo con 1 o 2 entradas
es algo más complejo y se describe a continuación. Consideremos primero el caso
de un nodo k sin depuradora instalada: si el nodo sólo tiene 1 entrada entonces
el grado de contaminación a la salida es el mismo que a la entrada; si el nodo
tiene dos entradas con caudales c_i y c_j, y grados de contaminación g_i y g_j,
el grado g_k a la salida vendrá dado por la siguiente media ponderada truncada

g_k = int( (c_i * g_i + c_j * g_j) / (c_i + c_j) )

siempre y cuando c_i + c_j > 0, porque obviamente g_k = 0 si c_i + c_j = 0.

Existirán D tipos de depuradora, identificados por valores d entre 1 y D, que
se caracterizan por dos parámetros, cm_d y gm_d. cm_d es el caudal máximo de
agua que puede tratar la depuradora, mientras que gm_d es el grado de
contaminación máximo que puede limpiar la depuradora. Todas las depuradoras que
sean del mismo tipo tendrán los mismos parámetros. Ninguno de los parámetros
cm_d y gm_d pueden ser cero para nigún tipo de depuradoras.

El efecto de una depuradora depende de si está instalada en un nodo con una
entrada o con dos. En cualquiera de los dos casos, si un nodo k contiene una
depuradora de tipo d entonces primero se calcula el caudal c'_k y el grado g'_k
a la entrada de la depuradora y a continuación se aplican sobre ellos los
parámetros de la depuradora, para calcular el caudal c_k el grado g_k
resultantes a la salida de la depuradora.

Si el nodo sólo tiene 1 entrada, c'_k y g'_k serán los valores respectivos de
caudal y grado del único cauce de entrada.

En el caso de nodos con 2 entradas tendremos

c'_k = c_i + c_j

Si c'_k = 0 entonces g'_k = 0, y

si c'_k > 0 entonces g'_k = int( (c_i * g_i + c_j * g_j) / (c_i + c_j) )  

Notad que esta última fórmula es la misma que la usada antes para calcular el
grado de contaminación de salida cuando no hay depuradora.

Ahora calculamos el caudal c_k y el grado g_k a la salida de la depuradora.
Después de pasar por una depuradora de tipo d (es decir, con parámetros cm_d y
gm_d) supondremos nuevamente que el caudal no se ve afectado, es decir c_k =
c'_k, mientras que el grado de contaminación g_k a la salida de la depuradora
(y del nodo) se determina como sigue, dependiendo de cuál de los cuatro casos
posibles se trate:

a) si c'_k <= cm_d  y  g'_k <= gm_d  entonces  g_k = 0 (toda el agua sale limpia)

b) si c'_k <= cm_d  y  g'_k > gm_d  entonces  g_k = g'_k - gm_d 

c) si c'_k > cm_d  y  g'_k <= gm_d  entonces  g_k = int( g'_k * (c'_k - cm_d) / c'_k )

d) si c'_k > cm_d  y  g'_k > gm_d  entonces 
                      g_k = int( (g'_k * (c'_k - cm_d) + (g'_k - gm_d) * cm_d) / c'_k )

La propagación de caudal y contaminación no es simultánea (todos los nodos de
la cuenca al mismo tiempo) sino que en cada nodo con 1 o 2 entradas se espera a
disponer de los valores de las entradas actualizados antes de realizar los
cálculos de los valores de salida del nodo y continuar la propagación.


Eventos e histórico de eventos
==============================

Nuestro objetivo principal es simular el comportamiento de la cuenca ante
diversos eventos. Los eventos pueden estar ocasionados por diferentes motivos
(instalación de depuradoras, vertidos incontrolados, crecidas, lluvia ácida,
lluvias torrenciales, etc.) y estarán identificados en general por un entero de
8 dígitos AAAAMMDD que representa la fecha del evento (sólo podemos tener un
evento por fecha), siendo AAAA el año, MM el mes y DD el día. En cualquier
caso, un evento alterará los datos de un número variable de nodos, que en
general será mucho menor que N, pero mayor que cero. Es decir, un evento
contendrá un cierto número de tuplas <k, d, c, g>, donde k es el identificador
del nodo, d es el identificador de un tipo de depuradora (entre 1 y D)
recientemente instalada en el nodo o d=0 si no modifica la existencia o tipo de
depuradora en el nodo, c es un valor de caudal y g es un valor de grado de
contaminación. Un nodo puede intervenir, como máximo, una vez en cada
evento. Dicho de otro modo, los identificadores de los nodos no pueden
repetirse en las tuplas de un mismo evento.

El significado de c y g varía un poco dependiendo de si el nodo k es origen o
no.  Si es un nodo origen, c y g substituirán a los valores iniciales del nodo.
Si es un nodo no origen, tendremos que añadir un caudal c con grado de
contaminación g al cauce de salida del nodo. Esto representa que el evento se
produce en el tramo entre dicho nodo y el siguiente (si lo hay). Para ello, se
debe sumar c al caudal de salida y recalcular el grado de contaminación de
salida mediante una media ponderada truncada entre g y el grado de salida
calculado según el apartado anterior. Es decir, hay que aplicar la misma
fórmula que hemos visto ya antes en el caso de dos entradas sin depuradora,
sólo que ahora las entradas de la fórmula serían los datos del evento (c y g)
por un lado y los calculados en la salida del nodo (a partir de las entradas)
por otro.

Los incrementos de caudal en los nodos no origen se deben a lluvias, mientras
que los nuevos valores de caudal y grado en los nodos origen pueden deberse a
diferentes factores (lluvias, sequías, modificaciones en la cantidad y calidad
de los vertidos, etc.). Por otro lado, cuando se instala una nueva depuradora
de tipo d (d>0) en un nodo k, tal vez substituyendo una anterior, los valores c
y g de la tupla correspondiente valdrán cero, esto es <k,d,0,0> (supondremos
que no coincidirá la puesta en marcha de la depuradora con un episodio de
lluvias en el cauce de salida del nodo).  Si el evento en el nodo k no consiste
en instalar una depuradora, el valor d de la tupla asociada será cero.

A continuación damos un ejemplo comentado de los datos de entrada de un evento
para la cuenca ejemplo mostrada antes:

20101103    /* identificador y fecha del evento: 3 de noviembre de 2010 */
3           /* número de nodos a los que afecta de manera directa el evento */
2 0 100 70  /* el nodo 2 (que es origen) tiene ahora un caudal 100 y un grado 70 */
5 0 300 20  /* se ha de añadir al cauce de salida del nodo 5 (no origen)
               un caudal de 300 con grado 20 (por lluvias entre el nodo 5 y el 10) */ 
9 1 0 0     /* se ha instalado una depuradora de tipo 1 en el nodo 9 */ 
  
Dado cualquier evento, una vez actualizada la información de los nodos,
procederemos a propagar los valores de caudal y grado de contaminación desde
los nodos orígen hasta la desembocadura. Habrá un evento especial, con
identificador cero (sin fecha), que servirá para inicializar el estado de la
cuenca fluvial. Este evento de inicialización asignará caudales y grados de
contaminación a todos los nodos origen y establecerá qué nodos tienen
depuradora y de qué tipo. El estado resultante del evento de inicialización lo
llamaremos "estado nominal" de la cuenca. Para simplificar, supondremos que el
resto de eventos se aplican siempre sobre este estado nominal, en lugar de ir
acumulándose sucesivamente. Esto implica que cuando se haya acabado de procesar
un evento la cuenca no ha de quedar modificada, excepto en el caso del evento
de inicialización.

Los eventos siguientes al evento de inicialización deberán almacenarse en un
histórico de eventos, sobre el que querremos realizar ciertas consultas que
definiremos más tarde. Ejemplos de tales consultas serían identificar el evento
que causó un mayor o menor grado de contaminación en la desembocadura o listar
los eventos que afectaron directamente a un nodo dado.


Estudio de ubicación de depuradoras
===================================

En ocasiones se desea simular la ubicación de un cierto conjunto de depuradoras
en la cuenca de manera que se pudiera reducir la contaminación del agua al
máximo sin malgastar capacidad de depuración. En estos casos supondremos que
para cada tipo d de depuradora entre 1 y D se dispone de un cierto número p_d
de depuradoras nuevas a instalar de ese tipo (que podría ser cero para una o
más d).  Llamaremos P al número total de estas nuevas depuradoras.

El objetivo ideal sería, dado el estado nominal de la cuenca, conocer qué
asignación de esas P depuradoras a nodos de la cuenca permitiría reducir al
máximo el grado de contaminación en la desembocadura teniendo en cuenta
factores económicos adicionales. A ese respecto, diremos que el precio de una
depuradora de tipo d es igual al producto de su caudal máximo cm_d por su grado
máximo gm_d. Sin embargo, el problema así planteado requiere técnicas
algorítmicas que aún no hemos estudiado y además tiene un coste computacional
excesivamente alto, por lo que diseñaremos un método heurístico para asignar
las depuradoras, que definimos a continuación.

Empezando por la desembocadura, para cualquier nodo con dos entradas
intentaremos primero asignar las depuradoras a la subcuenca izquierda o derecha
que tenga más alto el producto de caudal por grado de contaminación en el
estado nominal (en caso de empate, la izquierda); luego las depuradoras
restantes las intentaremos asignar a la otra subcuenca; y finalmente, si
todavía quedan, veremos si podemos asignar una al nodo. Para un nodo con una
sóla entrada primero intentaremos asignar depuradoras a los nodos de su cuenca
y luego al propio nodo. No podremos asignar depuradoras a nodos que ya
dispongan de una ni, recordad, a nodos origen. En caso contrario asignaremos al
nodo una depuradora de las disponibles que reduzca lo máximo posible el grado
de contaminación a la salida del nodo, y si hay varias de diferentes tipos que
lo hacen en igual medida eligiremos la de precio más barato. Si hubiera empate
también en el precio, eligiríamos la de identificador de tipo menor. Si ninguna
depuradora reduce el grado de contaminación a la salida del nodo, por ejemplo
si dicho grado es cero, no se realiza la asignación. Para ese cálculo tendremos
en cuenta el efecto de las depuradoras asignadas ya por este proceso a nodos
situados en la cuenca que confluye en dicho nodo.


SE PIDE:
=======

Diseñar un programa modular razonablemente eficiente que permita modelar la
cuenca fluvial, simular los eventos descritos y realizar los estudios de
ubicación de depuradoras.  En primer lugar, debe leer el número D de tipos de
depuradora y los parámetros de cada tipo. Luego debe leer el número de nodos N
de la cuenca y su estructura. Seguidamente debe leer el evento de
inicialización y aplicarlo para obtener el estado nominal de la cuenca. Se
deberá escribir solamente el caudal y el grado de contaminación resultante en
la desembocadura.  También se deberá inicializar un histórico de eventos vacío.
Después tendrá que ir procesando las diversas tareas que se le pidan.  Estas
podrán ser las siguientes:

1) Dado un evento, aplicarlo al estado nominal de la cuenca. Se deberá escribir
solamente el caudal y el grado de contaminación resultante en la desembocadura.
También se deberá actualizar el histórico de eventos.  Aplicaremos la política
de que los eventos irán apareciendo en orden cronológico, es decir, cada evento
tendrá una fecha posterior a la de los que se han aplicado anteriormente.

2) Dados D naturales que representan unidades de depuradora disponibles de cada
tipo, aplicar la estrategia de asignación de depuradoras descrita anteriormente
al estado nominal de la cuenca. Se deberá informar del grado de contaminación
resultante en la desembocadura, así como escribir una secuencia de pares de
enteros <k, d>, ordenada de manera ascendente por k, que represente los nodos k
con depuradora y el tipo de depuradora d asignada a cada nodo (incluirá también
las depuradoras asignadas por el evento de inicialización).

3) Dado un entero, que representa una fecha en el mismo formato que la de los
eventos, y un natural n entre 1 y 4, determinar qué evento E ocurrido con
posterioridad a dicha fecha causó como efecto:

- el mayor caudal en la desembocadura (si n=1), o
- el menor caudal en la desembocadura (si n=2), o
- el mayor grado de contaminación en la desembocadura (si n=3), o
- el menor grado de contaminación en la desembocadura (si n=4),
  
y escribir la fecha del evento E, así como el caudal y el grado de
contaminación correspondiente en la desembocadura. En caso de empate, se
escribirá la fecha del evento más antiguo.  Se escribirán tres ceros si no hay
ningún evento posterior a la fecha.

4) Dado un entero k entre 1 y N, escribir en orden cronológico los eventos que
han tenido al nodo k en alguna de sus tuplas. De cada evento listado sólo se ha
de escribir su fecha y los valores <d, c, g> que iban asociados al nodo k en el
evento en la entrada de datos.

La forma de comunicarnos con el programa para que realice dichas tareas será
parecida a la del caso de estudio "Cubeta" que se ve en la sesión 8 de
laboratorio.  Podéis diseñar un esquema provisional que ya refinaréis cuando
conozcáis el juego de pruebas público.

En días sucesivos se completarán los detalles que se hayan podido pasar por
alto en este enunciado y se publicarán las aclaraciones oportunas.

La sintaxis *exacta* de los datos y resultados, acompañada del juego de pruebas
público, se conocerá dos semanas antes del día del examen de la práctica.
Hasta entonces no podréis implementar de forma definitiva las operaciones de
lectura y escritura necesarias para los tipos que utilicéis, aunque sí podréis
especificarlas.

