Gambas France BETA


Pas de compte ? Incription

Algo d'optimisation qui coince quelque part

Ce sujet est résolu.

1
AuteurMessages
Flachy Joe#1 Posté le 8/11/2012 à 23:51:10
Iguane : Il Gambas Uniquement pour Activer ses NEuronesSalut,
je suis en train de coder un "optimiseur de débit de panneaux" qui positionne des petits rectangles dans un grand rectangle de manière à ce qu'il y ait le moins de chute.
Et j'ai un souci dans mon code que je n'arrive pas à localiser, c'est en rapport avec le positionnement des chutes. Je peut fournir le code complet, en attendant voila le module principal
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
PRIVATE rec AS INTEGER

PUBLIC FUNCTION Resoudre(Feuille AS Panneau, Debit AS Panneau[]) AS SolutionPartielle

DIM solution AS NEW SolutionPartielle
DIM feuille_entiere AS PanneauPositionne

solution.Proposition = NEW PanneauPositionne[]
solution.Reste_A_Debiter = Panneau.TriSurface(Debit) 'du plus grand au plus petit

feuille_entiere = NEW PanneauPositionne(Feuille.largeur, Feuille.longueur)
feuille_entiere.position = NEW Point(0, 0)

rec = 0

solution = RecResoudre(feuille_entiere, solution)

