Petit probleme de denombrement - Algo - Programmation
Marsh Posté le 23-05-2008 à 22:08:41
Je procederais ainsi:
1) se ramener au cas d'une suite decroissante de 3 entiers
Ici tu vas avoir
3 0 0
2 1 0
1 1 1
2) faire les permutations:
Si trois valeurs egales, on ne fait rien
si deux valeurs egales
permutations circulaires seulement
Si aucune valeur egale
les permutation circulaires et les transpositions de 2 elts (bref, les elts du groupe symmetrique S3 autres que l'identité)
3 0 0 -> 0 0 3 (permutation circulaire)
3 0 0 -> 0 3 0 (permutation circulaire²)
..........................................................
2 1 0 -> 1 0 2 (permutation circulaire)
2 1 0 -> 0 2 1 (permutation circulaire²)
2 1 0 -> 1 2 0 (transposition elts de tete)
2 1 0 -> 0 1 2 (transposition elt initial et final)
2 1 0 -> 2 0 1 (transposition elts de queue)
.............................................................
1 1 1 identiques: on ne fait rien
A+,
Marsh Posté le 23-05-2008 à 22:33:25
Empiriquement (testé pour C = 0..8) il semble que l'on aie le nombre de combinaisons de set comme valant (C+1)(C+2)/2
A+,
Marsh Posté le 23-05-2008 à 22:44:40
oui je viens de trouver (C+1)(C+2)/2 ^^
Pour l'algo, je m'attendais à qqchose d eplus regulier. La je fait betement une triple boucle dans la quelle je test si i+o+m = C avec une astuce dans le decompte de depart de o et m. Je vais voir à utiliser tes astuces
En fait, mon but est de generer les (C+1)(C+2)/2 en exactement (C+1)(C+2)/2 iterations
Marsh Posté le 23-05-2008 à 22:58:31
En exactement (C+1)(C+2)/2 iterations ca ne me semble pas particulierement evident.
Dans ce que je donnais, il y a beaucoup moins de tours de boucle, les generations par permutation et transposition ayant lieu a l'interieur d'un même tour de la triple boucle.
A+,
Marsh Posté le 23-05-2008 à 23:06:37
oui je vois.
Le problème ensuite va être de transformer ça en code à base de BOOST_PP_ XD
Marsh Posté le 23-05-2008 à 23:47:07
En fait, on n'a pas une triple boucle, mais une double boucle.
Le premier terme, i, varie en décroissant de C a [C/3]+ ou [X]+ note la partie entiere superieure de X
Le second terme, j, varie en décroissant de Min(C-i, i) a Min(C-i, [(C-i)/2]+) [cette expression complexe, c'est pour dire que ca varie en décroissant de Min(C-i, i) a [(C-i)/2]+ sauf quand i = C auquel cas j = 0]
et ca nous fournit les triplets ordonnés (i, j, C-i-j)
A+,
Marsh Posté le 24-05-2008 à 00:58:55
Me suis amusé a en coder un proto rapide en perl pour tester l'algo:
Passer la valeur de C sur la ligne de commande pour le faire marcher.
Code :
|
A+,
Marsh Posté le 24-05-2008 à 08:52:11
On dira ce qu'on veut, mais Prolog est quand même plus concis :
decoupe(X, I, J, K) :- |
Marsh Posté le 24-05-2008 à 10:03:53
Plus concis certes, mais beaucoup moins optimal, puisque tu fais une double boucle qui fait C*C itérations.
A+,
Marsh Posté le 24-05-2008 à 10:09:39
Joel F a écrit : voila, j'ai 3 sets : I,O,M |
Est-ce vraiment cela que tu veux ?
Tes N éléments sont-ils équivalents ?
Parce que là tu ne différencies pas les cas:
I={a},M={b,c},O={}
et
I={b},M={a,c},O={}
Marsh Posté le 24-05-2008 à 10:50:45
oui, les éléments en eux mêmes n'ont pas d'importances, c'est les cardinaux de ensembles qui m'intéressent.
Marsh Posté le 24-05-2008 à 11:04:48
gilou a écrit : Plus concis certes, mais beaucoup moins optimal, puisque tu fais une double boucle qui fait C*C itérations. |
tu as raison :
decoupe(X, I, J, K) :- |
Marsh Posté le 24-05-2008 à 12:51:05
Nettement mieux, cette derniere ecriture
Ca fait probablement (C+2)*(C+1)/2 tours de boucle.
A+,
Marsh Posté le 24-05-2008 à 13:04:26
Ah, explique.
Pour le calcul avec 1000, j'ai 2,008,033 inferences avec la deuxième méthode alors que j'en ai 3,509,533 avec la première.
Marsh Posté le 24-05-2008 à 15:30:54
Je parle des tours de boucle avec ta nouvelle écriture:
Il est clair que pour une valeur de I, on a C-I+1 valeurs de J (de 0 a C-I) et pour une valeur de I et une valeur de J données, on a une seule valeur de K.
Le nombre de tours de boucle total est donc Somme(I=0,I=C) de C-I+1
ce qui fait: (C+1)+ C + ... + 1, soit (C+1)*(C+2)/2
Pour 1000, ca devrait faire 501501 tours de boucle.
A+,
Marsh Posté le 24-05-2008 à 17:43:07
D'accord, mais comme le premier programme était en (C+1)^2 avec des essais inutiles, j'ai quand même gagné de l'efficacité non ?
Marsh Posté le 24-05-2008 à 19:01:02
Tout a fait, c'est ce que je disais dans mon post.
La, tu generes un triplet par iteration, sans iteration inutile.
Le code que je donne genere entre un et six triplets par iteration, sans iteration inutile. Donc plus efficace. Par contre il est totallement ciblé sur le problème précis, en utilisant la structure du groupe des permutations a trois elements et certaines de ses propriétés, et pas aisément generalisable au cas de n-uplets, contrairement au tien.
A+,
Marsh Posté le 23-05-2008 à 21:41:09
voila, j'ai 3 sets : I,O,M
chacun de ces ses peut contenir entre 0 et N éléments sous la contrainte suivante :
N(I)+N(O)+N(M) = C
ou C est une constante entière.
ex :
C = 3
Combo possibles
I O M
3 0 0
0 3 0
0 0 3
2 1 0
2 0 1
1 2 0
0 2 1
0 1 2
1 0 2
1 1 1
soit 10 combinaisons
Je voudrais savoir combien de combinaison de set j'ai en fonction de C et un chtit algo pr tous les générer tous.
Voila