IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MATLAB Discussion :

Génération aléatoire d'un nombre fixe de valeurs, avec une distance minimale entre chaque [Débutant]


Sujet :

MATLAB

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 7
    Points
    7
    Par défaut Génération aléatoire d'un nombre fixe de valeurs, avec une distance minimale entre chaque
    Bonjour à tous,

    Dans un vecteur colonne de 120 lignes, je souhaite insérer aléatoirement 90 NaN. Cependant, je dois imposer des contraintes à la répartition de ces NaN car ceux-ci doivent être répartis par groupe de 5 NaN (soit 18 groupes). De plus, ces "groupes de 5 NaN" doivent être non-joints, soit au moins une valeur entre chaque groupe de 5 NaN.

    Dans un premier temps, j'ai eu à réaliser la même chose avec 30 et 60 NaN, soit 6 et 12 groupes de 5 NaN, avec la boucle suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    clear all
    X=ones(120,1);
    GH=1;
    %Nb est le nombre de groupes de 5 NaN souhaité
    Nb=18;
     
    while GH==1
        ind=randperm(120)';
        clear po;po=find(ind>2 & ind<119);
        ind2=ind(po);
        [indice,val2]=sort(ind2(1:Nb,1));
     
        cp=0;
        for i=1:length(indice)-1
            cp=cp+1;
            %pour chaque valeur de indice, on vérifie que les écarts de 5
            %entre chaque valeur sont respectés
            clear test;test=indice(i+1:end,1)-(indice(i)+5);
            clear f;f=find(test<=0);
            test2(cp,1)=length(f);
        end
        f=find(test2>0);
        %si test2 a des valeurs > 0, alors les écarts ne sont pas toujours
        %respectés, on recommence donc le tirage aléatoire.
        if length(f)>0
            GH=1;
        else
            GH=0;
        end
    end
     
    %une fois les valeurs centrales des paquets de 5 trouvées, on insère les
    %NaN
    for i=1:length(indice)
        X((indice(i)-2):(indice(i)+2),:)=nan;
    end
    Cette boucle fonctionne très bien pour un nombre de groupes de 5 NaN = 6 ou 12 (vous pouvez tester en changeant Nb), mais lorsque j'en demande 18 la boucle tourne en rond car la probabilité que le tirage aléatoire respecte les conditions fixées est très faible. Je pense donc que cette méthode n'est absolument pas réalisable dans ce dernier cas. Avez-vous une solution qui me permettrait d'obtenir ce que je souhaite ? Ou une méthode pour améliorer le code existant ?

    Merci d'avance pour votre aide !

    Mikaël

  2. #2
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Bonjour,

    Une autre méthode pourrait être :
    • générer un indice
    • vérifier que l'indice est à une distance supérieur de 5 des autres indices
      si non, on génère une nouvelle valeur
      si oui, on passe au suivant

    Mais ça nécessite aussi de vérifier la faisabilité à chaque itération. Tu peux aussi tirer aléatoirement les indices dans un ensemble qui vérifie les critères de distance.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 7
    Points
    7
    Par défaut
    Merci Magellan

    Citation Envoyé par magelan Voir le message
    Bonjour,
    Une autre méthode pourrait être :
    • générer un indice
    • vérifier que l'indice est à une distance supérieur de 5 des autres indices
      si non, on génère une nouvelle valeur
      si oui, on passe au suivant
    Le problème que je vois dans cette proposition c'est que je dois certes avoir des distances supérieures à 5, mais je dois aussi "caser" mes 18 groupes de 5 NaN dans un vecteur de 120 lignes. Et en prenant les valeurs à la suite je pense que je serai en permanence au delà des 120.


    Citation Envoyé par magelan Voir le message
    Tu peux aussi tirer aléatoirement les indices dans un ensemble qui vérifie les critères de distance.
    Cette proposition m'intéresse grandement, aurais-tu moyen de développer tes explications sur cette méthode ? ou me donner un exemple ?

    Merci infiniment !

    Mikaël

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Je pensais à quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    nb = 18;
    GH = 1;
    for p=1:10000
        GH = 0;
        indice = [];
        choix = 1:115;
        for k=1:nb
            if ~isempty(choix)
                indice(k) = choix(randi(length(choix),1));
                choix = setdiff(choix,indice(k)-6:indice(k)+6);
            else
                GH = 1;
                break
            end
        end
        if GH==0
            disp('Séquence trouvée');
            break
        end
    end
    Mais ça ne fonctionne pas non plus, comme tu l'as dit la probabilité d'un tel tirage est trop faible... avec ce code on obtiens au mieux 14 ou 15 groupes.

    Une autre solution serait d'appliquer un algorithme jitter : partir d'une configuration uniforme et faire varier sensiblement la position de chaque indice.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant:chaque jour on aprend des choses ;)
    Inscrit en
    Septembre 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant:chaque jour on aprend des choses ;)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 43
    Points : 68
    Points
    68
    Par défaut
    Bonjour,

    Voici mon idée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    lst = [];
    n_groupes = 18;
    while length(lst)<n_groupes
        Ix = randperm(116);
        lst = Ix(1);
        for ii=2:length(Ix)
            if all(abs(lst-Ix(ii))>5)
                lst(end+1) = Ix(ii);
            end
        end
    end
    M = [1:120]';
    for ii=1:length(lst)
        ix_NaN = [lst(ii):lst(ii)+4];
        M(ix_NaN) = nan;
    end
    Je n'ai pas ajouté des comentaires car je pense c'est claire.
    J'arrive a créer jusqu'a 19 groupes.

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Citation Envoyé par KR4ZY_GUI Voir le message
    J'arrive a créer jusqu'a 19 groupes.
    En regardant ton code, je me suis rendu compte que j'avais fait une erreur sur la distance entre les indices. En corrigeant mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    nb = 18;
    GH = 1;
    for p=1:1000
        GH = 0;
        indice = [];
        choix = 1:116;
        for k=1:nb
            if ~isempty(choix)
                indice(k) = choix(randi(length(choix),1));
                choix = setdiff(choix,indice(k)-5:indice(k)+5);
            else
                GH = 1;
                break
            end
        end
        if GH==0
            disp('Séquence trouvée');
            break
        end
    end
    Effectivement, j'obtiens aussi des séquences avec 18 groupes.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2011
    Messages : 6
    Points : 7
    Points
    7
    Par défaut
    Bonjour à tous,

    et désolé pour le retard de ma réponse,

    milles merci à KR4ZY_GUI et magelan pour leurs précieuses aides, c'est parfait, j'ai exactement ce que j'espèrais avoir !

    Encore merci,

    @ bientôt,

    Mikaël

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 13/03/2013, 21h36
  2. Afficher un nombre fixe de lignes dans une ListView
    Par poutch dans le forum Composants graphiques
    Réponses: 3
    Dernier message: 12/08/2011, 09h14
  3. Réponses: 6
    Dernier message: 02/06/2007, 02h07
  4. Réponses: 14
    Dernier message: 09/03/2007, 13h21
  5. Retourner une valeur avec une fonction
    Par stephtbest dans le forum ASP
    Réponses: 4
    Dernier message: 31/10/2003, 17h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo