Optimiser une partie de code

Fermé
asmakalboussi Messages postés 45 Date d'inscription dimanche 19 août 2012 Statut Membre Dernière intervention 6 décembre 2012 - 21 nov. 2012 à 01:00
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 - 22 nov. 2012 à 14:27
Bonjour,

je suis debutante en java et je veux bien mieux optimiser ce code pour eviter tout les erreurs d'execution possible et le lenteur d'execution. j'espere bien avoir des proposition d'amelioration





public class MockAgent { //Begin MockAgent Class

.
.
wasteCart = new ArrayList<LocationObject>();
deadPoints = new ArrayList<LocationObject>();
}

//********************** Run the agent in an envrionment********************

public int run(TestCase env) {
int totalTime = 0;
Chargingstation[] charge = env.getStations();
Chargingstation cs1 =null;



List<Chargingstation> availableCharginstation = Arrays.asList(charge);;


Wastebin[] wbs = env.getWastebins();
Wastebin bins =null;

List<Wastebin> availableWasteBin = Arrays.asList(wbs);

while (totalTime < timeout) { //Begin While

//=======================================
//Go to the closest charging station
//=======================================
if (battery < 0.3 || rechargeRequired) {

Chargingstation cs = (Chargingstation) GeoMockUtil.closestObj(loc, env.getStations(), deadPoints);
if(cs != null)
{
distbestcs=loc.getDistance(cs.getLocation());

}
int randomcs = (int)(Math.random() * (2-0)) + 0;
cs1 =availableCharginstation.get(randomcs);
distAgentChosencs =loc.getDistance(cs1.getLocation());
if( distAgentChosencs != distbestcs)
{
Dropmovingtonearestcs = Dropmovingtonearestcs +1;
}

totalTime += recharge(cs1, env);



} else

//==============================================================
//If the agent already collect 3wastesit must drop it to wastebin
//===============================================================

if (battery > 0.3 && wasteCart.size() == CART_CAPACITY) {


Wastebin wb = (Wastebin) GeoMockUtil.closestObj(loc, env.getWastebins(), deadPoints);
if(wb != null)
{
distbestBin=loc.getDistance(wb.getLocation());
}
int randomBin = (int)(Math.random() * (2-0)) + 0;
bins =availableWasteBin.get(randomBin);
distAgentChosenBin =loc.getDistance(bins.getLocation());
if( distAgentChosenBin != distbestBin)
{
DropmovingtonearestBin = DropmovingtonearestBin +1;
}

totalTime += dropWaste(bins, env);


}


else
//==============================================================
//If the agent don't collect 3 wastes
//===============================================================
if (battery > 0.3 && wasteCart.size() < CART_CAPACITY) {
Waste w = getNextWaste(env);
if (w == null) {
CommonUtil.print("MockAgent: all waste are cleaned!");
// drop the last waste to a wastebin
if (wasteCart.size() > 0) {
//CommonUtil.print("drop the last waste to a wastebin");
Wastebin wb = (Wastebin) GeoMockUtil.closestObj(loc, env.getWastebins(), deadPoints);
if (wb != null)
{
distbestBin=loc.getDistance(wb.getLocation());
}


int randomBin = (int)(Math.random() * (2-0)) + 0;
bins =availableWasteBin.get(randomBin);
distAgentChosenBin =loc.getDistance(bins.getLocation());
if( distAgentChosenBin != distbestBin)
{
DropmovingtonearestBin = DropmovingtonearestBin +1;
}
totalTime += dropWaste(bins, env);



//*******************************
}
// relax
relax();

// nothing else todo
break;

} else {
totalTime += pickupWaste(w, env);
if(totalTime<100){
numWasteCollected= numWasteCollected+1;

}

}

}
//==============================
//If the battery level is too low
//===============================
if (battery < 0) {
CommonUtil.print("WARNING: battery is lower than 0%: " + battery);
}
} //End While

return totalTime;
}


