Cátedra Nissan

Anuncio
Cátedra Nissan
-PROTHIUS-
Aplicación de los algoritmos de hormigas para la
resolución del problema de equilibrado de líneas
de montaje SALBP-E y aplicación a un caso real –
Anexo IV: Listado del programa
Javier Bretón Blas y Jose Antonio Fernández Ros
SW-122/2010
(CN 2010-BF)
Departamento de Organización de Empresas
Universidad Politécnica de Cataluña
Publica:
Universitat Politècnica de Catalunya
www.upc.edu
Edita:
Cátedra Nissan
www.nissanchair.com
[email protected]
TiTOL
Aplicación de los algoritmos de hormigas para la resolución
del problema de equilibrado de líneas de montaje SALBP-E y
aplicacióna un caso real.
ALUMNE
JavierBretónBlas;Jose AntonioFernándezRos
ASSIGNATURA Proyectofinal del carrera
PROFESSOR
D. JoaquínBautistaValhondo
DATA
4 de octubrede 2000
DOCUMENT
Anexo lV: Listadosdel programa
RESUM
Esteanexoincluyeel códigofuenteen Java de las aplicaciones
informáticas
implementadas
para el algoritmode hormigassin
mejora,el algoritmode hormigascon mejoray el multi-start,
así
comola descripción
funcional
de losobjetosque lasforman.
- BARCELONA
INDUSTRIAL
ES C O L AT É C N IC AS U P E R IORD' ENGINYERIA
i
ÍNDICE
RESUMEN................................................................................................................................ 1
CAPÍTULO 1: ALGORITMO DE HORMIGAS................................................................... 2
1.1 DESCRIPCIÓN DEL PROGRAMA ....................................................................................... 3
1.2 LISTADO DE LOS OBJETOS .............................................................................................. 5
CAPÍTULO 2: ALGORITMO DE LAS HORMIGAS CON MEJORA LOCAL............. 58
2.1 DESCRIPCIÓN DEL PROGRAMA ..................................................................................... 59
2.2 LISTADO DE LOS OBJETOS ............................................................................................ 60
CAPÍTULO 3: MULTI-START............................................................................................. 68
3.1 DESCRIPCIÓN DEL PROGRAMA ..................................................................................... 69
3.2 LISTADO DE OBJETOS ................................................................................................... 70
1
RESUMEN
Este anexo incluye el código fuente en Java de las aplicaciones informáticas implementadas
para el algoritmo de hormigas sin mejora, el algoritmo de hormigas con mejora y el multistart, así como la descripción funcional de los objetos que las forman.
2
CAPÍTULO 1: ALGORITMO DE HORMIGAS
3
1.1 DESCRIPCIÓN DEL PROGRAMA
El programa está formado por 20 objetos con la siguientes características:
•
Azar: crea una semilla para la extracción de números aleatorios.
•
CotaSalbpE: cálculo de cotas para el SALBP-E.
•
CotasTC: calcula la cota máxima de tiempo de ciclo y la mínima.
•
Cronometro: contador de tiempo de ejecución.
•
Datos: es el encargado de leer toda la información inicial exterior al programa, así como
de crear la lista de sucesores y precedesores inmediatos.
•
Evaluacion: dada una secuencia de tareas y un tiempo de ciclo máximo y mínimo,
calcula la mejor combinación de tiempo de ciclo y número de estaciones para la
secuencia.
•
Hormiga: es el encargado de crear una secuencia de tareas. Instancia al objeto Indices y
recoge su información.
•
Indices: elabora los índices de decisión dada una lista de tareas candidatas y los
devuelve para ser utilizados por el objeto Hormiga.
•
Listas: contiene las listas de sucesores y predecesores inmediatos, así como la lista de
candidatas y de predecesores inmediatos asignado. Actualiza las dos últimas listas cada
vez que se asigna una tarea a la secuencia.
•
MatrizPesos: crea la matriz de pesos para cada tarea según los 14 criterios heurísticos.
Instancia al objeto CotasTC para calcular una primera cota de tiempo de ciclo máximo,
necesaria para algunos criterios heurísticos.
•
MejorSolucion: contiene la mejor solución global hallada.
•
NextTarea: dado un criterio heurístico y una lista de candidatas, elige la siguiente tarea.
•
NextTareaInicial: extensión de NextTarea utilizado por la clase SolucionInicial
•
Opciones: lee el archivo con opciones y parámetros.
•
Principal: clase principal (main). Inicializa los parámetros y crea las subcolonias.
•
Rastros: contiene la matriz de rastros, así como los métodos para su inicialización.
Además, crea copias de la matriz, controla la desviación de la solución y restaura la
matriz de rastros con la copia creada.
•
Ristra: contiene la secuencia de tareas en curso. Dada una nueva tarea, actualiza la
secuencia.
4
•
Salida: métodos para crear los ficheros de salida.
•
SolucionInicial: crea una solución inicial mediante una heurística Greedy usando los 14
criterios heurísticos.
•
Subcolonia: instancia el objeto Hormiga, lo inicializa y recoge su información. Con esa
información, actualiza la matriz de rastros.
5
1.2 LISTADO DE LOS OBJETOS
1.2.1 Principal
public class Principal
{
public static void main(String arg[])
{
int numSubColonia = 0;
Subcolonia.numSubcolonia = 0;
Cronometro cr = new Cronometro();
cr.inicio(); //Puesta a cero del cronómetro
Azar.semilla(); //Inicializa la semilla del random
Datos datos = new Datos(arg);
datos.importaDatos();
OpcionesTabla op = new OpcionesTabla(arg[4], arg[5]);
op.lecturaOpciones();
Salida salida = new Salida(arg[6]);
salida.cabecera();
MatrizPesos.inicializa();
CotaSalbpE cota = new CotaSalbpE();
MejorSolucion.inicializa();
Subcolonia.maxsubTC = Datos.TiempoTotal;
Subcolonia.mejorsubOBJ = 1000000000;
SolucionInicial solini = new SolucionInicial("ID");
solini.lanzaSolucion();
salida.OBJInicial = MejorSolucion.OBJ;
Rastros rastro = new Rastros(solini.PaqueteOBJ);
rastro.inicializaRastros();
System.out.println();
Subcolonia sub;
boolean condicionFinal = false;
if(Opciones.tipoLimitacion.equals("HORMIGAS")){
cr.fin();
for(int i=1; (i<=Opciones.limitacion) &&
(condicionFinal == false); i++){
//Creación subcolonia
if((i%2) != 0)
sub = new Subcolonia(Opciones.tamano, "ID", i);
else
sub = new Subcolonia(Opciones.tamano, "DI", i);
//Lanzamiento subcolonia
sub.lanzaHormigas();
numSubColonia++;
sub.actualizaRastros();
6
//Control de desvición (backtracking)
rastro.controlBacktracking(sub.igualado, sub.mejorado, i,
sub.Sentido);
System.out.print("Hormiga # "+i+" OBJ=
"+MejorSolucion.OBJ+" Back= "+ Rastros.contback+"\r");
salida.acumulaSalida(sub); //Escritura de la evolución de
//la solución
if(MejorSolucion.OBJ == CotaSalbpE.CotaSalbpE)
condicionFinal = true;
rastro.trasponer();
cr.fin();
}
} else if(Opciones.tipoLimitacion.equals("TIEMPO")){
int i=1;
cr.fin();
while((cr.tiempo()<=Opciones.limitacion) &&
((condicionFinal == false))){
if((i%2) != 0)
sub = new Subcolonia(Opciones.tamano, "ID", i);
else
sub = new Subcolonia(Opciones.tamano, "DI", i);
sub.lanzaHormigas();
numSubColonia++;
sub.actualizaRastros();
System.out.print("Hormiga # "+i+"\r");
rastro.controlBacktracking(sub.igualado, sub.mejorado, i,
sub.Sentido);
if(MejorSolucion.OBJ == Datos.OBJOptima)
condicionFinal = true;
rastro.trasponer();
cr.fin(); //Controla el tiempo que ha transcurrido
i++;
}
}
System.out.println();
System.out.println();
System.out.println("MEJOR SOLUCION");
System.out.println("OBJ= "+MejorSolucion.OBJ);
System.out.println("N = "+MejorSolucion.N);
System.out.println("TC = "+MejorSolucion.TC);
cr.fin();
System.out.println();
System.out.println("Tiempo de ejecucion: "+cr.tiempo()+" s");
salida.tablaSalida(numSubColonia, cr.tiempo());
salida.rellenaBlancos(numSubColonia);
salida.estacionesSalida();
7
salida.escribeSalida();
}
}
1.2.2 Listas
public class Listas
{
int ListaSuc[][];
int ListaPred[];
int ListaPredAsig[];
int Candidatas[];
int limCandidatas = 0; //Marca el final de la lista de candidatas
String Sentido;
public Listas(String s)
{
Sentido = s; // Sentido = ID ó DI
copiaListas();
inicializaCandidatas();
}
//Crea una copia de trabajo para la hormiga de la lista de sucesoras
//y precedesoras inmediatas según el sentido de la hormigo
public void copiaListas()
{
if(Sentido.equals("ID")){
ListaSuc = Datos.ListaSucID;
ListaPred = Datos.ListaPredID;
} else if(Sentido.equals("DI")){
ListaSuc = Datos.ListaSucDI;
ListaPred = Datos.ListaPredDI;
}
ListaPredAsig = new int[Datos.NumTareas+1];
}
//Calcula las candidatas por primera vez:
//Aquellas tareas que no tienen precedentes
public void inicializaCandidatas()
{
//Se crea la lista de candidatas
Candidatas = new int[Datos.NumTareas+1];
for(int i=1; i<=Datos.NumTareas ; i++){
if(ListaPred[i] == 0){
limCandidatas++; //Aumenta el tamaño de la venta
//de la lista de candidatas
Candidatas[limCandidatas] = i;
}
}
}
8
//Actualiza la lista de predecesoras inmediatas y la lista de
//candidatas dada la nueva tarea asignada y la posicion que
//ocupa en la lista de candidatas
public void actualizaListas(int TareaPos[])
{
//Tareas que van a ser nuevas candidatas
int nuevasCandidatas[] = new int[ListaSuc[1].length];
int aux=0;
int suc=0;
int lookTarea;
while((suc<=(ListaSuc[1].length-1)) &&
(ListaSuc[TareaPos[0]][suc] != 0)){
lookTarea = ListaSuc[TareaPos[0]][suc] ;
ListaPredAsig[lookTarea]++; //Aumenta en 1 el número de
//predecesoras asigna de la tareas
//sucesoras a la asignada
if(ListaPred[lookTarea] == ListaPredAsig[lookTarea]){
nuevasCandidatas[aux] = lookTarea;
aux++;
}
suc++;
}
actualizaCandidata(nuevasCandidatas,ListaSuc[1].length,
TareaPos[1]);
}
public void actualizaCandidata(int nuevas[],int longitud, int posicion)
{
if(nuevas[0]==0){ //No hay ninguna candidata nueva
for(int i=posicion; i<=(limCandidatas-1); i++)
Candidatas[i] = Candidatas[i+1];
limCandidatas--;
} else {
Candidatas[posicion] = nuevas[0];
if(longitud > 1){
int i=1;
while((i<=(longitud-1)) && (nuevas[i] !=0)){
Candidatas[limCandidatas+1] = nuevas[i];
limCandidatas++;
i++;
};
}
}
}
}
1.2.3 Ristra
public class Ristra
{
9
int RistraT[];
//Secuencias de tareas
int contTarea = 1;
public int ultimaH;
//Última heurística asignada
public int ultimaT;
//Última tarea asignada
public Evaluacion eval;
public NextTarea next;
public Ristra(String sentido)
{
RistraT = new int[Datos.NumTareas+1];
ultimaT = 0;
next = new NextTarea(sentido);
ultimaH = 0;
}
public void actualizaRistraT(int tarea)
{
RistraT[contTarea] = tarea;
ultimaT = tarea;
contTarea++;
}
public int[] getRistraT()
{
return RistraT;
}
public void evaluacionRistra(){
eval = new Evaluacion(RistraT);
eval.evalua();
}
}
1.2.4 NextTarea
public class NextTarea
{
Listas lista;
int heuristica;
int ultimaT; //Última tarea asignada
// en este vector se guardaran la tarea
// y la posicion que que devolvera la funcion
int tarea[]= new int[2];
String sentido;
//Al constructor hay que pasarle la heuristica para que decida
//la siguiente tarea en funcion de dicha heuristica y un String que
//solo puede ser ID o DI dependiendo si se quiere un lista
//preparada para rellenar una ristra con el problema directo (ID)
//o inverso (DI)
10
public NextTarea(String r)
{
sentido = r;
lista = new Listas(sentido);
}
//Método que devuelve la siguiente tarea y su posición dentro de la
//lista de candidatas
public int[] getTarea(int h, int u)
{
heuristica=h;
ultimaT=u;
if(lista.limCandidatas >=1){
if(sentido.equals("ID"))
return eligeTareaID();
else
return eligeTareaDI();
}
else {
tarea[0] = -1; //Condición de final
tarea[1] = -1;
return tarea;
}
}
public int[] eligeTareaID()
{
int empates;
//Cada fila de la matriz TareaPosAux [k][j] contiene en la
//posicion k una para el desempate y en j su posicion
//se utiliza la posicion "0" del vector
int TareaPosAux[][]= new int[lista.limCandidatas][2];
//Se inicializa el peso maximo y su posicion
//(dentro de la lista de candidatas) con la primera candidata
TareaPosAux[0][0]=lista.Candidatas[1];
TareaPosAux[0][1]=1;
//En la lista de candidatas no se utiliza la
//primera posicion se calcula el peso de la tarea
//candidata con mayor peso
empates=0;
for (int i=1; i <= lista.limCandidatas-1; i++ ){
int a=MatrizPesos.MatrizID[heuristica][lista.Candidatas[i+1]];
int c=MatrizPesos.MatrizID[heuristica][2];
int b=MatrizPesos.MatrizID[heuristica][TareaPosAux[0][0]];
if (MatrizPesos.MatrizID[heuristica][lista.Candidatas[i+1]] ==
MatrizPesos.MatrizID[heuristica][TareaPosAux[0][0]]){
empates++;
TareaPosAux[empates][0]=lista.Candidatas[i+1];
TareaPosAux[empates][1]=i+1;
}
else if(MatrizPesos.MatrizID[heuristica]
[lista.Candidatas[i+1]]>
MatrizPesos.MatrizID[heuristica][TareaPosAux[0][0]]){
empates=0;
11
TareaPosAux[empates][0]=lista.Candidatas[i+1];
TareaPosAux[empates][1]=i+1;
}
}
//Si el numero de empates es mayor que 0
//se debe desempatar
if (empates>0) {
//Al método se le pasa la lista de empates
//y el numero de empates y devuelve la tarea
//despues del desempate
tarea = desempate (TareaPosAux,empates);
}
else if (empates==0){
tarea[0] = TareaPosAux[0][0];
tarea[1] = TareaPosAux[0][1];
}
return tarea;
}
public int[] eligeTareaDI()
{
int empates;
//Cada fila de la matriz TareaPosAux [k][j] contiene
//en la posicion k una para el desempate y en j su posicion
//se utiliza la posicion "0" del vector
int TareaPosAux[][]= new int[lista.limCandidatas][2];
//Se inicializa el peso maximo y su posicion
//(dentro de la lista de candidatas) con la primera candidata
TareaPosAux[0][0]=lista.Candidatas[1];
TareaPosAux[0][1]=1;
//En la lista de candidatas no se utiliza la
//primera posicion se calcula el peso de la tarea
//candidata con mayor peso
empates=0;
for (int i=1; i <= lista.limCandidatas-1; i++ ){
if (MatrizPesos.MatrizDI[heuristica][lista.Candidatas[i+1]] ==
MatrizPesos.MatrizDI[heuristica][TareaPosAux[0][0]]){
empates++;
TareaPosAux[empates][0]=lista.Candidatas[i+1];
TareaPosAux[empates][1]=i+1;
}
else if (MatrizPesos.MatrizDI[heuristica]
[lista.Candidatas[i+1]]>
MatrizPesos.MatrizDI[heuristica][TareaPosAux[0][0]]){
empates=0;
TareaPosAux[empates][0]=lista.Candidatas[i+1];
TareaPosAux[empates][1]=i+1;
}
}
//Si el numero de empates es mayor que 0
//se debe desempatar
if (empates>0) {
12
//Al método se le pasa la lista de empates y el numero
//de empates y devuelve la tarea despues del desempate
tarea = desempate (TareaPosAux,empates);
}
else if (empates==0){
tarea[0] = TareaPosAux[0][0];
tarea[1] = TareaPosAux[0][1];
}
return tarea;
}
public int[] desempate (int TareaPosAux[][],int empates)
{
int empatesRastro;
int tareaPos[] = new int[2];
//Vector donde se guardan las tareas con el rastro maximo,
//si existen mas de 1, se escogerá una al azar
double sameRastro[][] = new double [empates+1][3];
sameRastro[0][0] = TareaPosAux[0][0];
sameRastro[0][1] = TareaPosAux[0][1];
sameRastro[0][2] = Rastros.Tareas[ultimaT][TareaPosAux[0][0]];
empatesRastro=0;
for (int i=0; i <= empates-1; i++){
if (Rastros.Tareas[ultimaT][TareaPosAux[i+1][0]] ==
Rastros.Tareas[ultimaT][(int)(sameRastro[0][0])]){
empatesRastro++;
sameRastro[empatesRastro][0] = TareaPosAux[i+1][0];
sameRastro[empatesRastro][1] = TareaPosAux[i+1][1];
sameRastro[empatesRastro][2] = Rastros.Tareas[ultimaT]
[TareaPosAux[i+1][0]];
}
else if (Rastros.Tareas[ultimaT][TareaPosAux[i+1][0]]>
Rastros.Tareas[ultimaT][(int)(sameRastro[0][0])]){
empatesRastro=0;
sameRastro[empatesRastro][0]=TareaPosAux[i+1][0];
sameRastro[empatesRastro][1]=TareaPosAux[i+1][1];
sameRastro[empatesRastro][2]=
Rastros.Tareas[ultimaT][TareaPosAux[i+1][0]];
}
}
if (empatesRastro>0) {
int azar;
azar = Azar.nextInt(0,empatesRastro);
tarea[0] = (int) (sameRastro[azar][0]);
tarea[1] = (int) (sameRastro[azar][1]);
}
else if (empatesRastro==0){
tarea[0] = (int) (sameRastro[0][0]);
tarea[1] = (int) (sameRastro[0][1]);
}else if (empatesRastro < 0)
System.out.println("error en Next Tarea Desempate:
13
empates rastro menor que 0");
return tarea;
}
}
1.2.5 SoluciónInicial
public class SolucionInicial
{
String sentido;
int tareapos[];
Ristra ristra;
NextTareaInicial next;
int PaqueteRistras[][];
int PaqueteOBJ[];
int numAnt;
public SolucionInicial(String sentido)
{
this.sentido = sentido;
PaqueteOBJ = new int[15];
PaqueteRistras = new int[15][Datos.NumTareas+1];
numAnt = 1;
}
public void lanzaSolucion()
{
for(int h=1; h<=14; h++){
creaSolucion(h);
recogeInformacion();
comparaInformacion();
numAnt++;
}
System.out.println();
System.out.println("MEJOR SOLUCION INICIAL");
System.out.println("OBJ= "+MejorSolucion.OBJ);
System.out.println("N = "+MejorSolucion.N);
System.out.println("TC = "+MejorSolucion.TC);
}
public void creaSolucion(int h)
{
tareapos = new int[2];
ristra = new Ristra(sentido);
next = new NextTareaInicial(sentido);
for(int i=1; i<=Datos.NumTareas; i++){
tareapos = next.getTarea(h, ristra.ultimaT);
ristra.actualizaRistraT(tareapos[0]);
next.lista.actualizaListas(tareapos);
}
14
ristra.evaluacionRistra();
}
public void recogeInformacion()
{
for(int i=1; i<=Datos.NumTareas; i++)
PaqueteRistras[numAnt][i] = ristra.RistraT[i];
PaqueteOBJ[numAnt] = ristra.eval.getObj();
}
public void comparaInformacion()
{
if(PaqueteOBJ[numAnt] < MejorSolucion.OBJ){
MejorSolucion.OBJ = PaqueteOBJ[numAnt];
MejorSolucion.N = ristra.eval.getNumEst();
MejorSolucion.TC = ristra.eval.getTC();
for(int i=1; i<=Datos.NumTareas; i++)
MejorSolucion.Ristra[i] = PaqueteRistras[numAnt][i];
MejorSolucion.sentidoHormiga = "ID";
}
}
}
1.2.6 NextTareaInicial
public class NextTareaInicial extends NextTarea
{
public NextTareaInicial(String r)
{
super(r);
lista = new Listas(sentido);
}
public int[] desempate (int TareaPosAux[][],int empates)
{
int i=1;
int tareaPos[] = new int[2];
tareaPos[0]=TareaPosAux[0][0];
tareaPos[1]=TareaPosAux[0][1];
for (i=1; i <= empates ; i++){
if(sentido.equals("ID")){
if (TareaPosAux[i][0] < tareaPos[0]){
tareaPos[0] = TareaPosAux[i][0];
tareaPos[1] = TareaPosAux[i][1];
}
} else {
if (TareaPosAux[i][0] > tareaPos[0]){
tareaPos[0] = TareaPosAux[i][0];
tareaPos[1] = TareaPosAux[i][1];
}
}
}
15
return tareaPos;
}
}
1.2.7 Indices
import java.math.*;
public class Indices
{
int HeuIntrinseca;
//Heurística intrínseca a la hormiga
double VectorIndices[]; //Índices de decisión
int t[][];
//Tarea asociada a la heurística elegida
//y su posición en la lista de candidatas
Ristra ristra;
String tipo;
int limCandidatas;
public Indices(int i)
{
HeuIntrinseca = i;
}
public int[] eligeTarea(Ristra r, String t)
{
ristra = r;
tipo = t;
limCandidatas = ristra.next.lista.limCandidatas;
VectorIndices = new double[limCandidatas+1];
VectorIndices = calculoIndices();
if(tipo.equals("ALEA"))
return sorteo();
else return maximo();
}
//Calcula los índices de decisión
public double[] calculoIndices()
{
double vectorAux[] = new double[limCandidatas+1];
double sumaDenominador = 0;
int ph[] = new int[limCandidatas+1]; //Peso de la tarea con la
//heurística intrínseca
int sumaph = 0;
//Denominador para ponderar los ph
double sumaRastro = (double) (0.0); //Denominador para ponderar
//los rastros
for(int i=1; i<=limCandidatas; i++){
int taux; //Tarea de la posicion i de la lista de candidatas
taux = ristra.next.lista.Candidatas[i];
ph[i] = Hormiga.Pesos[HeuIntrinseca][taux];
sumaph += ph[i];
sumaRastro += Rastros.Tareas[ristra.ultimaT][taux];
}
16
//Índices sin acumulación
if(Opciones.ponderacionIndices.equals("SI")){
for(int i=1; i<=limCandidatas; i++){
int taux; //Tarea de la posicion i de
//la lista de candidatas
taux = ristra.next.lista.Candidatas[i];
vectorAux[i] = (Math.pow(100*
(Rastros.Tareas[ristra.ultimaT][taux])/
sumaRastro,Opciones.alfa)) *
Math.pow(100*((double)(ph[i])/
(double)(sumaph)), Opciones.beta));
sumaDenominador += vectorAux[i];
}
} else if(Opciones.ponderacionIndices.equals("NO")){
for(int i=1; i<=limCandidatas; i++){
int taux;
taux = ristra.next.lista.Candidatas[i];
vectorAux[i] = (Math.pow(
(Rastros.Tareas[ristra.ultimaT][taux]),
Opciones.alfa)) *
(Math.pow((double)(ph[i]), Opciones.beta));
sumaDenominador += vectorAux[i];
}
} else System.out.println("ERROR: Elegir si hay o no índices de
ponderación");
if(tipo.equals("ALEA")){
VectorIndices[0] = 0;
for(int i=1; i<=limCandidatas; i++)
VectorIndices[i] = VectorIndices[i-1] +
vectorAux[i]/sumaDenominador;
} else {
for(int i=1; i<=limCandidatas; i++)
VectorIndices[i] = vectorAux[i];
}
return VectorIndices;
}
public int[] sorteo(){
int cand = limCandidatas; //Nº candidata escogida en el sorteo
//cand=limCanditas al inicio para
//asegurar la candidata
//en caso de que rand sea igual a 1
double rand = Azar.aleatorio.nextDouble();
for(int i=1; i<=limCandidatas; i++){
if((rand >= VectorIndices[i-1]) && (rand < VectorIndices[i])){
cand = i;
i = limCandidatas+1; //Marca para salir del bucle
}
}
17
int tareapos[] = new int[2];
tareapos[0] = ristra.next.lista.Candidatas[cand];
tareapos[1] = cand;
return tareapos;
}
public int[] maximo(){
int cand = 1; //Tarea escogida por ser la de mayor índice
for(int i=2; i<=limCandidatas; i++){
if(VectorIndices[i]>VectorIndices[cand])
cand = i;
}
int tareapos[] = new int[2];
tareapos[0] = ristra.next.lista.Candidatas[cand];
tareapos[1] = cand;
return tareapos;
}
}
1.2.8 Hormiga
import java.math.*;
public class Hormiga
{
Ristra ristra;
Indices indices;
int heuIntrinseca;
String sentido;
String tipo;
static int Pesos[][];
//Matriz de pesos estandarizada
public Hormiga(int h, String s, String t)
{
heuIntrinseca = h; //Heurística intrínseca
sentido = s;
//Dirección: ID ó DI
tipo = t;
//Aleatoria o pseudo-aleatoria
ristra = new Ristra(sentido);
indices = new Indices(heuIntrinseca);
if(sentido.equals("ID"))
Pesos = MatrizPesos.MatrizID;
else
Pesos = MatrizPesos.MatrizDI;
}
public void construirSolucion()
{
18
//Opción según hormigas aleatorias o pseudo-aleatorias
if(tipo.equals("ALEA"))
aleatorio(1, Datos.NumTareas);
else if(tipo.equals("PSEUDO"))
pseudoAleatorio();
ristra.evaluacionRistra();
}
public void aleatorio(int inicio, int fin)
{
int tareapos[]; //Tarea elegida
for(int i=inicio; i<=fin; i++){
tareapos = indices.eligeTarea(ristra, "ALEA");
//Se añade la tarea a la secuencia de tareas
ristra.actualizaRistraT(tareapos[0]);
//Se actualiza la lista de candidatas
ristra.next.lista.actualizaListas(tareapos);
}
}
public void pseudoAleatorio()
{
int tareapos[] = new int[2]; //Tarea elegida
double rand; //Índice para el sorteo pesudo-aleatorio
for(int cont=1; cont<=Datos.NumTareas; cont++){
rand = Math.random();
if(rand>Opciones.indicePseudo) //Elige ser aleatorio
aleatorio(cont, cont);
else {
//Elige ser pseudo-aleatorio
tareapos = indices.eligeTarea(ristra, "PSEUDO");
ristra.actualizaRistraT(tareapos[0]);
ristra.next.lista.actualizaListas(tareapos);
}
}
}
}
1.2.9 Evaluacion
import java.math.*;
public class Evaluacion
{
private int Ristra[];
private int Obj, TC, NumEst;
String mejorSentido;
19
public Evaluacion(int ris[])
{
Ristra = ris;
}
public void evalua()
{
mejorSentido = "ID";
evaluaID();
evaluaDI();
MejorSolucion.sentidoEval = mejorSentido;
}
public void evaluaID()
{
int TC2 = CotasTC.CotaMinTC;
Obj = 1000000000;
int tacum, tasig, TCajust2, n2, TCnext;
int i, r;
int marca, cota2;
int obj2 = Obj+1; //Se pone porque hay que inicilizarla!!!
do{ //loop de tiempos de ciclo
tacum = 0; tasig = 0; TCajust2 = 0;
n2 = 1;
r = 1;
marca = 0;
cota2 = 1;
TCnext = 1000000000;
Salida.numSol++; //Contador del número de soluciones evaluadas
do{ //loop de r
i = Ristra[r];
tacum += Datos.Tiempos[i];
if(tacum > TC2){
if((tacum-Datos.Tiempos[i]) > TCajust2)
TCajust2 = tacum-Datos.Tiempos[i];
if(tacum < TCnext)
TCnext = tacum;
tasig = tasig + tacum - Datos.Tiempos[i];
tacum = Datos.Tiempos[i];
n2 += 1;
if((n2-1+
(int)Math.floor((double)(Datos.TiempoTotaltasig)/TC2))*TCajust2 >=
Subcolonia.mejorsubOBJ)
cota2 = 0;
}
if(r==Datos.NumTareas)
marca = 1;
r++;
} while((r<=Datos.NumTareas) &&
(n2*TCajust2<Subcolonia.mejorsubOBJ) && (cota2>0) &&
(n2<=Datos.NumEstMax));
20
if(tacum>TCajust2) {TCajust2 = tacum;}
if(TC2 == Datos.TiempoTotal) {TCajust2 = TC2;}
if((marca==1) && n2<=Datos.NumEstMax)
{obj2 = TCajust2*n2;}
else if((marca==0) || n2>Datos.NumEstMax) {obj2 = Obj +1;}
if(n2<=Datos.NumEstMax){
if(n2 > Datos.NumEstMin){
if((obj2 <= Obj) && (marca==1)){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
Subcolonia.mejorsubOBJ = Obj;
}
TC2 = TCnext;
} else if(n2 == Datos.NumEstMin){
if(marca == 1){
if(TCajust2<CotasTC.CotaMaxTC){
CotasTC.CotaMaxTC = TCajust2;
MatrizPesos.actualizaPesos();
}
if(TCajust2<Subcolonia.maxsubTC){
Subcolonia.maxsubTC = TCajust2;
}
if(obj2 <= Obj){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
Subcolonia.mejorsubOBJ = Obj;
}
TC2 = Datos.TiempoTotal+1;
} else if(marca == 0){
if((Datos.TiempoTotal-tasig)<=TC2){
if((Datos.TiempoTotal-tasig)>TCajust2)
TCajust2 = Datos.TiempoTotal-tasig;
obj2 = n2*TCajust2;
if(obj2 <= Obj){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
Subcolonia.mejorsubOBJ = Obj;
}
if(TCajust2<CotasTC.CotaMaxTC){
CotasTC.CotaMaxTC = TCajust2;
MatrizPesos.actualizaPesos();
}
if(TCajust2<Subcolonia.maxsubTC){
Subcolonia.maxsubTC = TCajust2;
}
TC2 = Datos.TiempoTotal+1;
} else if((Datos.TiempoTotal-tasig)>TC2)
TC2 = TCnext;
}
} else if(n2<Datos.NumEstMin){
if(marca == 1)
TC2 = Datos.TiempoTotal+1;
else if(marca == 0){
21
if((n2-1+(int)Math.floor(
(double)(Datos.TiempoTotal-tasig)/TC2))
> Datos.NumEstMin)
TC2 = TCnext;
else if((n2-1+(int)Math.floor(
(double)(Datos.TiempoTotal-tasig)/TC2))
<= Datos.NumEstMin)
TC2 = Datos.TiempoTotal+1;
}
}
} else
TC2 = TCnext;
} while(TC2 <= Subcolonia.maxsubTC);
}
public void evaluaDI()
{
int TC2 = CotasTC.CotaMinTC;
int tacum, tasig, TCajust2, n2, TCnext;
int i, r;
int marca, cota2;
int obj2 = Obj+1; //Se pone porque hay que inicilizarla!!!
do{ //loop de tiempos de ciclo
tacum = 0; tasig = 0; TCajust2 = 0;
n2 = 1;
r = 1;
marca = 0;
cota2 = 1;
TCnext = 1000000000;
Salida.numSol++; //Contador del número de soluciones evaluadas
do{ //loop de r
i = Ristra[r];
tacum += Datos.Tiempos[i];
if(tacum > TC2){
if((tacum-Datos.Tiempos[i]) > TCajust2)
TCajust2 = tacum-Datos.Tiempos[i];
if(tacum < TCnext)
TCnext = tacum;
tasig = tasig + tacum - Datos.Tiempos[i];
tacum = Datos.Tiempos[i];
n2 += 1;
if((n2-1+
(int)Math.floor((double)(Datos.TiempoTotaltasig)/TC2))*TCajust2 >=
Subcolonia.mejorsubOBJ)
cota2 = 0;
}
if(r==Datos.NumTareas)
marca = 1;
r++;
} while((r<=Datos.NumTareas) &&
(n2*TCajust2<Subcolonia.mejorsubOBJ) && (cota2>0) &&
(n2<=Datos.NumEstMax));
22
if(tacum>TCajust2) {TCajust2 = tacum;}
if(TC2 == Datos.TiempoTotal) {TCajust2 = TC2;}
if((marca==1) && n2<=Datos.NumEstMax)
{obj2 = TCajust2*n2;}
else if((marca==0) || n2>Datos.NumEstMax) {obj2 = Obj +1;}
if(n2<=Datos.NumEstMax){
if(n2 > Datos.NumEstMin){
if((obj2 <= Obj) && (marca==1)){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
mejorSentido = "DI";
Subcolonia.mejorsubOBJ = Obj;
}
TC2 = TCnext;
} else if(n2 == Datos.NumEstMin){
if(marca == 1){
if(TCajust2<CotasTC.CotaMaxTC){
CotasTC.CotaMaxTC = TCajust2;
MatrizPesos.actualizaPesos();
}
if(TCajust2<Subcolonia.maxsubTC){
Subcolonia.maxsubTC = TCajust2;
}
if(obj2 <= Obj){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
mejorSentido = "DI";
Subcolonia.mejorsubOBJ = Obj;
}
TC2 = Datos.TiempoTotal+1;
} else if(marca == 0){
if((Datos.TiempoTotal-tasig)<=TC2){
if((Datos.TiempoTotal-tasig)>TCajust2)
TCajust2 = Datos.TiempoTotal-tasig;
obj2 = n2*TCajust2;
if(obj2 <= Obj){
Obj = obj2;
TC = TCajust2;
NumEst = n2;
mejorSentido = "DI";
Subcolonia.mejorsubOBJ = Obj;
}
if(TCajust2<CotasTC.CotaMaxTC){
CotasTC.CotaMaxTC = TCajust2;
MatrizPesos.actualizaPesos();
}
if(TCajust2<Subcolonia.maxsubTC){
Subcolonia.maxsubTC = TCajust2;
}
TC2 = Datos.TiempoTotal+1;
} else if((Datos.TiempoTotal-tasig)>TC2)
TC2 = TCnext;
}
} else if(n2<Datos.NumEstMin){
23
if(marca == 1)
TC2 = Datos.TiempoTotal+1;
else if(marca == 0){
if((n2-1+(int)Math.floor(
(double)(Datos.TiempoTotal-tasig)/TC2))
> Datos.NumEstMin)
TC2 = TCnext;
else if((n2-1+(int)Math.floor(
(double)(Datos.TiempoTotal-tasig)/TC2))
<= Datos.NumEstMin)
TC2 = Datos.TiempoTotal+1;
}
}
} else
TC2 = TCnext;
} while(TC2 <= Subcolonia.maxsubTC);
}
public int getObj(){
return Obj;
}
public int getTC(){
return TC;
}
public int getNumEst(){
return NumEst;
}
}
1.2.10 Rastros
import java.math.*;
public class Rastros
{
static double[][] Tareas;
int[] solini;
int contBacktracking, auxBacktracking;
double[][] copiaTareas;
static int contback;
public Rastros(int[] s)
{
solini = s;
Tareas = new double[Datos.NumTareas+1][Datos.NumTareas+1];
copiaTareas = new double[Datos.NumTareas+1][Datos.NumTareas+1];
contBacktracking = 0;
auxBacktracking = 0;
contback = 0;
}
public void inicializaRastros()
24
{
if(Opciones.tipoRastro.equals("CONSTANTE"))
constante();
else if(Opciones.tipoRastro.equals("ALEATORIO"))
aleatorio();
}
public void constante()
{
for(int i=0; i<=Datos.getNumTareas(); i++){
for(int j=0; j<=Datos.getNumTareas(); j++){
Tareas[i][j] = Opciones.rastroInicial;
}
}
}
public void aleatorio()
{
for(int i=0; i<=Datos.getNumTareas(); i++){
for(int j=0; j<=Datos.getNumTareas(); j++){
Tareas[i][j] = Azar.aleatorio.nextInt();
}
}
}
public void trasponer()
{
double aux;
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=i+1; j<=Datos.NumTareas; j++){
aux = Tareas[i][j];
Tareas[i][j] = Tareas[j][i];
Tareas[j][i] = aux;
}
}
}
//Hace una copia de la Matriz de Rastros
//para poder restaurarla en caso de backtracking
public void copiaRastro(String sentido)
{
//La matriz de copia siempre se guarda en sentido ID
if(sentido.equals("ID")){
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++)
copiaTareas[i][j] = Tareas[i][j];
}
} else {
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++)
25
copiaTareas[i][j] = Tareas[j][i];
}
}
}
//Sustituye la matriz actual por la
//copia guardada por copiaRastro()
public void restauraRastro(String sentido)
{
//La matriz de copia siempre se guarda en sentido ID
if(sentido.equals("ID")){
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++)
Tareas[i][j] = copiaTareas[i][j];
}
} else {
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++)
Tareas[i][j] = copiaTareas[j][i];
}
}
}
//Controla la desviación de las soluciones
//y decide si es necesario un backtracking
public void controlBacktracking(boolean igualado, boolean mejorado,
int subcolonia, String sentido)
{
if(igualado == true)
contBacktracking++;
if(mejorado == true){
auxBacktracking = subcolonia;
contBacktracking = 1;
copiaRastro(sentido);
}
if(subcolonia > (auxBacktracking+100)){
if(contBacktracking < 40){
restauraRastro(sentido);
contback++;
}
auxBacktracking = subcolonia;
contBacktracking = 0;
}
}
}
1.2.11 Subcolonia
public class Subcolonia
{
int tamano; //1 ó 14
String Sentido;
26
Hormiga ant;
int numAnt = 0;
double b;
boolean marcaMejor = false; //true si la mejor hormiga mejora
//o iguala la OBJ global
boolean marcaMejorSolo = false; //true si la mejor hormiga
//mejora la OBJ global
boolean mejorado, igualado; //Parámetros para el control
//de backtracking
static int mejorsubOBJ;
static int maxsubTC;
static int numSubcolonia;
MejoraLocal mejora;
//Atributos para la recolección de información
int PaqueteRistras[][];
int PaqueteOBJ[];
int PaqueteN[];
int PaqueteTC[];
int numSub;
public Subcolonia(int t, String s, int n)
{
tamano = t;
Sentido = s;
PaqueteOBJ = new int[14];
PaqueteRistras = new int[14][Datos.NumTareas+1];
PaqueteN = new int[14];
PaqueteTC = new int[14];
MatrizPesos.actualizaPesoAzar(Sentido);
mejorsubOBJ = 2000000000;
maxsubTC = Datos.TiempoTotal;
rastretes = Rastros.Tareas;
numSub = n;
igualado = false;
mejorado = false;
}
public void lanzaHormigas()
{
for(int i=1; i<=14; i++){
ant = new Hormiga(i, Sentido, Opciones.tipoHormiga);
ant.construirSolucion();
recogeInformacion();
comparaInformacion();
numAnt++;
}
numSubcolonia++;
}
27
public void recogeInformacion()
{
for(int i=1; i<=Datos.NumTareas; i++)
PaqueteRistras[numAnt][i] = ant.ristra.RistraT[i];
PaqueteOBJ[numAnt] = ant.ristra.eval.getObj();
PaqueteN[numAnt] = ant.ristra.eval.getNumEst();
PaqueteTC[numAnt] = ant.ristra.eval.getTC();
}
public void comparaInformacion()
{
if(PaqueteOBJ[numAnt] < MejorSolucion.OBJ){
MejorSolucion.OBJ = PaqueteOBJ[numAnt];
MejorSolucion.N = PaqueteN[numAnt];
MejorSolucion.TC = PaqueteTC[numAnt];
for(int i=1; i<=Datos.NumTareas; i++)
MejorSolucion.Ristra[i] = PaqueteRistras[numAnt][i];
MejorSolucion.sentidoHormiga = Sentido;
MejorSolucion.sentidoEval = ant.ristra.eval.mejorSentido;
marcaMejorSolo = true;
mejorado = true;
}
if(PaqueteOBJ[numAnt] <= MejorSolucion.OBJ){
marcaMejor = true;
igualado = true;
}
}
public void actualizaRastros()
{
evaporaRastros();
actualizaTareas();
}
public void actualizaTareas()
{
double unidadRastro[] = new double[15];
double sumaOBJ = 0;
int tareaA, tareaB;
if(tamano == 14){
//Dejan rastro todas las hormigas
for(int i=0; i<=13; i++){
b = 100.0*(((double)(PaqueteOBJ[i])(double)(Datos.TiempoTotal))/
((double)(Datos.TiempoTotal)));
unidadRastro[i] = 1/(Math.pow(b, 1.0));
}
for(int contAnt = 0; contAnt<=13; contAnt++){
tareaA = 0;
28
for(int r=1; r<=Datos.NumTareas; r++){
tareaB = PaqueteRistras[contAnt][r];
Rastros.Tareas[tareaA][tareaB] +=
unidadRastro[contAnt];
tareaA = tareaB;
}
}
}
//Sólo dejan rastro las mejores hormigas
int minOBJ[] = new int[14]; //Contiene las hormigas con mejor OBJ
int limAnt = 0;
minOBJ[0] = 0;
for(int contAnt=1; contAnt<=13; contAnt++){
if(PaqueteOBJ[contAnt]<PaqueteOBJ[minOBJ[0]]){
minOBJ[0] = contAnt;
limAnt = 0;
} else if(PaqueteOBJ[contAnt]==PaqueteOBJ[minOBJ[0]]){
minOBJ[limAnt+1] = contAnt;
limAnt++;
}
}
if(marcaMejor == true){ //La mejor hormiga mejora o
//iguala la OBJ global
for(int i=0; i<=limAnt; i++){
tareaA = 0;
for(int r=1; r<=Datos.NumTareas; r++){
tareaB = PaqueteRistras[minOBJ[i]][r];
double maxRastro = 0.0;
//Se busca el máximo rastro
for(int j=0; j<=Datos.NumTareas; j++){
if(Rastros.Tareas[tareaA][j] > maxRastro)
maxRastro = Rastros.Tareas[tareaA][j];
}
//Rastro extra
if(marcaMejorSolo == true){
for(int j=0; j<=Datos.NumTareas; j++)
Rastros.Tareas[tareaA][j] *=
(1-Opciones.evaporacionExtra);
maxRastro *= Opciones.rastroExtra;
}
//Iguala el máximo rastro
Rastros.Tareas[tareaA][tareaB] = maxRastro;
tareaA = tareaB;
}
if(marcaMejorSolo == true){ //Última tarea de la secuencia
double maxRastro = 0.0;
for(int j=0; j<=Datos.NumTareas; j++){
//Se busca el máximo rastro
if(Rastros.Tareas[tareaA][j] > maxRastro)
maxRastro = Rastros.Tareas[tareaA][j];
}
for(int pos=0; pos<=Datos.NumTareas; pos++)
//Evaporación extra de la fila de la
29
//última tarea de la ristra
Rastros.Tareas[tareaA][pos] *=
(1-Opciones.evaporacionExtra);
maxRastro *= Opciones.rastroExtra;
Rastros.Tareas[tareaA][0] = maxRastro;
marcaMejorSolo = false; //Ya no entra más, sólo evapora
//la primera hormiga
}
}
}
for(int i=0; i<=limAnt; i++){
b = 100.0*(((double)(PaqueteOBJ[minOBJ[i]])((double)(CotaSalbpE.CotaSalbpE)))/
((double)(CotaSalbpE.CotaSalbpE)));
double unidad = 1/(Math.pow(b, 2.0));
tareaA = 0;
for(int r=1; r<=Datos.NumTareas; r++){
tareaB = PaqueteRistras[minOBJ[i]][r];
Rastros.Tareas[tareaA][tareaB] += unidad;
tareaA = tareaB;
}
Rastros.Tareas[tareaA][0] += unidad;
//Rastro entre la última tarea de la ristra
//y la tarea 0 en sentido contrario
}
}
public void evaporaRastros()
{
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++)
Rastros.Tareas[i][j] = Rastros.Tareas[i][j]*
(1.0-Opciones.evaporacion);
}
}
}
1.2.12 Opciones
import java.io.*;
import java.util.*;
public class Opciones
{
private String fichero;
static double alfa;
static double beta;
static double evaporacion ;
30
static
static
static
static
static
static
static
static
static
static
static
static
double evaporacionExtra;
double rastroExtra;
int tamano;
String tipoHormiga;
double indicePseudo;
String sentido;
double rastroInicial;
double coefDifusion;
String tipoRastro;
String tipoLimitacion;
int limitacion;
String ponderacionIndices;
public Opciones(String f)
{
fichero = f;
}
public void lecturaOpciones()
{
try{
String descripcion;
BufferedReader inbr = new BufferedReader(
new FileReader(fichero));
String inString = inbr.readLine();
StringTokenizer st = new StringTokenizer(inString);
descripcion = st.nextToken();
while(!descripcion.equals("fin")){
if(descripcion.equals("alfa"))
alfa = Double.valueOf(
st.nextToken().trim()).doubleValue();
else if(descripcion.equals("beta"))
beta = Double.valueOf(
st.nextToken().trim()).doubleValue();
else if(descripcion.equals("evaporacion"))
evaporacion = Double.valueOf(
st.nextToken().trim()).doubleValue();
else if(descripcion.equals("evaporacionExtra"))
evaporacionExtra = Double.valueOf(
st.nextToken().trim()).doubleValue();
else if(descripcion.equals("rastroExtra"))
rastroExtra = Double.valueOf(
st.nextToken().trim()).doubleValue();
else if(descripcion.equals("tipoHormiga")){
tipoHormiga = st.nextToken();
if(tipoHormiga.equals("PSEUDO"))
indicePseudo = Double.valueOf(
st.nextToken().trim()).doubleValue();
} else if(descripcion.equals("sentido"))
sentido = st.nextToken();
else if(descripcion.equals("tamano"))
tamano = Integer.valueOf(
st.nextToken().trim()).intValue();
31
else if(descripcion.equals("rastroInicial")){
tipoRastro = st.nextToken();
if(tipoRastro.equals("CONSTANTE"))
rastroInicial = Double.valueOf(
st.nextToken().trim()).doubleValue();
if(tipoRastro.equals("DIFUSION"))
coefDifusion = Double.valueOf(
st.nextToken().trim()).doubleValue();
} else if(descripcion.equals("limitacion")){
tipoLimitacion = st.nextToken();
limitacion = Integer.valueOf(
st.nextToken().trim()).intValue();
} else if(descripcion.equals("ponderacionIndices"))
ponderacionIndices = st.nextToken();
inString = inbr.readLine();
st = new StringTokenizer(inString);
descripcion = st.nextToken();
}
} catch(EOFException e) {
System.out.println("End of stream encountered");
} catch(FileNotFoundException e) {
System.out.println("File Not Found:" + fichero);
} catch(IOException e){
System.out.println("IO Exception");
}
}
}
1.2.13 Datos
import java.io.*;
import java.util.*;
public class Datos
{
static int NumTareas;
static int NumEstMin, NumEstMax;
static int Tiempos[];
static int MatrizSucI[][];
static int MatrizSuc[][];
static int MatrizPre[][];
static int ListaSucID[][];
static int ListaSucDI[][];
static int ListaPredID[];
static int ListaPredDI[];
static int TiempoTotal;
static int TiempoMax;
static int OBJOptima;
private String argumentos[];
public Datos(String a[])
{
argumentos=a;
NumEstMin = Integer.valueOf(argumentos[1].trim()).intValue();
NumEstMax = Integer.valueOf(argumentos[2].trim()).intValue();
32
OBJOptima = Integer.valueOf(argumentos[3].trim()).intValue();
}
public void importaDatos(){
try{
//Lectura del número de tareas (NumTareas)
BufferedReader inbr = new BufferedReader(
new FileReader(argumentos[0]));
NumTareas = Integer.valueOf(inbr.readLine().trim()).intValue();
//Lectura de los tiempos de las tareas (Tiempos[])
Tiempos = new int[NumTareas+1];
for(int i=1;i<=NumTareas;i++){
Tiempos[i]=
(Integer.valueOf(inbr.readLine().trim()).intValue());
}
//Cálculo del número máximo de sucesores ID
//y relleno MatrizSucI
inbr.mark(1000000);
MatrizSucI = new int[NumTareas+1][NumTareas+1];
int NumSucID=0;
NumSucID = getNumSucID(inbr);
//Inicilizar la matriz ListaPred y ListaSuc ID
inicializaMatrices(NumSucID, ListaSucID, ListaPredID);
//Se llena la lista de sucesores y precedesores ID
inbr.reset();
llenaListaID(inbr, NumSucID);
inbr.close();
//Cálculo del número máximo de sucesores DI
int NumSucDI = 0;
NumSucDI = getNumSucDI();
//Inicializa la matriz ListaPred Y ListaSuc ID
inicializaMatrices(NumSucDI, ListaSucDI, ListaPredDI);
//Se llena la lista de sucesores y predecesores DI
llenaListaDI(NumSucDI, NumSucID);
//Calcula la suma total de tiempos
TiempoTotal = sumaTiempos();
} catch(EOFException e) {
System.out.println("End of stream encountered");
} catch(FileNotFoundException e) {
System.out.println("File Not Found:" + argumentos[0]);
} catch(IOException e){
System.out.println("IO Exception");
}
33
}
//Método que devuelve el número máximo de sucesores ID
//a partir del stream de lectura directo del fichero
public int getNumSucID(BufferedReader inbr) throws IOException
{
String inString = inbr.readLine();
StringTokenizer st = new StringTokenizer(inString);
for(int i=1; i<=NumTareas ; i++)
MatrizSucI[i][i] = 1;
int a, b, aux, NumSucID=0, NumSucAux=1;
a = Integer.valueOf(st.nextToken().trim()).intValue();
aux = Integer.valueOf(st.nextToken().trim()).intValue();
MatrizSucI[a][aux]=1;
inString = inbr.readLine();
st = new StringTokenizer(inString);
b=Integer.valueOf(st.nextToken().trim()).intValue();
aux = Integer.valueOf(st.nextToken().trim()).intValue();
while(aux != -1){
MatrizSucI[b][aux]=1;
if(a==b){
NumSucAux++;
} else {
a=b;
if(NumSucAux>NumSucID){
NumSucID=NumSucAux;
}
NumSucAux=1;
}
inString = inbr.readLine();
st = new StringTokenizer(inString);
b = Integer.valueOf(st.nextToken().trim()).intValue();
aux = Integer.valueOf(st.nextToken().trim()).intValue();
}
if(NumSucAux > NumSucID)
NumSucID = NumSucAux;
return(NumSucID);
}
//Inicializa a cero todos los valores de las
//Listas de Sucesores y Predecedorestanto de ID como de DI
public void inicializaMatrices(int NumSuc, int ListaSuc[][],
int ListaPred[])
{
ListaSuc = new int[NumTareas+1][NumSuc];
ListaPred = new int[NumTareas+1];
34
for(int i=0; i<=NumTareas; i++){
ListaPred[i]=0;
for(int j=0;j<=(NumSuc-1);j++)
ListaSuc[i][j]=0;
}
}
//Crea y llena las listas de predecesores y sucesores a partir del
//stream de entrada del fichero sabiendo el número máximo de sucesores.
public void llenaListaID(BufferedReader inbr, int NumSuc)
throws IOException
{
ListaSucID = new int[NumTareas+1][NumSuc];
ListaPredID = new int[NumTareas+1];
String inString = inbr.readLine();
StringTokenizer st = new StringTokenizer(inString);
int a = Integer.valueOf(st.nextToken().trim()).intValue();
int b = Integer.valueOf(st.nextToken().trim()).intValue();
int aux;
int cont=0;
while(a != -1){
ListaSucID[a][cont]=b;
ListaPredID[b]++;
aux = a;
inString = inbr.readLine();
st = new StringTokenizer(inString);
a = Integer.valueOf(st.nextToken().trim()).intValue();
b = Integer.valueOf(st.nextToken().trim()).intValue();
if(a==aux)
cont++;
else
cont=0;
}
}
//Calcula el número máximo de sucesores de DI una vez rellenadas las
//listas de sucesores y predecesores de ID.
public int getNumSucDI()
{
int NumSucDI=0;
for(int i=1; i<=NumTareas;i++){
if(ListaPredID[i]>NumSucDI)
NumSucDI = ListaPredID[i];
}
return (NumSucDI);
}
35
//Crea y llena las listas de sucesores y predecesores de ID una vez
//se tienen las de DI.
public void llenaListaDI(int NumSucDI, int NumSucID)
{
ListaSucDI = new int[NumTareas+1][NumSucDI];
ListaPredDI = new int[NumTareas+1];
int cont[] = new int[NumTareas+1];
for(int i=0; i<=(NumSucDI-1);i++)
cont[i]=0;
for(int i=1;i<=NumTareas;i++){
for(int j=0;j<=(NumSucID-1);j++){
if(ListaSucID[i][j] != 0){
ListaSucDI[ListaSucID[i][j]][cont[ListaSucID[i][j]]]=i;
ListaPredDI[i]++;
cont[ListaSucID[i][j]]++;
}
}
}
}
public static int getNumTareas()
{
return NumTareas;
}
public int sumaTiempos()
{
TiempoMax=0;
int suma = 0;
for(int i=1; i<=NumTareas; i++){
suma += Tiempos[i];
if (Tiempos[i]>TiempoMax)
TiempoMax = Tiempos[i];
}
return suma;
}
}
1.2.14 MatrizPesos
public class MatrizPesos
{
static int MatrizID[][];
static int MatrizDI[][];
static int MatrizSuc[][];
final static void inicializa()
{
calculoMatrizSuc();
inicializaID();
inicializaDI();
36
actualizaPesoAzar("ID");
actualizaPesoAzar("DI");
}
final static void inicializaID()
{
//La matriz MatrizID contiene en la posicion [i][j] el peso
//de la tarea j segun el criterio i segun el grafo directo
MatrizID = new int[15][Datos.getNumTareas()+1];
peso1ID();
CotasTC cotas = new CotasTC(); //El cálculo de algunos pesos
cotas.calculoCotasIniciales(); //requieren conocer la cotaMaxTC
peso2ID();
peso3ID();
peso4ID();
peso5ID();
peso6ID();
peso7ID();
peso8ID();
peso9ID();
peso10ID();
peso11ID();
peso12ID();
peso13ID();
ConstruirMatrizPesos(MatrizID);
}
final static void inicializaDI()
{
//La matriz MatrizDI contiene en la posicion [i][j] el peso
//de la tarea j segun el criterio i segun el grafo inverso
MatrizDI = new int[15][Datos.getNumTareas()+1];
peso1DI();
peso2DI();
peso3DI();
peso4DI();
peso5DI();
peso6DI();
peso7DI();
peso8DI();
peso9DI();
peso10DI();
peso11DI();
peso12DI();
peso13DI();
ConstruirMatrizPesos(MatrizDI);
}
//Algoritmo de ordenacion rapida para estandarizar los pesos
public static int[][] Quicksort (int a[][], int izq, int der)
{
int indiceTareaAux,indicePesoAux, i , j , k ;
if(izq < der){
37
i = izq; //Extremo izquierdo del vector o
j = der; //extremo derecho del vector numero de componentes
k = (int) ((izq+der)/2); //Punto que se utiliza como pivote en
int pivote =a[k][1];
//la variable pivote se coloca el peso
do {
while((a[i][1] < pivote) ) i++;
while((a[j][1] > pivote) ) j--;
if (i <= j ){
indiceTareaAux =a[j][0];
indicePesoAux = a[j][1];
a[j][1] = a[i][1];
a[j][0] = a[i][0];
a[i][0] = indiceTareaAux;
a[i][1] = indicePesoAux;
i++;
j--;
}
}while (i < j);
a = Quicksort (a, izq, j);
a = Quicksort (a, i, der);
}
return a;
}
//A este método se le pasa las tareas ordenadas convenientemente en
//función de sus pesos, y los transforma a la forma estandar (todos
//positivos y mayores que o)para el cálculo de los índices de decisión
final static void ConstruirMatrizPesos(int MatrizPes[][])
{
//Al método quicksort se le pasa la tarea y su peso
//que se guarda en aux1[i][j], el índice de
//la tarea se guarda en la columna i y el peso en la j
int n=Datos.getNumTareas();
int [][] aux = new int [n+1][2];
for(int heuristica=1; heuristica <= 14 ; heuristica++){
for(int tarea=1 ; tarea <= n; tarea++) {
aux[tarea][0] = tarea;
aux[tarea][1] = MatrizPes[heuristica][tarea];
}
//Se ordena el vector por pesos
aux = Quicksort (aux, 1, n);
//Se transforman los pesos
MatrizPes[heuristica][aux[n][0]] = n;
for(int i=n ; i>1; i--){
if(aux[i-1][1] == aux[i][1])
MatrizPes[heuristica][aux[i-1][0]] =
MatrizPes[heuristica][aux[i][0]];
else if(aux[i-1][1] < aux[i][1])
MatrizPes[heuristica][aux[i-1][0]] = i-1;
else System.out.println("error al calcular el peso "+
": los pesos no se han ordenado bien");
}
}
}
38
public static void actualizaPesoAzar(String s)
{
int inferior, superior, aleatorio;
int aux[]= new int[Datos.getNumTareas()];
//Se rellena el vector para despues extraer los numero de dicho
// vector utilizando el azar no para obtener directamente el numero
//sino a traves de los indices, los cuales se escogeran al azar
inferior = 0;
superior = Datos.getNumTareas();
for(int i=0; i<=Datos.getNumTareas()-1; i++)
aux[i]=i+1;
if (s.equals("ID")){
for(int i=1; i<=Datos.getNumTareas(); i++){
aleatorio=Azar.nextInt(inferior, superior-1);
MatrizID[14][i] = aux[aleatorio];
aux[aleatorio]= aux[superior-1];
superior--;
}
} else if(s.equals("DI")){
for(int i=1; i<=Datos.getNumTareas(); i++){
aleatorio=Azar.nextInt(inferior, superior-1);
MatrizDI[14][i] = aux[aleatorio];
aux[aleatorio]= aux[superior-1];
superior--;
}
MatrizDI[14][Datos.getNumTareas()] = aux[0];
}
else System.out.println ("Error al leer parametro sentido en el
fichero opciones");
}
final static void calculoMatrizSuc()
//Cálculo de la matriz de
//sucesores totales
{
int MatrizSucAux[][];
int n=Datos.getNumTareas();
MatrizSuc = new int[n+1][n+1];
MatrizSucAux = new int[n+1][n+1];
int fila, columna, i, j, sumafila,aux,aux2;
//Inicializar la matriz MatrizSuc con MatrizSucI
for(fila=1 ;fila<=n ;fila++){
for(columna=1 ;columna<=n ;columna++)
MatrizSuc[fila][columna]=Datos.MatrizSucI[fila][columna];
}
//En la iteracion k se calcula el producto de la
//matriz se sucesores MatrizSuc por ella misma
sumafila=0;
aux2=1;
//Se ejecuta una nueva iteración si la suma de las diferencias
39
//entre los componentes de la iteración k i la k-1 (aux2)
//es igual a cero
while(aux2>0){
aux2=0;
for(fila=1 ;fila<=Datos.getNumTareas() ;fila++){
for (columna=1 ;columna<=Datos.getNumTareas() ;columna++){
i=1;
sumafila=0;
while (i <= Datos.getNumTareas()){
aux=MatrizSuc[fila][i]*MatrizSuc[i][columna];
sumafila=sumafila+aux;
i=i+1;
}
//Se cambian los componentes diferentes de 0
//por el valor 1
if(sumafila > 0)
sumafila=1;
if(sumafila < 0)
System.out.println("error al calcular la matriz de
sucesores totales");
//Se comprueba si algun componente de la matriz
// MatrizSuc ha cambiado respecto a la
//iteracion anterior
aux2=aux2+Math.abs((sumafilaMatrizSuc[fila][columna]));
MatrizSucAux[fila][columna]=sumafila;
}
}
// copiar la matriz auxliar en la matriz MatrizSuc
for(fila=1 ;fila<=Datos.getNumTareas() ;fila++){
for(columna=1 ;columna<=Datos.getNumTareas() ;columna++)
MatrizSuc[fila][columna]=MatrizSucAux[fila][columna];
}
}
}
// CONSTRUCCION DE LA MATRIZ DE PESOS ORIGINALES DE IZQUIERDA A DERECHA
final static void peso1ID()
{
int n=Datos.getNumTareas();
for (int tarea=1; tarea<=n; tarea++) {
MatrizID[1][tarea] = Datos.Tiempos[tarea];
}
}
final static void peso2ID(){
int n=Datos.getNumTareas();
for(int tarea=1; tarea<=n ; tarea++){
MatrizID[2][tarea] = Datos.ListaPredDI[tarea];
//El número de sucesores ID es el de predecesores DI
}
}
final static void peso3ID(){
40
int n=Datos.getNumTareas();
int peso3;
for (int tarea=1; tarea<=n; tarea++) {
peso3=0;
for (int sucesor=1; sucesor<=n ; sucesor++) {
if (MatrizSuc[tarea][sucesor] == 1)
peso3=peso3+1;
}
MatrizID[3][tarea]=peso3-1;
//la matriz de sucesores tambien incluye en la diagonal
//el valor 1, por lo tanto hay que restarselo
}
}
final static void peso4ID(){
int n=Datos.getNumTareas();
int peso4;
for (int tarea=1; tarea<=n ; tarea++) {
peso4=0;
for (int sucesor=1; sucesor<=n ; sucesor++) {
if (MatrizSuc[tarea][sucesor] == 1)
peso4=peso4+Datos.Tiempos[sucesor];
}
MatrizID[4][tarea]=peso4;
}
}
final static void peso5ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for(tarea=1; tarea<=n; tarea++)
MatrizID[5][tarea]=(100*(MatrizID[4][tarea])/
((MatrizID[3][tarea])+1));
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 5");
}
}
final static void peso6ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizID[6][tarea]=
(int)Math.ceil(((double)(MatrizID[4][tarea])/
(double)(CotasTC.CotaMaxTC)))-n-1;
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 6");
}
}
final static void peso7ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
41
for (tarea=1; tarea<=n ; tarea++)
MatrizID[7][tarea]=(100*(MatrizID[6][tarea]))/
(MatrizID[3][tarea]+1);
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 7");
}
}
final static void peso8ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++)
MatrizID[8][tarea]=(1000*(MatrizID[1][tarea]))/
(-MatrizID[6][tarea]);
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 8");
}
}
final static void peso9ID(){
int n=Datos.getNumTareas();
int tarea=1;
int peso9, predecesor;
try {
for (tarea=1; tarea<=n ; tarea++) {
peso9=0;
for ( predecesor=1; predecesor<=n ; predecesor++) {
if (MatrizSuc[predecesor][tarea] == 1)
peso9=peso9+Datos.Tiempos[predecesor];
}
MatrizID[9][tarea]=-(int)Math.ceil((double)peso9/
(double) CotasTC.CotaMaxTC);
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 9");
}
}
final static void peso10ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizID[10][tarea]=MatrizID[6][tarea]-MatrizID[9][tarea];
// +(-UB(i))-(-LB(i))
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 10");
}
}
final static void peso11ID(){
int n=Datos.getNumTareas();
int tarea=1;
42
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizID[11][tarea]=(100*(MatrizID[3][tarea])/
(-MatrizID[10][tarea]));
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 11");
}
}
final static void peso12ID(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizID[12][tarea] = MatrizID[1][tarea] +
MatrizID[3][tarea];
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 12");
}
}
final static void peso13ID(){
int n=Datos.getNumTareas();
int i,tarea, predecesor, aux;
//Se inicilizan los indices K&W los niveles se
//establecen hacia atras, del final al principio
for (i=1; i<=n ; i++)
MatrizID[13][i]=1;
aux=0;
while (aux==0) {
aux=1;
//En este caso se empieza por la ultima tarea para disminuir
//el numero de pasadas y asi aumentar la velocidad
for (tarea=n; tarea>0 ; tarea--) {
for( predecesor=1; predecesor<=n ; predecesor++) {
//Para todas las tareas que tengan un predecesor inmediato
if ((Datos.MatrizSucI[predecesor][tarea] == 1) &&
(tarea!=predecesor)){
//Como los niveles de calculan hacia atras, se
//utiliza la matriz de predecesores si la tarea
//tiene un predecesor inmediato con un nivel menor o
//igual que dicha tarea, aumentar el nivel del
//predecesor en 1
if(MatrizID[13][tarea]>=MatrizID[13][predecesor]){
MatrizID[13][predecesor]=MatrizID[13][tarea]+1;
aux=0;
}
}
}
}
}
}
43
// CONSTRUCCION DE LA MATRIZ DE PESOS ORIGINALES DE DERECHA A IZQUIERDA
final static void peso1DI(){
int n=Datos.getNumTareas();
for (int tarea=1; tarea<=n; tarea++) {
MatrizDI[1][tarea]= Datos.Tiempos[tarea];
//La fila , el numero 1, representa el indice de peso
}
}
final static void peso2DI(){
int n=Datos.getNumTareas();
for(int tarea=1; tarea<=n ; tarea++)
MatrizDI[2][tarea] = Datos.ListaPredID[tarea];
}
final static void peso3DI(){
int n=Datos.getNumTareas();
int peso3;
for (int tarea=1; tarea<=n; tarea++) {
peso3=0;
for (int sucesor=1; sucesor<=n ; sucesor++) {
if (MatrizSuc[sucesor][tarea] == 1)
peso3=peso3+1;
}
MatrizDI[3][tarea]=peso3-1;
//La matriz de sucesores tambien incluye en la diagonal
//el valor 1, por lo tanto hay que restarselo
}
}
final static void peso4DI(){
int n=Datos.getNumTareas();
int peso4;
for (int tarea=1; tarea<=n ; tarea++) {
peso4=0;
for (int sucesor=1; sucesor<=n ; sucesor++) {
if (MatrizSuc[sucesor][tarea] == 1)
peso4=peso4+Datos.Tiempos[sucesor];
}
MatrizDI[4][tarea]=peso4;
}
}
final static void peso5DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for(tarea=1; tarea<=n; tarea++) {
MatrizDI[5][tarea]=(100*(MatrizDI[4][tarea])/
((MatrizDI[3][tarea])+1));
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 5 DI");
44
}
}
final static void peso6DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[6][tarea]=
(int)Math.ceil(((double)(MatrizDI[4][tarea])/
(double)(CotasTC.CotaMaxTC)))-n-1;
//se ha de calcular en algun sitio una cota maxima
//del tiempo de ciclo
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 6 DI");
}
}
final static void peso7DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[7][tarea]=(100*(MatrizDI[6][tarea]))/
(MatrizDI[3][tarea]+1);
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 7
DI");
}
}
final static void peso8DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[8][tarea]=
(1000*(MatrizDI[1][tarea]))/(-MatrizDI[6][tarea]);
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 8
DI");
}
}
final static void peso9DI(){
int n=Datos.getNumTareas();
int tarea=1;
int peso9, predecesor;
try {
for (tarea=1; tarea<=n ; tarea++) {
peso9=0;
for ( predecesor=1; predecesor<=n ; predecesor++) {
if (MatrizSuc[tarea][predecesor] == 1)
peso9=peso9+Datos.Tiempos[predecesor];
}
45
MatrizDI[9][tarea]=
-(int)Math.ceil((double)peso9/(double)CotasTC.CotaMaxTC);
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 9
}
DI");
}
final static void peso10DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[10][tarea]=MatrizDI[6][tarea]-MatrizDI[9][tarea];
// +(-UB(i))-(-LB(i))
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 10
DI");
}
}
final static void peso11DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[11][tarea]=(100*(MatrizDI[3][tarea])/
(-MatrizDI[10][tarea]));
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 11");
}
}
final static void peso12DI(){
int n=Datos.getNumTareas();
int tarea=1;
try {
for (tarea=1; tarea<=n ; tarea++) {
MatrizDI[12][tarea] = MatrizDI[1][tarea] +
MatrizDI[3][tarea];
}
}
catch (ArithmeticException e){
System.out.println(tarea+" peso 12");
}
}
final static void peso13DI(){
int n=Datos.getNumTareas();
int i,tarea, predecesor, aux;
//Inicializamos los indices K&W los niveles se establecen
//hacia atras, del final al principio
for (i=1; i<=n ; i++)
MatrizDI[13][i]=1;
aux=0;
46
while (aux==0) {
aux=1;
//En este caso se empieza por la ultima tarea para disminuir
//el numero de pasadas y asi aumentar la velocidad
for (tarea=1 ; tarea <= n ; tarea++) {
for( predecesor=1; predecesor<=n ; predecesor++) {
if ((Datos.MatrizSucI[tarea][predecesor] == 1) &&
(tarea != predecesor) ){
if(MatrizDI[13][tarea]>=MatrizDI[13][predecesor]){
MatrizDI[13][predecesor]=MatrizDI[13][tarea]+1;
aux=0;
}
}
}
}
}
}
public static void actualizaPesos()
{
peso6ID();
peso7ID();
peso8ID();
peso9ID();
peso10ID();
peso11ID();
peso6DI();
peso7DI();
peso8DI();
peso9DI();
peso10DI();
peso11DI();
}
}
1.2.15 CotasTC
public class CotasTC
{
static int CotaMinTC;
static int CotaMaxTC;
public CotasTC(){
CotaMaxTC = Datos.TiempoTotal;
}
public void calculoCotasIniciales()
{
CotaMinTC = calculoMinTC();
calculoMaxTC();
}
public int calculoMinTC()
{
int tiempoMax = Datos.Tiempos[1];
47
int sumaTiempos = tiempoMax;
for(int i=2; i<=Datos.NumTareas ; i++){
sumaTiempos += Datos.Tiempos[i];
if(Datos.Tiempos[i]>tiempoMax)
tiempoMax = Datos.Tiempos[i];
}
if(tiempoMax <= (sumaTiempos/Datos.NumEstMax))
return (sumaTiempos/Datos.NumEstMax);
else
return tiempoMax;
}
public void calculoMaxTC()
{
int tareapos[] = new int[2];
Ristra ristra = new Ristra("ID");
NextTareaInicial next = new NextTareaInicial("ID");
for(int i=1; i<=Datos.NumTareas; i++){
tareapos = next.getTarea(1, ristra.ultimaT);
ristra.actualizaRistraT(tareapos[0]);
next.lista.actualizaListas(tareapos);
}
int Ristra[] = new int[Datos.NumTareas+1];
Ristra = ristra.getRistraT();
int TC2 = CotaMinTC;
int tacum, tasig, TCajust2, n2, TCnext;
int i, r;
int marca, cota2;
do{ //loop de tiempos de ciclo
tacum = 0; tasig = 0; TCajust2 = 0;
n2 = 1;
r = 1;
marca = 0;
cota2 = 1;
TCnext = 1000000000;
do{ //loop de r
i = Ristra[r];
tacum += Datos.Tiempos[i];
if(tacum > TC2){
if((tacum-Datos.Tiempos[i]) > TCajust2)
TCajust2 = tacum-Datos.Tiempos[i];
if(tacum < TCnext)
TCnext = tacum;
tasig = tasig + tacum - Datos.Tiempos[i];
tacum = Datos.Tiempos[i];
n2 += 1;
if((n2-1+(int)Math.floor((double)(Datos.TiempoTotaltasig)/TC2)) > Datos.NumEstMin)
cota2 = 0;
}
if(r==Datos.NumTareas)
48
marca = 1;
r++;
} while((r<=Datos.NumTareas) && (n2<=Datos.NumEstMin) &&
(cota2>0));
if(tacum>TCajust2) {TCajust2 = tacum;}
if(TC2 == Datos.TiempoTotal) {TCajust2 = TC2;}
if(n2 > Datos.NumEstMin){
TC2 = TCnext;
} else if(n2 == Datos.NumEstMin){
if(marca == 1){
if(TCajust2<CotaMaxTC)
CotaMaxTC = TCajust2;
TC2 = Datos.TiempoTotal+1;
} else if(marca == 0){
if((Datos.TiempoTotal-tasig)<=TC2){
if((Datos.TiempoTotal-tasig)>TCajust2)
TCajust2 = Datos.TiempoTotal-tasig;
if(TCajust2<CotasTC.CotaMaxTC)
CotaMaxTC = TCajust2;
TC2 = Datos.TiempoTotal+1;
} else if((Datos.TiempoTotal-tasig)>TC2)
TC2 = TCnext;
}
} else if(n2<Datos.NumEstMin){
if(marca == 1){
TC2 = Datos.TiempoTotal+1;
CotaMaxTC = TCajust2;
} else if(marca == 0){
if((n2-1+(int)Math.floor((double)(Datos.TiempoTotaltasig)/TC2))
> Datos.NumEstMin)
TC2 = TCnext;
else if((n2-1+(int)Math.floor(
(double)(Datos.TiempoTotal-tasig)/TC2))
<= Datos.NumEstMin) {
TC2 = Datos.TiempoTotal+1;
CotaMaxTC = Datos.TiempoTotal;
}
}
}
} while(TC2 <= Datos.TiempoTotal);
}
}
1.2.16 CotaSALBPE
public class CotaSalbpE
{
int Cota1;
int Cota2;
int Cota3;
49
int Cota4;
int [] TCicloMin;
//En este vector se guarda para cada numero de
//estaciones(SALBP-2)su cota minima de tiempo de
//ciclo necesaria para empezar en el mayor
//tiempo de ciclo posible la cota 4
static int CotaSalbpE;
public CotaSalbpE()
{
TCicloMin = new int [Datos.NumEstMax-Datos.NumEstMin+1];
CalculoCota1();
System.out.println("cota1 : "+Cota1);
CalculoCota2();
System.out.println("cota2 : "+Cota2);
CalculoCota3();
System.out.println("cota3 : "+Cota3);
CalculoCota4();
System.out.println("cota4 : "+Cota4);
CotaSalbpE = maximo(Cota1, Cota2, Cota3, Cota4);
System.out.println("CotaSalbpE : "+ CotaSalbpE);
}
public void CalculoCota1()
{
Cota1 = Datos.TiempoTotal;
int aux;
for (int i=0; i <= (Datos.NumEstMax-Datos.NumEstMin); i++){
aux=Datos.TiempoTotal/(Datos.NumEstMin+i);
if (aux >= Datos.TiempoMax)
TCicloMin[i] = aux;
else TCicloMin[i] = Datos.TiempoMax;
}
}
public void CalculoCota2()
{
Cota2 = Datos.TiempoMax * Datos.NumEstMin;
}
public void CalculoCota3()
{
int Cota3Aux,k, suma, sumaAux, estaciones;
int n = Datos.getNumTareas();
int [][] auxTiempos = new int [n+1][2];
int [][] auxTiempos2 = new int [n+1][2];
//Se copian los tiempos en en vector auxTiempos ordenados de menor
//a mayor y comenzando por la posicion
for (int j=1 ; j <= n; j++){
auxTiempos[j][0]= j;
auxTiempos[j][1]= Datos.Tiempos[j];
}
//Se ordena el vector por pesos
auxTiempos = MatrizPesos.Quicksort(auxTiempos, 0, n-1);
//Se invierte el orden para que la tareas esten en orden
//decreciente de tiempos
50
for (int t=1 ; t <= n; t++){
auxTiempos2[t][0] = auxTiempos[n-t+1][0];
auxTiempos2[t][1] = auxTiempos[n-t+1][1];
}
Cota3=1000000000;
for (estaciones = Datos.NumEstMin;
estaciones <= Datos.NumEstMax;
estaciones++){
k=1;
suma = 0;
while ( k <= (int) (Math.floor((double)((n-1)/estaciones)))){
//Ver sumatorio libro Scholl pag 56
sumaAux=0;
for (int i = 0; i<=k; i++)
sumaAux = sumaAux + auxTiempos2[(k*estaciones+1-i)][1];
if (sumaAux > suma)
suma = sumaAux;
k++;
}
if ( suma*estaciones < Cota3)
Cota3 = suma*estaciones;
if (suma > TCicloMin[estaciones-Datos.NumEstMin])
TCicloMin[estaciones-Datos.NumEstMin] = suma;
}
}
public void CalculoCota4()
{
int estaciones;
int tiempoCiclo;
int tiempoAcum;
int tarea;
boolean finTareas = false;
boolean finTiempoCiclo = false;
int [] tiempoPredecesores = new int[Datos.NumTareas+1];
int [] EarliestStation = new int[Datos.NumTareas+1];
int [] LatestStation = new int[Datos.NumTareas+1];
//Se calcula el numerador de la formula de la EarliestStation
//ya que es fijo para todos los tiempos de ciclo
for (tarea=1; tarea <= Datos.NumTareas; tarea++) {
tiempoAcum=0;
for (int predecesor=1;predecesor<=Datos.NumTareas
;predecesor++){
if (MatrizPesos.MatrizSuc[predecesor][tarea] == 1)
tiempoAcum=tiempoAcum+Datos.Tiempos[predecesor];
}
tiempoPredecesores[tarea] = tiempoAcum;
}
Cota4=1000000000;
for (estaciones = Datos.NumEstMin;
estaciones <= Datos.NumEstMax;
estaciones++){
//Se inicializa el tiempo de ciclo
tiempoCiclo = TCicloMin[estaciones-Datos.NumEstMin];
51
//Se calcula la EarliestStation y la LatestStation
//para cada tarea
while (tarea <= Datos.NumTareas){
EarliestStation[tarea] =(int)Math.ceil((double)
tiempoPredecesores[tarea]/ (double) tiempoCiclo);
LatestStation[tarea] = Datos.NumTareas+1(int)Math.ceil(
((double)(MatrizPesos.MatrizID[4][tarea])/
(double)(tiempoCiclo)));
if (EarliestStation[tarea] > LatestStation[tarea]){
tiempoCiclo = tiempoCiclo+1;
tarea = 1;
}
else tarea=tarea+1;
}
if ( tiempoCiclo*estaciones < Cota4)
Cota4 = tiempoCiclo*estaciones;
}
}
public int maximo(int cota1,int cota2, int cota3, int cota4)
{
int maximo;
maximo = Math.max(cota1, cota2);
maximo = Math.max(maximo, cota3);
maximo = Math.max(maximo, cota4);
return maximo;
}
}
1.2.17 Azar
import java.util.*;
public class Azar extends Random
{
static Random aleatorio;
public static void semilla()
{
aleatorio = new Random();
}
public static int nextInt (int inferior, int superior)
{
if (superior <= inferior-1)
System.out.println("error al utilizar el metodo nextInt
de la clase Azar: inferior > que superior");
int i;
i = aleatorio.nextInt();
i = inferior + (Math.abs(i)) % (superior- inferior +1);
return i;
}
}
52
1.2.18 MejorSolucion
public class MejorSolucion
{
static int OBJ;
static int N;
static int TC;
static int Ristra[];
static String sentidoHormiga;
static String sentidoEval;
static int OBJInicial;
public static void inicializa()
{
OBJ = 1000000000;
N = 1000000000;
TC = 1000000000;
Ristra = new int[Datos.NumTareas+1];
}
}
1.2.19 Cronometro
import java.util.*;
public class Cronometro
{
Calendar i, f;
int ihoras, iminutos, isegundos;
int fhoras, fminutos, fsegundos;
public Cronometro()
{
}
public void inicio()
{
i = Calendar.getInstance();
ihoras = i.get(Calendar.HOUR_OF_DAY);
iminutos = i.get(Calendar.MINUTE);
isegundos = i.get(Calendar.SECOND);
}
public void fin()
{
f = Calendar.getInstance();
fhoras = f.get(Calendar.HOUR_OF_DAY);
fminutos = f.get(Calendar.MINUTE);
fsegundos = f.get(Calendar.SECOND);
}
53
public int tiempo() //Devuelve el tiempo en segundos
{
int tiempo = -1;
if(f.get(Calendar.DAY_OF_YEAR) == i.get(Calendar.DAY_OF_YEAR)){
tiempo = (fhoras - ihoras)*3600 + (fminutos - iminutos)*60 +
(fsegundos - isegundos);
} else if((f.get(Calendar.DAY_OF_YEAR) –
i.get(Calendar.DAY_OF_YEAR)) == 1){
tiempo = (fhoras + (24-ihoras))*3600 + (fminutos - iminutos)
*60 + (fsegundos - isegundos);
}
return tiempo;
}
}
1.2.20 Salida
import
import
import
import
java.io.*;
java.math.*;
java.util.*;
java.text.*;
public class Salida
{
String Fichero;
PrintWriter outbr, tablabr, distrbr;
static int numSol; //Número de soluciones evaluadas
int OBJInicial;
public Salida(String f)
{
try{
//Fichero de salida con la evolución del porblema
outbr = new PrintWriter(new FileWriter(
"Evol_"+f+"-"+Datos.NumEstMin+""+Datos.NumEstMax+".dat", true));
//Tabla de resultados
tablabr = new PrintWriter(new FileWriter(
"Tabla_"+f+"-"+Datos.NumEstMin+""+Datos.NumEstMax+".dat", true));
//Distribución de tareas: solución final encontrada
distrbr = new PrintWriter(new FileWriter(
"Distr_"+f+"-"+Datos.NumEstMin+""+Datos.NumEstMax+".dat", true));
numSol = 0;
} catch(FileNotFoundException e) {
System.out.println("File Not Found");
54
} catch(IOException e){
System.out.println("IO Exception");
}
}
public void acumulaSalida(Subcolonia sub)
{
outbr.print(MejorSolucion.OBJ+"\t");
int mejorSub = sub.PaqueteOBJ[0];
for(int ant=1; ant<=13; ant++){
if(sub.PaqueteOBJ[ant] < mejorSub)
mejorSub = sub.PaqueteOBJ[ant];
}
outbr.print(mejorSub+"\t");
double desviacion=0.0, media=0.0;
for(int ant=0; ant<=13; ant++)
media += (double)sub.PaqueteOBJ[ant];
media = media/14;
for(int ant=0; ant<=13; ant++)
desviacion += Math.pow((double)sub.PaqueteOBJ[ant]-media,2.0);
desviacion = Math.pow(desviacion/13, 0.5);
outbr.println(desviacion);
}
public void tablaSalida(int numSubColonia, int tiempo)
{
NumberFormat N = NumberFormat.getInstance();
N.setMinimumFractionDigits(3);
N.setMaximumFractionDigits(3);
tablabr.print(Datos.OBJOptima+"$"); //OBJ óptima del juego de datos
tablabr.print(OBJInicial+"$");
tablabr.print(MejorSolucion.OBJ+"$");
tablabr.print(MejorSolucion.N+"$");
tablabr.print(MejorSolucion.TC+"$");
double discrepancia;
discrepancia = (((double)(MejorSolucion.OBJ –
Datos.OBJOptima))/(double)(Datos.OBJOptima))*100.0;
tablabr.print(N.format(discrepancia)+"$");
//Discrepancia relativa a la solución óptima
double mejora;
mejora = (((double)(OBJInicial –
MejorSolucion.OBJ))/(double)(OBJInicial))*100.0;
tablabr.print(N.format(mejora)+"$");
tablabr.print(numSubColonia+"$");
tablabr.print(numSol+"$");
if(tiempo == 0)
tablabr.println("1");
55
if(tiempo != 0)
tablabr.println(tiempo);
}
public void rellenaBlancos(int ultima)
{
for(int i=(ultima+1); i<=Opciones.limitacion; i++)
outbr.println();
}
public void estacionesSalida()
{
if(MejorSolucion.sentidoHormiga.equals("DI"))
invertirRistra();
if(MejorSolucion.sentidoEval.equals(MejorSolucion.sentidoHormiga))
evaluacionNormal();
else
evaluacionMarcas();
}
public void invertirRistra()
{
int aux;
for(int r=1; r<=(Datos.NumTareas/2); r++){
aux = MejorSolucion.Ristra[r];
MejorSolucion.Ristra[r] =
MejorSolucion.Ristra[Datos.NumTareas-r+1];
MejorSolucion.Ristra[Datos.NumTareas-r+1] = aux;
}
}
public void evaluacionNormal()
{
int n = 1;
int tacum = 0;
int cont = 0;
int tmuerto[] = new int[MejorSolucion.N+1];
distrbr.println("@inicio");
for(int r=1; r<=Datos.NumTareas; r++){
tacum += Datos.Tiempos[MejorSolucion.Ristra[r]];
if(tacum > MejorSolucion.TC){
tmuerto[n] = MejorSolucion.TC -tacum +
Datos.Tiempos[MejorSolucion.Ristra[r]];
tacum = Datos.Tiempos[MejorSolucion.Ristra[r]];
n++;
}
}
56
tmuerto[n] = MejorSolucion.TC - tacum;
n=1;
distrbr.println("Estacion 1 (Tiempo muerto= "+tmuerto[1]+")");
tacum = 0;
for(int r=1; r<=Datos.NumTareas; r++){
tacum += Datos.Tiempos[MejorSolucion.Ristra[r]];
if(tacum > MejorSolucion.TC){
tacum = Datos.Tiempos[MejorSolucion.Ristra[r]];
n++;
distrbr.println();
distrbr.println();
distrbr.println("Estacion "+n+
" (Tiempo muerto= "+tmuerto[n]+")");
cont = 0;
}
distrbr.print("\t"+MejorSolucion.Ristra[r]);
cont++;
if((cont == 10) && r<Datos.NumTareas){
if(tacum+Datos.Tiempos[MejorSolucion.Ristra[r+1]] <=
MejorSolucion.TC){
cont = 0;
distrbr.println();
}
}
}
distrbr.println();
}
public void evaluacionMarcas()
{
int marcas[] = new int[MejorSolucion.N+1];
//marcas[n] es la posicion donde acaba la estacion n
int n = MejorSolucion.N;
int tacum = 0;
int cont = 0;
int tmuerto[] = new int[MejorSolucion.N+1];
distrbr.println("@inicio");
for(int r=Datos.NumTareas; r>=1; r--){
tacum += Datos.Tiempos[MejorSolucion.Ristra[r]];
if(tacum > MejorSolucion.TC){
tmuerto[n] = MejorSolucion.TC -tacum +
Datos.Tiempos[MejorSolucion.Ristra[r]];
tacum = Datos.Tiempos[MejorSolucion.Ristra[r]];
marcas[n-1] = r;
n--;
}
}
tmuerto[n] = MejorSolucion.TC - tacum;
marcas[0] = 0;
marcas[MejorSolucion.N] = Datos.NumTareas;
57
for(n=1; n<=MejorSolucion.N; n++){
cont = 0;
distrbr.println();
distrbr.println("Estacion "+n+
" (Tiempo muerto= "+tmuerto[n]+")");
for(int r=marcas[n-1]+1; r<=marcas[n]; r++){
distrbr.print("\t"+MejorSolucion.Ristra[r]);
cont++;
if((cont == 10) && r != marcas[n]){
cont = 0;
distrbr.println();
}
}
distrbr.println();
}
}
public void escribeSalida()
{
outbr.close();
tablabr.close();
distrbr.close();
}
}
58
CAPÍTULO 2: ALGORITMO DE LAS HORMIGAS CON
MEJORA LOCAL
59
2.1 DESCRIPCIÓN DEL PROGRAMA
Utiliza todas las clases del programa del apartado 1, añadiendo la clase MejoraLocal y
reemplazando la clase Subcolonia para que sea capaz de llamar a la clase MejoraLocal
cuando sea necesario.
60
2.2 LISTADO DE LOS OBJETOS
2.2.1 MejoraLocal
public class MejoraLocal
{
Ristra ristra;
int numRistras;
int r;
static int mejorOBJ;
int mejorTC;
int mejorN;
String sentido;
String mejorSentidoEval;
public MejoraLocal(Ristra ris, String s, int obj)
{
ristra = ris;
r=0;
mejorOBJ = obj;
sentido = s;
}
public void inicia(int numRistras, String sentidoMejora)
{
if(sentidoMejora.equals("DI")){
invierte();
if(sentido.equals("ID"))
sentido = "DI";
else
sentido = "ID";
}
for(int cont=1; cont<=numRistras; cont++){
intercambia();
compara(sentidoMejora);
}
if(sentidoMejora.equals("DI"))
invierte();
}
public void intercambia()
{
int aux;
do{
if(r==Datos.NumTareas-1)
r=0;
r++;
} while(factibilidad() == false);
aux = ristra.RistraT[r];
ristra.RistraT[r] = ristra.RistraT[r+1];
ristra.RistraT[r+1] = aux;
}
61
public boolean factibilidad()
{
//Factible si r+1 no es sucesor de r
if((sentido.equals("ID")) &&
(MatrizPesos.MatrizSuc[ristra.RistraT[r]][ristra.RistraT[r+1]]
== 1))
return false;
else if((sentido.equals("DI")) &&
(MatrizPesos.MatrizSuc[ristra.RistraT[r+1]][ristra.RistraT[r]]
== 1))
return false;
else
return true;
}
public void compara(String sentidoMejora)
{
ristra.evaluacionRistra();
int aux;
if(ristra.eval.getObj() > mejorOBJ){
aux = ristra.RistraT[r];
ristra.RistraT[r] = ristra.RistraT[r+1];
ristra.RistraT[r+1] = aux;
}
if(ristra.eval.getObj() < mejorOBJ){
mejorOBJ = ristra.eval.getObj();
mejorN = ristra.eval.getNumEst();
mejorTC = ristra.eval.getTC();
if(sentidoMejora.equals("ID"))
mejorSentidoEval = ristra.eval.mejorSentido;
else {
if(ristra.eval.mejorSentido.equals("ID"))
mejorSentidoEval = "DI";
else
mejorSentidoEval = "ID";
}
}
}
public void invierte()
{
int aux;
for(int r=1; r<=(Datos.NumTareas/2); r++){
aux = ristra.RistraT[r];
ristra.RistraT[r] = ristra.RistraT[Datos.NumTareas-r+1];
ristra.RistraT[Datos.NumTareas-r+1] = aux;
}
}
}
62
2.2.2 Subcolonia
public class Subcolonia
{
int tamano; //1 ó 14
String Sentido;
Hormiga ant;
int numAnt = 0;
double b;
boolean marcaMejor = false; //true si la mejor hormiga mejora
//o iguala la OBJ global
boolean marcaMejorSolo = false; //true si la mejor hormiga mejora
//la OBJ global
boolean mejorado, igualado;
static int mejorsubOBJ;
static int maxsubTC;
MejoraLocal mejora;
static int numSubcolonia;
static int numMejora;
//nº de mejora global
boolean aplicaMejora;
//true si se debe aplicar una mejora local
static int numSubMejora; //nº mejora dentro de la subcolonia
boolean lasPrimeras10;
//Controla la mejora en las 10 primeras
//subcolonias de hormigas
//Atributos para la recolección de información
int PaqueteRistras[][];
int PaqueteOBJ[];
int PaqueteN[];
int PaqueteTC[];
int auxRistra[];
int auxOBJ;
int numSub;
public Subcolonia(int t, String s, int n)
{
tamano = t;
Sentido = s;
PaqueteOBJ = new int[14];
PaqueteRistras = new int[14][Datos.NumTareas+1];
PaqueteN = new int[14];
PaqueteTC = new int[14];
MatrizPesos.actualizaPesoAzar(Sentido);
mejorsubOBJ = 2000000000;
maxsubTC = Datos.TiempoTotal;
rastretes = Rastros.Tareas;
numSub = n;
igualado = false;
mejorado = false;
aplicaMejora = false;
lasPrimeras10 = true;
63
}
public void lanzaHormigas()
{
for(int i=1; i<=14; i++){
ant = new Hormiga(i, Sentido, Opciones.tipoHormiga);
ant.construirSolucion();
recogeInformacion();
comparaInformacion();
numAnt++;
}
numSubcolonia++;
if(aplicaMejora == true)
numSubMejora++;
}
public void recogeInformacion()
{
for(int i=1; i<=Datos.NumTareas; i++)
PaqueteRistras[numAnt][i] = ant.ristra.RistraT[i];
PaqueteOBJ[numAnt] = ant.ristra.eval.getObj();
PaqueteN[numAnt] = ant.ristra.eval.getNumEst();
PaqueteTC[numAnt] = ant.ristra.eval.getTC();
}
public void comparaInformacion()
{
if((numSubcolonia <=10 || (numSubcolonia%30 == 0)) &&
lasPrimeras10 == true){
mejoraLocal("ID");
lasPrimeras10 = false;
}
if(PaqueteOBJ[numAnt] < MejorSolucion.OBJ){
MejorSolucion.OBJ = PaqueteOBJ[numAnt];
MejorSolucion.N = PaqueteN[numAnt];
MejorSolucion.TC = PaqueteTC[numAnt];
for(int i=1; i<=Datos.NumTareas; i++)
MejorSolucion.Ristra[i] = PaqueteRistras[numAnt][i];
MejorSolucion.sentidoHormiga = Sentido;
MejorSolucion.sentidoEval = ant.ristra.eval.mejorSentido;
marcaMejorSolo = true;
mejorado = true;
}
if(PaqueteOBJ[numAnt] <= MejorSolucion.OBJ){
marcaMejor = true;
igualado = true;
if((numMejora%2) != 0)
mejoraLocal("ID");
else
mejoraLocal("DI");
numMejora++;
64
aplicaMejora = true;
}
if(PaqueteOBJ[numAnt] < MejorSolucion.OBJ){
MejorSolucion.OBJ = PaqueteOBJ[numAnt];
MejorSolucion.N = PaqueteN[numAnt];
MejorSolucion.TC = PaqueteTC[numAnt];
for(int i=1; i<=Datos.NumTareas; i++)
MejorSolucion.Ristra[i] = PaqueteRistras[numAnt][i];
MejorSolucion.sentidoEval = mejora.mejorSentidoEval;
marcaMejorSolo = true;
mejorado = true;
}
}
public void actualizaRastros()
{
evaporaRastros();
actualizaTareas();
}
public void actualizaTareas()
{
double unidadRastro[] = new double[15];
double sumaOBJ = 0;
int tareaA, tareaB;
if(tamano == 14){
//Dejan rastro todas las hormigas
for(int i=0; i<=13; i++){
b = 100.0*(((double)(PaqueteOBJ[i])(double)(Datos.TiempoTotal))/
((double)(Datos.TiempoTotal)));
unidadRastro[i] = 1/(Math.pow(b, 1.0));
}
for(int contAnt = 0; contAnt<=13; contAnt++){
tareaA = 0;
for(int r=1; r<=Datos.NumTareas; r++){
//r = posición en la ristra
tareaB = PaqueteRistras[contAnt][r];
Rastros.Tareas[tareaA][tareaB] +=
unidadRastro[contAnt];
tareaA = tareaB;
}
}
}
//Sólo dejan rastro las mejores hormigas
int minOBJ[] = new int[14]; //Contiene las hormigas con mejor OBJ
int limAnt = 0;
minOBJ[0] = 0;
for(int contAnt=1; contAnt<=13; contAnt++){
65
if(PaqueteOBJ[contAnt]<PaqueteOBJ[minOBJ[0]]){
minOBJ[0] = contAnt;
limAnt = 0;
} else if(PaqueteOBJ[contAnt]==PaqueteOBJ[minOBJ[0]]){
minOBJ[limAnt+1] = contAnt;
limAnt++;
}
}
if(marcaMejor == true){ //La mejor hormiga mejora
//o iguala la OBJ global
for(int i=0; i<=limAnt; i++){
tareaA = 0;
for(int r=1; r<=Datos.NumTareas; r++){
tareaB = PaqueteRistras[minOBJ[i]][r];
double maxRastro = 0.0;
for(int j=0; j<=Datos.NumTareas; j++){
//Se busca el máximo rastro
if(Rastros.Tareas[tareaA][j] > maxRastro)
maxRastro = Rastros.Tareas[tareaA][j];
}
//Evaporación extra
if(marcaMejorSolo == true){
for(int j=0; j<=Datos.NumTareas; j++){
Rastros.Tareas[tareaA][j] *=
(1-Opciones.evaporacionExtra);
}
maxRastro *= Opciones.rastroExtra;
if(numSubcolonia == 1)
maxRastro *=Opciones.tamano;
}
Rastros.Tareas[tareaA][tareaB] = maxRastro;
tareaA = tareaB;
}
if(marcaMejorSolo == true){
double maxRastro = 0.0;
for(int j=0; j<=Datos.NumTareas; j++){
//Se busca el máximo rastro
if(Rastros.Tareas[tareaA][j] > maxRastro)
maxRastro = Rastros.Tareas[tareaA][j];
}
//Evaporación extra de la fila de la
//última tarea de la ristra
for(int pos=0; pos<=Datos.NumTareas; pos++){
Rastros.Tareas[tareaA][pos] *=
(1-Opciones.evaporacionExtra);
}
maxRastro *= Opciones.rastroExtra;
if(numSubcolonia == 1)
maxRastro *=Opciones.tamano;
Rastros.Tareas[tareaA][0] = maxRastro;
marcaMejorSolo = false; //Ya no entra más, sólo evapora
//la primera hormiga
}
}
66
}
for(int i=0; i<=limAnt; i++){
b = 100.0*(((double)(PaqueteOBJ[minOBJ[i]])((double)(CotaSalbpE.CotaSalbpE)))/
((double)(CotaSalbpE.CotaSalbpE)));
double unidad = 1/(Math.pow(b, 2.0));
tareaA = 0;
for(int r=1; r<=Datos.NumTareas; r++){
tareaB = PaqueteRistras[minOBJ[i]][r];
Rastros.Tareas[tareaA][tareaB] += unidad;
tareaA = tareaB;
}
Rastros.Tareas[tareaA][0] += unidad; //Rastro entre la última
//tarea de la ristra y la
//tarea 0 en sentido
//contrario
}
}
public void evaporaRastros()
{
for(int i=0; i<=Datos.NumTareas; i++){
for(int j=0; j<=Datos.NumTareas; j++){
Rastros.Tareas[i][j] = Rastros.Tareas[i][j]*
(1.0-Opciones.evaporacion);
}
}
}
public void mejoraLocal(String sentidoMejora)
{
if(numSubcolonia >= 0 && numSubMejora <=80){
Hormiga antMejora =
new Hormiga(1, Sentido, Opciones.tipoHormiga);
for(int i=1; i<=Datos.NumTareas; i++)
antMejora.ristra.RistraT[i] = PaqueteRistras[numAnt][i];
mejora = new
MejoraLocal(antMejora.ristra, Sentido, PaqueteOBJ[numAnt]);
mejora.inicia(2000, sentidoMejora);
if(mejora.mejorOBJ < PaqueteOBJ[numAnt]){
PaqueteOBJ[numAnt] = mejora.mejorOBJ;
PaqueteN[numAnt] = mejora.mejorN;
PaqueteTC[numAnt] = mejora.mejorTC;
for(int i=1; i<=Datos.NumTareas; i++)
PaqueteRistras[numAnt][i] = mejora.ristra.RistraT[i];
}
67
if(mejora.mejorOBJ < MejorSolucion.OBJ){
System.out.println();
System.out.println("Mejora con OBJ= "+
mejora.mejorOBJ+" con sentido "+numMejora);
}
}
}
}
68
CAPÍTULO 3: MULTI-START
69
3.1 DESCRIPCIÓN DEL PROGRAMA
Se aprovechan objetos de los dos capítulos anteriores:
•
Azar
•
CotaSalbpE
•
CotaTC
•
Cronometro
•
Datos
•
Evaluación
•
Listas
•
MatrizPesos
•
MejoraLocal
•
MejorSolucion
•
NextTarea
•
Ristra
•
Salida
Se reemplazan Principal y SolucionInicial para adaptarlos al funcionamiento del Multi-Start.
70
3.2 LISTADO DE OBJETOS
3.2.1 Principal
public class Principal
{
public static void main(String args[])
{
String sentido;
int numRistras;
int subNum;
Cronometro cr = new Cronometro();
cr.inicio(); //Puesta a cero del cronómetro
Azar.semilla();
Datos datos = new Datos(args);
datos.importaDatos();
Salida salida = new Salida(args[6]);
SolucionInicial solini;
MatrizPesos.inicializa();
CotaSalbpE cota = new CotaSalbpE();
MejorSolucion.inicializa();
MejoraLocal mejora;
numRistras = 0;
cr.fin();
for(int numIni=1; !MejorSolucion.optimo &&
cr.tiempo()<=(Integer.valueOf(args[4].trim()).intValue());
numIni++){
if((numIni%2)!=0)
sentido = "ID";
else
sentido = "DI";
MatrizPesos.actualizaPesoAzar(sentido);
solini = new SolucionInicial(sentido);
solini.creaSolucion(14);
mejora = new MejoraLocal(solini.ristra, sentido);
int numRis=Integer.valueOf(args[5].trim()).intValue();
subNum = mejora.inicia(numRis);
numRistras += subNum;
cr.fin();
}
System.out.println();
System.out.println();
System.out.println("MEJOR SOLUCION");
System.out.println("OBJ= "+MejorSolucion.OBJ);
System.out.println("N = "+MejorSolucion.N);
System.out.println("TC = "+MejorSolucion.TC);
cr.fin();
System.out.println();
System.out.println("Tiempo de ejecucion: "+cr.tiempo()+" s");
71
salida.tablaSalida(numRistras, cr.tiempo());
salida.estacionesSalida();
salida.escribeSalida();
}
}
3.2.2 SolucionInicial
public class SolucionInicial
{
String sentido;
int tareapos[];
Ristra ristra;
NextTarea next;
public SolucionInicial(String sentido)
{
this.sentido = sentido;
}
public void creaSolucion(int h)
{
tareapos = new int[2];
ristra = new Ristra(sentido);
next = new NextTarea(sentido);
for(int i=1; i<=Datos.NumTareas; i++){
tareapos = next.getTarea(h, ristra.ultimaT);
ristra.actualizaRistraT(tareapos[0]);
next.lista.actualizaListas(tareapos);
}
}
}
Descargar