Résolu Simplification et systémisation fonction VBA

  • Auteur de la discussion Schnapz
  • Date de début

Schnapz

Nouveau membre
Bonjour,
j'ai un petit problème de programmation avec VBA (pour Arena). Il s'agit d'une
fonction testant les possibilités de mettre des outils dans un buffer en temps
masqué (pour un magasin d'outil de machine).
Le but est de remplir un tableau nommé Buffer_use() avec des 0 et des 1, sachant
que les 1 correspondent à la possibilité de réaliser le placement en temps
masqué. Pour cela, j'ai créer une fonction qui compare le temps de déplacement
du bras pour mettre les outils dans le buffer avec le temps de coupe de
l'opération actuelle. Ces données sont respectivement dans des tableaux nommés
Temps_Deplac() et Temps_Op(). n_tools est le nombre d'opération dans la gamme.

La fonction que j'ai réalisé fonctionne pour un buffer ayant 4 positions (elle
peut donc placer jusqu'à 4 outils dans le buffer a la suite).
Néanmoins, le nombre de positions du buffer est variable. Pouvez-vous m'aider à
transformer cette fonction pour que cela soit prit en compte ? ( J'ai pensé à
faire une fonction récursive mais je ne m'en sors pas).

Voici la fonction telle qu'elle est actuellement :

Code:
buffer_v = 0
counter = 1
Do Until counter = n_tools
    If counter + 1 <= n_tools Then
        If Temps_Deplac(counter + 1) < Temps_Op(counter) Then
            Buffer_Use(counter + 1) = 1
            buffer_v = 1
            If counter + 2 <= n_tools Then
                If Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) <
Temps_Op(counter) Then
                    Buffer_Use(counter + 2) = 1
                    buffer_v = 2
                    If counter + 3 <= n_tools Then
                        If Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2)
+ Temps_Deplac(counter + 1) < Temps_Op(counter) Then
                            Buffer_Use(counter + 3) = 1
                            buffer_v = 3
                            If counter + 4 <= n_tools Then
                                If Temps_Deplac(counter + 4) +
Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter +
1) < Temps_Op(counter) Then
                                    Buffer_Use(counter + 4) = 1
                                    buffer_v = 4
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End If
    counter = counter + buffer_v + 1
    buffer_v = 0
    If counter >= n_tools Then GoTo Nextstep

Loop
Nextstep:

Merci d'avance.
Schnapz.
 

Schnapz

Nouveau membre
pour une meilleure visualisation du code.


______________________________
Modérateur : [strike]NON !
Pour une meilleure visualisation du code, merci de lire le règlement et de l'appliquer.
[/strike]
:merci:
 

marsien

Grand Maître
Une fonction récursive est effectivement une bonne idée sur le principe. Mais je ne connais pas VBA, au point où je ne sais même pas si ce langage accepte les fonctions récursives...
 

zeb

Modérateur
Le code VB est ré-entrant, les fonctions récursives sont donc possibles.

Arhhhhh !!! Au secours, un GoTo :eek:
 

zeb

Modérateur
Je regarde un peu ton code et je me fais les réflexions suivantes.
Il faut virer le GoTo, c'est comme ça. C'est non négociable.
Ensuite, deux If qui se suivent, c'est une clause de trop.
Enfin, une boucle Until avec deux bornes connues, ça me paraît louche. (à voir)

Ça donne :
Code:
buffer_v = 0
counter = 1
Do Until counter = n_tools
    If counter + 1 <= n_tools And Temps_Deplac(counter + 1) < Temps_Op(counter) Then
        Buffer_Use(counter + 1) = 1
        buffer_v = 1
        If counter + 2 <= n_tools And Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
            Buffer_Use(counter + 2) = 1
            buffer_v = 2
            If counter + 3 <= n_tools And Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
                Buffer_Use(counter + 3) = 1
                buffer_v = 3
                If counter + 4 <= n_tools And Temps_Deplac(counter + 4) + Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
                    Buffer_Use(counter + 4) = 1
                    buffer_v = 4
                End If
            End If            
        End If
    End If
    counter = counter + buffer_v + 1
    buffer_v = 0
    If counter >= n_tools Then Exit Do
Loop

Comme je préfère y voir mieux, je sors les tests imbriqués. Ça manquera d'efficacité, mais ce sera plus visible :
Code:
buffer_v = 0
counter = 1
Do Until counter = n_tools
    If counter + 1 <= n_tools And Temps_Deplac(counter + 1) < Temps_Op(counter) Then
        Buffer_Use(counter + 1) = 1
        buffer_v = 1
    End If
    If counter + 2 <= n_tools And Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
        Buffer_Use(counter + 2) = 1
        buffer_v = 2
    End If
    If counter + 3 <= n_tools And Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
        Buffer_Use(counter + 3) = 1
        buffer_v = 3
    End If
    If counter + 4 <= n_tools And Temps_Deplac(counter + 4) + Temps_Deplac(counter + 3) + Temps_Deplac(counter + 2) + Temps_Deplac(counter + 1) < Temps_Op(counter) Then
        Buffer_Use(counter + 4) = 1
        buffer_v = 4
    End If
    counter = counter + buffer_v + 1
    buffer_v = 0
    If counter >= n_tools Then Exit Do
Loop
Bon, du premier coup d'oeil, j'ai envie de mettre une boucle pour cumuler les Temps_Deplac. COmme les quatre blocs se reseemblent, je les assemble ( :fille: ). Ça donne :
Code:
Dim tdc As Integer ' // Temps_Deplac_Cumulé