//**************************************************************************************
//Get the nearest waste from the current location of the agent
//*************************************************************************************
private Waste getNextWaste(TestCase env) {
Waste[] ws = env.getWastes();
Wastebin[] wbs = env.getWastebins();
List<Waste> availableWaste = new ArrayList<Waste>();

for (Waste w : ws) {
boolean cleaned = false;
for (Wastebin wb : wbs) {
if (wb.contains(w)) {
cleaned = true;
}
}
if (!cleaned) {
availableWaste.add(w);
}
}

if (availableWaste.size() == 0) {
return null;
} else {


double minDistance = Double.MAX_VALUE;
double bestdist=minDistance;
int i=0;
int k=0;
List<Waste> addedwastes = new ArrayList<Waste>();

Waste ret = null;
for (Waste w : availableWaste) { //begin for
if (!CommonUtil.contains(w, deadPoints) && !CommonUtil.contains(w, wasteCart)) {
double tmp = loc.getDistance(w.getLocation()); //tmp is the distance between the agent and the chosen waste
if (tmp < minDistance) {

distwastes[i]=tmp;

k++;
addedwastes.add(w);

if(tmp< bestdist){
bestdist=tmp;
}

}
i++;

}

} //end for


if(i== 0)
{
distAgentCollectedWaste = distwastes[0];

}
else{
int random = (int)(Math.random() * (i-0)) + 0;

distAgentCollectedWaste = distwastes[random];
if(distwastes[random] != bestdist) // teh agent collect the nearest waste
{
DROPcollectnearestwaste=DROPcollectnearestwaste+1;
}
ret =addedwastes.get(random);
}
return ret;

}
}
A voir également:

1 réponse

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
21 nov. 2012 à 10:31
Comme d'habitude, tu nous donne un code sans aucune explication de ce que c'est censé faire, copier-coller sans même prendre la peine de le mettre en forme pour conserver l'indentation, avec des classes et des méthodes externes qui n'existent pas et qu'il faut "deviner". Donc au niveau de l'optimisation difficile de faire grand chose à part quelques changements purement mécaniques.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/*
class Chargingstation
{
    public Object getLocation() { return null; }
}

class CommonUtil
{
    public static void print(String string) { }
    public static boolean contains(Waste w, ArrayList<LocationObject> deadPoints) { return false; }
}

class GeoMockUtil
{
    public static Wastebin closestObj(Unknown loc, Chargingstation[] chargingstations,    ArrayList<LocationObject> deadPoints) { return null;}
}

class LocationObject 
{
}

class TestCase
{
    public Chargingstation[] getStations() { return null; }
    public Wastebin[] getWastebins() { return null; }
    public Waste[] getWastes() { return null; }
}

class Unknown 
{
    public double getDistance(Object location) { return 0; }
}

class Waste 
{
    public Object getLocation() { return null; }
}

class Wastebin extends Chargingstation 
{
    public Object getLocation() { return null; }
    public boolean contains(Waste w) { return false; }
}
*/

public class MockAgent
{
/*
    private static final int CART_CAPACITY = 0;
    private ArrayList<LocationObject> wasteCart;
    private ArrayList<LocationObject> deadPoints;
    private int timeout;
    private double battery;
    private boolean rechargeRequired;
    private Object distbestcs;
    private Unknown loc;
    private Object distAgentChosencs;
    private int Dropmovingtonearestcs;
    private Object distbestBin;
    private Object distAgentChosenBin;
    private int DropmovingtonearestBin;
    private int numWasteCollected;
    private double[] distwastes;
    private double distAgentCollectedWaste;
    private int DROPcollectnearestwaste;
    
    private int pickupWaste(Waste w, TestCase env) { return 0; }
    private void relax() { }
    private int dropWaste(Wastebin bins, TestCase env) { return 0; }
    private int recharge(Chargingstation cs1, TestCase env) { return 0; }
*/
//********************** Run the agent in an envrionment********************

    private static final Random random = new Random();
    
    public int run(TestCase env)
    {
        // Limiter au maximum la portée des variables, plus une variable est interne dans le code, moins il y a de problèmes
        int totalTime = 0;
        
        // Ne pas stocker tes tableaux dans des variables, après ils restent en mémoire pour rien puisque tu utilises tout le temps les listes
        List<Chargingstation> availableCharginstation = Arrays.asList(env.getStations());
        List<Wastebin> availableWasteBin = Arrays.asList(env.getWastebins());
        
        while (totalTime < timeout)
        {
            //=======================================
            //Go to the closest charging station
            //=======================================
            
            // Commencer le test par la valeur booléenne la plus simple, ici si chargeRequired est true, la comparaison "battery < 0.3" sera économisée
            if (rechargeRequired || battery < 0.3)
            {
                Chargingstation cs = (Chargingstation) GeoMockUtil.closestObj(loc, env.getStations(), deadPoints);
                
                if (cs != null)
                    distbestcs = loc.getDistance(cs.getLocation());

                // Pour les valeurs aléatoires, utilise la classe Random (ici avec mon objet random)
                Chargingstation cs1 = availableCharginstation.get(random.nextInt(2)); // soit 0, soit 1
                
                distAgentChosencs = loc.getDistance(cs1.getLocation());
                if (distAgentChosencs != distbestcs)
                    Dropmovingtonearestcs++; // x++ est meilleur que x=x+1
                
                totalTime += recharge(cs1, env);
            }
            else if (battery > 0.3 && wasteCart.size() == CART_CAPACITY) //If the agent already collect 3wastesit must drop it to wastebin
            {
                Wastebin wb = (Wastebin) GeoMockUtil.closestObj(loc, env.getWastebins(), deadPoints);
                
                if(wb != null)
                    distbestBin=loc.getDistance(wb.getLocation());
    
                Wastebin bins = availableWasteBin.get(random.nextInt(2));
                
                distAgentChosenBin = loc.getDistance(bins.getLocation());
    
                if( distAgentChosenBin != distbestBin)
                    DropmovingtonearestBin++;
    
                totalTime += dropWaste(bins, env);
            }
            else if (battery > 0.3 && wasteCart.size() < CART_CAPACITY) //If the agent don't collect 3 wastes
            {
                Waste w = getNextWaste(env);
                
                if (w == null)
                {
                    CommonUtil.print("MockAgent: all waste are cleaned!");
                    
                    // drop the last waste to a wastebin
                    if (!wasteCart.isEmpty()) // plus rapide qu'un calcul exhaustif de la taille
                    {
                        //CommonUtil.print("drop the last waste to a wastebin");
                        Wastebin wb = (Wastebin) GeoMockUtil.closestObj(loc, env.getWastebins(), deadPoints);
                        
                        if (wb != null)
                            distbestBin = loc.getDistance(wb.getLocation());
    
                        Wastebin bins = availableWasteBin.get(random.nextInt(2));
                        
                        distAgentChosenBin = loc.getDistance(bins.getLocation());
                        if( distAgentChosenBin != distbestBin)
                            DropmovingtonearestBin++;
    
                        totalTime += dropWaste(bins, env);
                    }
    
                    // relax
                    relax();
    
                    // nothing else todo
                    break;
                }
                else // w != null
                {
                    totalTime += pickupWaste(w, env);
    
                    if(totalTime<100)
                        numWasteCollected++;
                }
    
            } // if (battery)
        
            //==============================
            //If the battery level is too low
            //===============================
            if (battery < 0)
                CommonUtil.print("WARNING: battery is lower than 0%: " + battery);
        } // while
        
        return totalTime;
    }
        
    //**************************************************************************************
    //Get the nearest waste from the current location of the agent
    //*************************************************************************************
        
