package buffalo.twoTasksAnalysis; import java.util.Vector; import buffalo.dataStructures.*; import buffalo.transportNetwork.*; /** Ensemble de méthodes qui permettent d'effectuer sur un graphe partiel à deux <CODE>tâches</CODE> une réduction polynomiale vers un problème de coupe minimale dans un réseau de Transport. On se retrouve à la dernière étape avec un <CODE>TransportNetwork</CODE> sur lequel il n'est nécessaire que de faire un <CODE>runFlow()</CODE>. */ public class TwoTasksAnalysis { /** Si <CODE>print</CODE>, une trace de l'algorithme est affichée sur <CODE>stdout</CODE>. */ public static boolean print = false; /*-------------------------------------------------------*/ /** Retourne une condition nécessaire de non-blocage entre <CODE>firstBuffer</CODE> et <CODE>secondBuffer</CODE> de même orientation. Il trace les contraintes de buffer vide de <CODE>secondBuffer</CODE> et cherche la dimension à donner à <CODE>secondBuffer</CODE> pour ne pas bloquer. */ public static BufferPairExpression getOneWayBufferPairExpression (Buffer firstBuffer, Buffer secondBuffer) { TraceTracer.traceEmptyBufferConstraints(secondBuffer); BufferPairExpression myExpression = new BufferPairExpression(firstBuffer, secondBuffer); BufferPairCondition myCondition = getOneWayBufferPairCondition(firstBuffer); myExpression.addBufferPairCondition(myCondition); return myExpression; } /*-------------------------------------------------------*/ /** Retourne une condition nécessaire de non-blocage entre <CODE>firstBuffer</CODE> et <CODE>secondBuffer</CODE>. Les arcs des <CODE>opérations</CODE> liées à <CODE>secondBuffer</CODE> sont supposés déjà tracés. */ private static BufferPairCondition getOneWayBufferPairCondition (Buffer firstBuffer) { firstBuffer.setSize(1); TraceTracer.traceFullBufferConstraints(firstBuffer); TwoTasksCircuit myCircuit; myCircuit = TraceTracer.findTwoTasksCircuit (firstBuffer.getWritingTask(), firstBuffer.getReadingTask()); while(myCircuit != null) { adjustSizeOf(firstBuffer, myCircuit); TraceTracer.traceFullBufferConstraints(firstBuffer); myCircuit = TraceTracer.findTwoTasksCircuit (firstBuffer.getWritingTask(), firstBuffer.getReadingTask()); } return new BufferPairCondition(firstBuffer.getSize(), 1); } /*-------------------------------------------------------*/ /** Ajuste la capacité de <CODE>myBuffer</CODE> de sorte à briser <CODE>myCircuit</CODE>. */ private static void adjustSizeOf(Buffer myBuffer, TwoTasksCircuit myCircuit) { int formerSize = myBuffer.getSize(); Operation myOperation; int n_o_p; if (myCircuit.getNorthWest().getBuffer() == myBuffer) { myOperation = myCircuit.getNorthEast(); n_o_p = myCircuit.getNorthWest().getN(); } else { myOperation = myCircuit.getSouthEast(); n_o_p = myCircuit.getSouthWest().getN(); } while(myOperation.getBuffer()!=myBuffer) { myOperation = myOperation.getPreviousFixedOperation(); } int n_o_r = myOperation.getN(); myBuffer.setSize(formerSize + n_o_r - n_o_p + 1); } /*-------------------------------------------------------*/ /** Retourne une disjonction de conditions suffisantes de non-blocage entre <CODE>northBuffer</CODE> et <CODE>southBuffer</CODE>. */ public static BufferPairExpression getTwoWaysBufferPairExpression (Buffer firstBuffer, Buffer secondBuffer) { secondBuffer.setSize(1); BufferPairExpression myExpression = new BufferPairExpression (firstBuffer, secondBuffer); BufferPairCondition myCondition; do { TraceTracer.traceFullBufferConstraints(secondBuffer); myCondition = getOneWayBufferPairCondition (firstBuffer); myCondition.setSecondSize(secondBuffer.getSize()); myExpression.addBufferPairCondition(myCondition); secondBuffer.setSize(secondBuffer.getSize()+1); TraceTracer.removeAllConstraints(firstBuffer); TraceTracer.removeAllConstraints(secondBuffer); } while(myCondition.getFirstSize()!=1); return myExpression; } /*-------------------------------------------------------*/ /** Retourne un <CODE>BufferPairCollection</CODE> contenant les conditions nécessaires et suffisantes de non-blocage dans le graphe partiel induit par <CODE>task1</CODE> et <CODE>task2</CODE> sous forme canonique disjonctive. */ public static BufferPairCollection getBufferCollectionVee (Task task1, Task task2) { TwoTasksCircuit empty = emptyBufferCircuit(task1, task2); if (empty==null) { BufferPairCollection myCollection = new BufferPairCollection(task1, task2); Vector oneWayBuffers = myCollection.getOneWayBuffers(); Vector twoWaysBuffers = myCollection.getTwoWaysBuffers(); Buffer firstBuffer; Buffer secondBuffer; BufferPairExpression myExpression; int sizeOfVector = oneWayBuffers.size(); for(int i = 0 ; i < sizeOfVector - 1 ; i ++) { firstBuffer = (Buffer)oneWayBuffers.get(i); i++; secondBuffer = (Buffer)oneWayBuffers.get(i); myExpression = getOneWayBufferPairExpression (firstBuffer, secondBuffer); myCollection.addBufferPairExpression (myExpression); TraceTracer.removeAllConstraints(firstBuffer); TraceTracer.removeAllConstraints(secondBuffer); } sizeOfVector = twoWaysBuffers.size(); for(int i = 0 ; i < sizeOfVector - 1 ; i ++) { firstBuffer = (Buffer)twoWaysBuffers.get(i); i++; secondBuffer = (Buffer)twoWaysBuffers.get(i); myExpression = getTwoWaysBufferPairExpression (firstBuffer, secondBuffer); myCollection.addBufferPairExpression (myExpression); } return myCollection; } else { System.out.println("A Circuit made of empty buffer constraints " + " has been found, it's impossible to continue." + empty); return null; } } /*-------------------------------------------------------*/ /** Met <CODE>nonClausalBufferPairExpression</CODE> sous forme clausale (canonique conjonctive). */ public static BufferPairExpression twoWaysBufferExpressionWedgeOfBufferExpressionVee (BufferPairExpression nonClausalBufferPairExpression) { int l = nonClausalBufferPairExpression.getNbConditions(); BufferPairExpression clausalBufferPairExpression = new BufferPairExpression(nonClausalBufferPairExpression.getFirstBuffer(), nonClausalBufferPairExpression.getSecondBuffer()); BufferPairCondition firstCondition = new BufferPairCondition (nonClausalBufferPairExpression.getBufferPairCondition (l-1).getFirstSize(), nonClausalBufferPairExpression.getBufferPairCondition(0).getSecondSize() ); clausalBufferPairExpression.addBufferPairCondition(firstCondition); for(int i = 0 ; i < l - 1 ; i++) { clausalBufferPairExpression.addBufferPairCondition (new BufferPairCondition (nonClausalBufferPairExpression.getBufferPairCondition(i).getFirstSize(), nonClausalBufferPairExpression.getBufferPairCondition(i+1).getSecondSize()) ); } return clausalBufferPairExpression; } /*-------------------------------------------------------*/ /** Met <CODE>nonClausalBufferPairCollection</CODE> sous forme clausale (canonique conjonctive). */ public static void bufferCollectionWedgeOfBufferCollectionVee (BufferPairCollection nonClausalBufferPairCollection) { Vector twoWaysBuffers = nonClausalBufferPairCollection.getTwoWaysBuffers(); Buffer firstBuffer; Buffer secondBuffer; BufferPairExpression myExpression; int sizeOfVector = twoWaysBuffers.size(); for(int i = 0 ; i < sizeOfVector - 1 ; i ++) { firstBuffer = (Buffer)twoWaysBuffers.get(i); i++; secondBuffer = (Buffer)twoWaysBuffers.get(i); nonClausalBufferPairCollection.addBufferPairExpression (twoWaysBufferExpressionWedgeOfBufferExpressionVee (nonClausalBufferPairCollection.getBufferPairExpression (firstBuffer, secondBuffer)) ); } } /*-------------------------------------------------------*/ /** Renvoie <CODE>true</CODE> si il existe dans la trace d'exécution partielle induite par <CODE>task1</CODE> et <CODE>task2</CODE> un <CODE>TwoTasksCircuit</CODE> formé par des contraintes de buffer vide. */ public static TwoTasksCircuit emptyBufferCircuit(Task task1, Task task2) { TraceTracer.traceAllEmptyBufferConstraints(); TwoTasksCircuit answer = TraceTracer.findTwoTasksCircuit(task1, task2); TraceTracer.removeAllConstraints(); return answer; } /*-------------------------------------------------------*/ /** Extrait de la collection sous forme clausale </CODE>clausalBufferPairCollection</CODE> les sommets du <CODE>BufferBipartiteGraph</CODE> formé par les domaines de définition des capacités des buffers. */ public static BufferBipartiteGraph bufferBipartiteGraphOfClausalBufferPairCollection (BufferPairCollection clausalBufferPairCollection) { BufferBipartiteGraph myBufferBipartiteGraph = new BufferBipartiteGraph (clausalBufferPairCollection.getFirstTask(), clausalBufferPairCollection.getSecondTask()); extractMinimums (myBufferBipartiteGraph, clausalBufferPairCollection); Vector twoWaysBuffers = clausalBufferPairCollection.getTwoWaysBuffers(); int nbBuffers = twoWaysBuffers.size(); BufferPairExpression myBufferPairExpression; BufferPairCondition myBufferPairCondition; Buffer firstBuffer; Buffer secondBuffer; int firstValue; int secondValue; int nbConditions; BufferDomain firstBufferDomain; BufferDomain secondBufferDomain; for(int i = 1 ; i < nbBuffers ; i+=2) { firstBuffer = (Buffer)twoWaysBuffers.get(i-1); secondBuffer = (Buffer)twoWaysBuffers.get(i); myBufferPairExpression = clausalBufferPairCollection.getBufferPairExpression (firstBuffer, secondBuffer); nbConditions = myBufferPairExpression.getNbConditions(); firstBufferDomain = myBufferBipartiteGraph.getBufferDomain(firstBuffer); secondBufferDomain = myBufferBipartiteGraph.getBufferDomain(secondBuffer); for(int j = 0 ; j < nbConditions ; j++) { myBufferPairCondition = myBufferPairExpression.getBufferPairCondition(j); firstValue = myBufferPairCondition.getSizeOf(firstBuffer); secondValue = myBufferPairCondition.getSizeOf(secondBuffer); firstBufferDomain.getHeap().add(new Integer(firstValue)); secondBufferDomain.getHeap().add(new Integer(secondValue)); } } myBufferBipartiteGraph.load(); return myBufferBipartiteGraph; } /*-------------------------------------------------------*/ /** Trace les arêtes du graphe biparti à partir de <CODE>clausalBufferPairCollection</CODE> et de <CODE>edgeLessBufferBipartiteGraph</CODE>. */ public static void traceBufferBipartiteGraphEdges (BufferPairCollection clausalBufferPairCollection, BufferBipartiteGraph edgeLessBufferBipartiteGraph) { Vector twoWaysBuffers = clausalBufferPairCollection.getTwoWaysBuffers(); int nbTwoWaysBuffers = twoWaysBuffers.size(); Buffer firstBuffer; Buffer secondBuffer; int firstValue; int secondValue; BufferPairExpression myBufferPairExpression; BufferPairCondition myBufferPairCondition; int nbBufferPairCondition; for (int i = 1 ; i < nbTwoWaysBuffers ; i += 2) { firstBuffer = (Buffer)twoWaysBuffers.get(i-1); secondBuffer = (Buffer)twoWaysBuffers.get(i); myBufferPairExpression = clausalBufferPairCollection. getBufferPairExpression(firstBuffer, secondBuffer); nbBufferPairCondition = myBufferPairExpression.getNbConditions(); for(int j = 0 ; j < nbBufferPairCondition ; j++) { myBufferPairCondition = myBufferPairExpression.getBufferPairCondition(j); firstValue = myBufferPairCondition.getFirstSize(); secondValue = myBufferPairCondition.getSecondSize(); edgeLessBufferBipartiteGraph.addEdge (firstBuffer, secondBuffer, firstValue, secondValue); } } } /*-------------------------------------------------------*/ /** Tranforme le graphe biparti <CODE>completeBufferBipartiteGraph</CODE> en <CODE>TransportNetwork</CODE>. */ public static TransportNetwork transportNetworkOfBufferBipartiteGraph (BufferBipartiteGraph completeBufferBipartiteGraph) { TransportNetwork myTransportNetwork = new TransportNetwork(); myTransportNetwork.setNbVertices (completeBufferBipartiteGraph.getNbVertices()); Vertex source = new Vertex(myTransportNetwork, 1); Vertex sink = new Vertex(myTransportNetwork, 2); myTransportNetwork.setSource(source); myTransportNetwork.setSink(sink); Vector leftVerticesSet = completeBufferBipartiteGraph. getLeftVerticesSet(); int nbVertices = leftVerticesSet.size(); BufferValue myVertex; for(int i = 0 ; i < nbVertices ; i++ ) { myVertex = (BufferValue)leftVerticesSet.get(i); new Arc(source, myVertex, 0, myVertex.getWeight()); } Vector rightVerticesSet = completeBufferBipartiteGraph. getRightVerticesSet(); nbVertices = rightVerticesSet.size(); for(int i = 0 ; i < nbVertices ; i++ ) { myVertex = (BufferValue)rightVerticesSet.get(i); new Arc(myVertex, sink, 0, myVertex.getWeight()); } return myTransportNetwork; } /*-------------------------------------------------------*/ /** Récupère à partir de la coupe dans le réseau de transport <CODE>cuttedTransportNetwork</CODE> les dimensions à attribuer aux buffers pour ensuite les placer dans les champs <CODE>size</CODE> de ces derniers. */ public static void defineBuffersSizes (BufferBipartiteGraph cuttedTransportNetwork) { cuttedTransportNetwork.defineBuffersSizes(); } /*-------------------------------------------------------*/ /** Extrait de <CODE>clausalBufferPairCollection</CODE> les plus petites capacités admissibles pour chaque <CODE>Buffer</CODE> et les consigne dans leur <CODE>BufferBipartiteGraph</CODE>. */ public static void extractMinimums (BufferBipartiteGraph myBufferBipartiteGraph, BufferPairCollection clausalBufferPairCollection) { Vector oneWayBuffers = clausalBufferPairCollection.getOneWayBuffers(); int nbBuffers = Buffer.getNbBuffers(); nbBuffers = oneWayBuffers.size(); BufferPairExpression myBufferPairExpression; BufferPairCondition myBufferPairCondition; Buffer firstBuffer; Buffer secondBuffer; int firstValue; int secondValue; for(int i = 1 ; i < nbBuffers ; i+=2) { firstBuffer = (Buffer)oneWayBuffers.get(i-1); secondBuffer = (Buffer)oneWayBuffers.get(i); myBufferPairExpression = clausalBufferPairCollection.getBufferPairExpression (firstBuffer, secondBuffer); myBufferPairCondition = myBufferPairExpression.getBufferPairCondition(0); firstValue = myBufferPairCondition.getSizeOf(firstBuffer); secondValue = myBufferPairCondition.getSizeOf(secondBuffer); myBufferBipartiteGraph.getBufferDomain(firstBuffer).updateMaximin(firstValue); myBufferBipartiteGraph.getBufferDomain(secondBuffer).updateMaximin(secondValue); } } /*-------------------------------------------------------*/ /** Calcule la solution optimale à deux tâches et place les résultats dans les champs <CODE>size</CODE> des buffers concernés. */ public static void go(Task task1, Task task2) { BufferPairCollection bpc = getBufferCollectionVee (task1, task2); if (print) { System.out.println(bpc); } bufferCollectionWedgeOfBufferCollectionVee(bpc); if (print) { System.out.println("Sous forme clausale : \n" + bpc); } BufferBipartiteGraph bbg = bufferBipartiteGraphOfClausalBufferPairCollection (bpc); if (print) { System.out.println("Extraction des domaines de définition : \n" + bbg); System.out.print("Tracé du graphe biparti"); } traceBufferBipartiteGraphEdges(bpc, bbg); if (print) { System.out.println(".\n"); System.out.print("Transformation en réseau de transport"); } TransportNetwork tn = transportNetworkOfBufferBipartiteGraph(bbg); if (print) { System.out.println(".\n"); System.out.print("Flot maximal = "); System.out.println(tn.runFlow()); } if (print) { System.out.println("Dimensions des buffers : "); } tn.runFlow(); defineBuffersSizes(bbg); } /*-------------------------------------------------------*/ /** Un exemple d'utilisation de cette classe. */ public static void main(String[] args) { try { Loader.run(args[0]); } catch(Loader.ScriptErrorException e) { System.out.println(e); } catch(Exception e) { System.out.println(e); } print = true; go(Task.get(0), Task.get(1)); } }