Dim position As Integer
Dim i As Integer

buffer_v = 0
counter = 1
Do Until counter = n_tools
    For position = 1 To 4
        tdc = 0
        For i = 0 To position - 1
            tdc = tdc + Temps_Deplac(counter + i)
        Next
        If counter + position <= n_tools And tdc < Temps_Op(counter) Then
            Buffer_Use(counter + position) = 1
            buffer_v = position
        End If
    Next
    
    counter = counter + buffer_v + 1
    buffer_v = 0
    If counter >= n_tools Then Exit Do
Loop

Qu'en penses-tu ?
Te poses-tu toujours la question des 4 positions ?
 

Schnapz

Nouveau membre
Merci pour cette réponse très constructive :)
Je viens de tester avec ton code. Cela marche jusqu'à ce que Temps_Deplac(counter + i) sorte du tableau. Il faut donc que je rajoute une condition pour pas que counter+i dépasse n_tools (et non pas seulement n_tools).
Sinon j'ai l'impression que ton code fais la somme de 4 cases automatiquement puis compare si le temps est inférieur. Or le but serait de comparer le premier élément, puis le premier + le deuxième, puis on rajoute le troisième, etc jusqu'à ce que la somme soit supérieure.
Est-ce ce qui est réalisé ? Car je ne sais pas trop l'effet du Next en ligne 13.
 

zeb

Modérateur
Oui, il faut sans doute vérifier les bornes mieux que je ne le faisais.
M'enfin, il y a deux boucles For imbriquées. Donc la première itère de 1 à 4, l'autre dépend de la première. Regarde bien les lignes 11 à 13.

En fait, je dois ne pas bien comprendre la problématique. Je me fie trop à ton code.

Essaie d'expliquer un peu mieux ton problème, sans te (nous) perdre avec trop de détails.
Mieux, c'est-à-dire au sens "mathématique".
 

Schnapz

Nouveau membre
Alors le problème vu simplement :
Parcourir un tableau (Temps_Deplac) dans l'ordre en additionnant les valeurs des cases jusqu'à ce que la somme soit le plus proche mais toujours inférieure à une case d'un autre tableau (Temps_op). Lorsque que l'on atteint cette limite, on repars dans chaque tableau à la case suivante de la dernière utilisée. En même temps on remplit un autre tableau (Buffer_Use) avec des 1 pour chaque élément du tableau Temps_Deplac qui a été utilisé dans la somme.


En rajoutant la condition pour éviter de sortir du tableau, et en ayant remplacé le 4 par une variable d'entrée, il me semble que ça marche :) :sol:
Après est-ce que l'ensemble fait quelque chose de logique ... Ca c'est mon problème.

Merci zeb tu m'as bien aidé sur ce coup-là. Mais peut-être que j'aurai d'autres problèmes sous peu donc je dis pas au revoir si vite ;)
 

zeb

Modérateur
Meilleure réponse
Après est-ce que l'ensemble fait quelque chose de logique ... Ca c'est mon problème.
On est bien d'accord :o ;)

Euh..... à te lire tout à l'heure, je pensais que ce n'était pas du tout résolu. L'est-ce ?
(Si oui, clique sur le bouton "Élire meilleure réponse" de la moins mauvaise réponse ;) )

Sinon, s'il ne te manque que la borne 4, tu devrais t'en sortir tout seul ;)
Pour l'arrêt dès qu'on a dépassé, aussi. Mais je te donne une bonne (on peut toujours faire mieux) façon de faire :
Code:
Dim tdc As Integer ' // Temps_Deplac_Cumulé
Dim position As Integer
Dim i As Integer

buffer_v = 0
counter = 1
Do Until counter > n_tools
    For position = 1 To 4 ' // A toi de voir
        If counter + position > n_tools Then Exit For
        tdc = 0
        For i = 0 To position - 1
            tdc = tdc + Temps_Deplac(counter + i)
        Next
        If counter + position <= n_tools And tdc < Temps_Op(counter) Then
            Buffer_Use(counter + position) = 1
            buffer_v = position
        End If
    Next
   
    counter = counter + buffer_v + 1
    buffer_v = 0
    If counter >= n_tools Then Exit Do
Loop

Je n'ai fais qu'ajouter la ligne 9. On sort de la boucle et on se retrouve donc à la ligne 20.

---------------------------

Observe toutefois la ligne 7, j'ai mis une inégalité. NE JAMAIS METTRE D'EGALITE.
Ben pourquoi ? Imagine pour une raison ou une autre, que ton code, dans un cas extrême ou par effet de bord, fasse déborder (tiens, c'est la même racine que effet de bord, justement) ta borne..... Hop, boucle infinie, bug, etc.

Les programmeurs en C l'ont bien compris :
Code:
for (i=1; i<=4; i++)
La condition est toujours une inégalité.
 

Schnapz

Nouveau membre
Mon programme a l'air stable avec cette solution, je la conserve donc jusqu'à nouvel ordre. Le problème est résolu puisque je sais comment faire en sorte de changer le 4. Il me fallait surtout savoir comment assembler les conditions comme tu l'as fait. Merci beaucoup ! J'ai même corrigé les histoires d'inégalités ;)

 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 128
Messages
6 717 845
Membres
1 586 373
Dernier membre
https://forum.tomshardwar
Partager cette page
Haut