    private Waste getNextWaste(TestCase env)
    {
        Wastebin[] wbs = env.getWastebins();
        
        // Si tu ne te sers que des méthode des List, un LinkedList est profitable.
        List<Waste> availableWaste = new LinkedList<Waste>();
        
        for (Waste w : env.getWastes())
        {
            boolean cleaned = false;
            
            for (Wastebin wb : wbs)
            {
                if (wb.contains(w))
                {
                    cleaned = true;
                    break; // Ne pas l'oublier celui-là, ça va te faire gagner du temps !
                }
            }
            
            if (!cleaned)
                availableWaste.add(w);
        }
        
        wbs = null; // libération explicite, car on n'en a plus besoin !
        
        if (availableWaste.isEmpty())
            return null;
        else
        {
            double minDistance = Double.MAX_VALUE;
            double bestdist = minDistance;
            
            int i=0;
    
            List<Waste> addedwastes = new LinkedList<Waste>();
            
            for (Waste w : availableWaste)
            {
                if (!CommonUtil.contains(w, deadPoints) && !CommonUtil.contains(w, wasteCart))
                {
                    double tmp = loc.getDistance(w.getLocation()); //tmp is the distance between the agent and the chosen waste
    
                    if (tmp < minDistance)
                    {
                        distwastes[i]=tmp;
                        addedwastes.add(w);
                        
                        if(tmp < bestdist)
                            bestdist=tmp;
                        
                        // Est-ce qu'il ne faudrait pas aussi avoir ceci ?
                        // minDistance = tmp; // TODO
                    }
                    
                    i++;
                }
            }
            
            if (i==0)
            {
                distAgentCollectedWaste = distwastes[0];
                return null;
            }
            else
            {
                int rd = random.nextInt(i);
                
                distAgentCollectedWaste = distwastes[rd];
                if (distAgentCollectedWaste != bestdist) // teh agent collect the nearest waste
                    DROPcollectnearestwaste++;
                
                return addedwastes.get(rd);
            }
        }
    }
}
1
asmakalboussi Messages postés 45 Date d'inscription dimanche 19 août 2012 Statut Membre Dernière intervention 6 décembre 2012
21 nov. 2012 à 15:41
merci énormememt KX pour vos efforts.
j'ai pris en considération tout vos conseils d'optimisation .Comme vous voyez, il s'agit bien d'agent de nettoyage qui est en train de collecter les déchets....
Comme mon algorithme évolutionnaire est basé sur un certain nombre de générations(par exemple 100) et un nombre de cas de test a exécutés(par exemple 30 ,chaque cas de test contient un agent,2 poubelles,2 stations de recharge et un nombres d'obstacles et déchets ), a chaque génération, il ya 30 fois exécution de ce code.
Maintenant , avec toute les modifications prises en comptes , j'ai ce message d'erreur(comme l'autre fois exactement):
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
[java] at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
[java] at java.util.ArrayList.grow(Unknown Source)
[java] at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
[java] at java.util.ArrayList.add(Unknown Source)
[java] at jadex.examples.cleanerworld.multi.mocks.MockAgent.dropWaste(Unknown Source)
[java] at jadex.examples. .multi.mocks.MockAgent.run(Unknown Source)


J'ai pas compris surtout un point , pourquoi a 95% l'exécution de l'algo est bloquée mais de temps en temps (disant une fois sur 20) il se termine normalement -_-
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
21 nov. 2012 à 15:52
Tu utilises de l'aléatoire dans ton code, donc tu ne peux pas avoir un résultat déterministe, même dans la gestion des exceptions, si tu bloquais l'aléatoire en imposant une graine fixe, tu aurais toujours strictement la même exécution. Cependant les erreurs de mémoire peuvent aussi venir du Garbage Collector qui lui n'est pas déterministe pour un sous, et fais ce qu'il veut...

Remarque : optimiser ce code est une chose mais ton erreur n'est pas là, elle est dans dropWaste !
0
asmakalboussi Messages postés 45 Date d'inscription dimanche 19 août 2012 Statut Membre Dernière intervention 6 décembre 2012
21 nov. 2012 à 16:06
c'est le code de dropwaste ,je pense qu'il est bien structuré . Déjà le travail de base d'un chercheur qui est ma source d'inspiration utilise la même méthode dropwaste et elle fonctionne normalemnt dans son travail
private int dropWaste(Wastebin wb, TestCase env) {
int cost = moveTo(wb.getLocation(), env);

double estimateBatteryLeft = battery - wasteCart.size() * BATTERY_UNIT * 3.0;
if (cost > 0 && estimateBatteryLeft > 0) {
CommonUtil.print("MockAgent: Dropping waste to " + wb);
for (LocationObject w : wasteCart) {
wb.addWaste((Waste) w);
battery -= BATTERY_UNIT * 3;
// for monitoring & GA
totalPower += BATTERY_UNIT * 3;

cost += DROP_TIME;
}
wasteCart.clear();

return cost;
} else if (!rechargeRequired && estimateBatteryLeft > 0) {
deadPoints.add(wb);
}

return 0;
}
0
asmakalboussi Messages postés 45 Date d'inscription dimanche 19 août 2012 Statut Membre Dernière intervention 6 décembre 2012
21 nov. 2012 à 16:36
il n'ya aucune solution pour ce sorte de souci KX?????? je me sens vraiment déprimée car il me reste que 15j de dépôt de mémoire et j'ai aucune personne qui peut m'aider :(
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
21 nov. 2012 à 16:46
Vu la description de l'erreur là où ça plante ensuite c'est sur un ArrayList.add, et je n'en vois qu'un :

deadPoints.add(wb);

La je pense qu'il faudrait revoir l'intérêt d'avoir un ArrayList pour deadPoints, je les avais déjà remplacé par des LinkedList dans ton code plus haut.

Il faut savoir qu'un ArrayList en interne c'est un tableau, il a donc une capacité fixée, et dès que l'on veut ajouter un élément au delà de la capacité, il faut créer un nouveau tableau de taille plus grand (méthode ArrayList.grow) et faire un copier-coller de toutes les données d'un tableau vers l'autre (Arrays.copyOf), or c'est sur cette opération que ton programme plante, car d'un coup au lieu d'avoir "N" éléments en mémoire, tu te retrouves temporairement avec "2N" éléments ce qui n'est pas supportable pour N grand.

En revanche la gestion de la mémoire est très différente pour une LinkedList, et tu n'as jamais une telle copie à faire, donc moins de mémoire gaspillée. Evidemment la liste chaînée a aussi des inconvénients, elle est en particulier plus longue pour les accès en milieu de liste, mais avec le code que j'ai vu passer ça ne devrait pas poser de problème.
0