Message.Info("Nombre d'appels à recResoudre : " rec ' = 123521 pour mes 8 panneaux de test

RETURN solution

END

PRIVATE FUNCTION PreparerSolution(solution_1 AS SolutionPartielle, sol AS PanneauPositionne, pan AS Panneau) AS SolutionPartielle

DIM nouvelleSolution AS NEW SolutionPartielle
DIM p AS Panneau

nouvelleSolution.proposition = NEW PanneauPositionne[]
nouvelleSolution.proposition.Insert(solution_1.proposition)
nouvelleSolution.proposition.Add(sol)

nouvelleSolution.reste_a_debiter = NEW Panneau[]
FOR EACH p IN solution_1.reste_a_debitermais
nouvelleSolution.reste_a_debiter.Add(p)
NEXT
nouvelleSolution.reste_a_debiter.Delete(nouvelleSolution.reste_a_debiter.Find(pan))

nouvelleSolution.chutes = NEW PanneauPositionne[]

RETURN nouvelleSolution

END


PRIVATE FUNCTION RecResoudre(Feuille AS PanneauPositionne, solution AS SolutionPartielle) AS SolutionPartielle

DIM chute1 AS PanneauPositionne
DIM chute2 AS PanneauPositionne
DIM sol AS PanneauPositionne

'Les 8 branches de l'arbre des possibilités
DIM nsolution AS NEW SolutionPartielle[8]

DIM pan AS Panneau
DIM n AS INTEGER
DIM mini AS INTEGER, maxi AS INTEGER

rec += 1

IF solution.reste_a_debiter.Count = 0 THEN
'Tous les panneau sont placés
solution.chutes.Add(Feuille)
RETURN solution
ENDIF
IF Feuille.surface = 0 THEN
RETURN solution
ENDIF

'On teste les panneaux du plus grand au plus petit
n = 0
WHILE n < solution.reste_a_debiter.Count
pan = solution.reste_a_debiter[n]
'la feuille est considérée horizontale = longueur en x, largeur en y
'si le panneau entre verticalement
IF pan.largeur <= Feuille.longueur AND pan.longueur <= Feuille.largeur THEN
'Premier cas de chute : coupe verticale à travers
chute1 = NEW PanneauPositionne(pan.largeur, Feuille.largeur - pan.longueur, TRUE)
chute1.Position.x = Feuille.position.x
chute1.Position.y = Feuille.position.y + pan.longueur
chute2 = NEW PanneauPositionne(Feuille.longueur - pan.largeur, Feuille.largeur, TRUE)
chute2.Position.x = Feuille.position.x + pan.largeur
chute2.Position.y = Feuille.position.y
sol = NEW PanneauPositionne(pan.largeur, pan.longueur)
sol.Repere = pan.Repere
sol.Position = Feuille.position
sol.Vertical = TRUE
nsolution[0] = PreparerSolution(solution, sol, pan)
nsolution[0] = RecResoudre(chute1, nsolution[0])
nsolution[0] = RecResoudre(chute2, nsolution[0])
'la même chose en inversant l'ordre dans lequel on teste les chutes
nsolution[1] = PreparerSolution(solution, sol, pan)
nsolution[1] = RecResoudre(chute2, nsolution[1])
nsolution[1] = RecResoudre(chute1, nsolution[1])

'Second cas de chute : coupe horizontale à travers
chute1 = NEW PanneauPositionne(Feuille.longueur, Feuille.largeur - pan.longueur, TRUE)
chute1.Position.x = Feuille.position.x
chute1.Position.y = Feuille.position.y + pan.longueur
chute2 = NEW PanneauPositionne(Feuille.longueur - pan.largeur, pan.longueur, TRUE)
chute2.Position.x = Feuille.position.x + pan.largeur
chute2.Position.y = Feuille.position.y
sol = NEW PanneauPositionne(pan.largeur, pan.longueur)
sol.Repere = pan.Repere
sol.Position = Feuille.position
sol.Vertical = TRUE
nsolution[2] = PreparerSolution(solution, sol, pan)
nsolution[2] = RecResoudre(chute1, nsolution[2])
nsolution[2] = RecResoudre(chute2, nsolution[2])
'la même chose en inversant l'ordre dans lequel on teste les chutes
nsolution[3] = PreparerSolution(solution, sol, pan)
nsolution[3] = RecResoudre(chute2, nsolution[3])
nsolution[3] = RecResoudre(chute1, nsolution[3])
ENDIF

'si le panneau entre horizontalement
IF (pan.largeur <= Feuille.largeur AND pan.longueur <= Feuille.longueur) THEN
'Premier cas de chute : coupe verticale à travers
chute1 = NEW PanneauPositionne(pan.longueur, Feuille.largeur - pan.largeur, TRUE)
chute1.Position.x = Feuille.position.x
chute1.Position.y = Feuille.position.y + pan.largeur
chute2 = NEW PanneauPositionne(Feuille.longueur - pan.longueur, Feuille.largeur, TRUE)
chute2.Position.x = Feuille.position.x + pan.longueur
chute2.Position.y = Feuille.position.y
sol = NEW PanneauPositionne(pan.largeur, pan.longueur)
sol.Repere = pan.Repere
sol.Position = Feuille.position
sol.Vertical = FALSE
nsolution[4] = PreparerSolution(solution, sol, pan)
nsolution[4] = RecResoudre(chute1, nsolution[4])
nsolution[4] = RecResoudre(chute2, nsolution[4])
'la même chose en inversant l'ordre dans lequel on teste les chutes
nsolution[5] = PreparerSolution(solution, sol, pan)
nsolution[5] = RecResoudre(chute2, nsolution[5])
nsolution[5] = RecResoudre(chute1, nsolution[5])

'Second cas de chute : coupe horizontale à travers
chute1 = NEW PanneauPositionne(Feuille.longueur, Feuille.largeur - pan.largeur, TRUE)
chute1.Position.x = Feuille.position.x
chute1.Position.y = Feuille.position.y + pan.largeur
chute2 = NEW PanneauPositionne(Feuille.longueur - pan.longueur, pan.largeur, TRUE)
chute2.Position.x = Feuille.position.x + pan.longueur
chute2.Position.y = Feuille.position.y
sol = NEW PanneauPositionne(pan.largeur, pan.longueur)
sol.Repere = pan.Repere
sol.Position = Feuille.position
sol.Vertical = FALSE
nsolution[6] = PreparerSolution(solution, sol, pan)
nsolution[6] = RecResoudre(chute1, nsolution[6])
nsolution[6] = RecResoudre(chute2, nsolution[6])
'la même chose en inversant l'ordre dans lequel on teste les chutes
nsolution[7] = PreparerSolution(solution, sol, pan)
nsolution[7] = RecResoudre(chute2, nsolution[7])
nsolution[7] = RecResoudre(chute1, nsolution[7])
ENDIF

IF ((pan.largeur <= Feuille.largeur AND pan.longueur <= Feuille.longueur) OR
(pan.largeur <= Feuille.longueur AND pan.longueur <= Feuille.largeur)) THEN
'le plus grand panneau possible est rentré on sort de la boucle
BREAK
ENDIF

n += 1
WEND
IF n = solution.reste_a_debiter.Count THEN
'aucun panneau n'entre
solution.chutes.Add(Feuille)
RETURN solution
ENDIF

'choix de la solution qui fait le plus petit nombre de chutes
mini = 0
FOR n = 0 TO 7
IF NOT IsNull(nsolution[n]) THEN
IF nsolution[mini].chutes.Count > nsolution[n].chutes.Count THEN
mini = n
ENDIF
ELSE IF IsNull(nsolution[mini]) THEN
mini = n + 1
ENDIF
NEXT
IF NOT IsNull(solution.chutes) THEN
nsolution[mini].chutes.Insert(solution.chutes)
ENDIF
RETURN nsolution[mini]

END


Pour comprendre le code :
La classe Panneau stock largeur, longueur , si le troisième argument du constructeur est faux(par défaut) alors la longueur est toujours supérieure à la largeur.
PanneauPositionne hérite de Panneau et stock le point d'origine et l'info vertical/horizontal
SolutionPartielle :
1
2
3
PUBLIC proposition AS PanneauPositionne[]
PUBLIC reste_a_debiter AS Panneau[]
PUBLIC chutes AS PanneauPositionne[]


Voila la solution que j'obtiens avec mon débit test, panneaux en cyan, chutes en rose, le cadre blanc est la feuille dans laquelle il faut couper, mais POURQUOI MES PANNEAUX EN SORTENT ?? :

Merci !!
;) Flachy Joe ;)
gambix#2 Posté le 10/11/2012 à 22:43:51
Faire simple !Le résultat ne ressemble a rien tu veux dire non ?

je ne comprend pas vraiement ce résultat... car je ne vois pas le support de départ...
Reprend du début pour expliquer ça clairement s'il te plait.

SI j'ai bien compris tu veux couper les panneau bleu ? dans la grande plaque.

Moins de texte dans une signature c'est agrandir son espace.
Flachy Joe#3 Posté le 11/11/2012 à 17:40:37
Iguane : Il Gambas Uniquement pour Activer ses NEuronesSalut gambix,

C'est bien ça, je veux couper les panneaux bleus dans la grande plaque blanche.

Le résultat ne ressemble pas tout à fait à rien, j'ai l'impression que les panneaux et les chutes sont mal positionnés mais que ces dernières ont les bonnes dimensions.

On teste les panneaux du plus grand au plus petit jusqu'à en trouver un qui entre dans la plaque, ça défini alors au maximum 8 cas de 2 chutes selon que le panneau entre horizontalement ou verticalement que la coupe traversante se fait verticalement ou horizontalement et que l'on teste d'abord une chute ou l'autre.
chaque chute devient alors (de manière récursive) une plaque dans laquelle on essaie de faire rentrer les panneaux qui restent.
A chaque niveau on défini la meilleur solution comme celle qui fait le moins de chute et on la retourne, La meilleur solution remonte donc la pile des appels.

Apparemment mon souci vient d'une erreur dans la position de la chute qui se répercute sur les propositions de découpe, j'ai beau vérifier et revérifier je ne trouve pas l'erreur.

Le projet est téléchargeable à cette adresse : http://florianfoinant.olympe.in/COPano-0.0.1.tar.gz

Merci !

EDIT : J'ai réussi à avoir un résultat tout à fait correct mais j'ai encore des tests qui se font sur des chutes qui sortent de la grande plaque :
1620 points rouges
;) Flachy Joe ;)
Flachy Joe#4 Posté le 16/11/2012 à 12:05:04
Iguane : Il Gambas Uniquement pour Activer ses NEuronesIl y avait des erreurs dans le calcul des dimensions des chutes, c'est résolu.

Ce petit utilitaire sera bientôt dans la forge...
;) Flachy Joe ;)
1