Comment comprendre la dynamique de la solution de programmation linéaire de partitionnement?
J'ai du mal à comprendre la dynamique de la solution de programmation linéaire de partitionnement problème. Je suis à la lecture de la La Conception D'Un Algorithme Manuel et le problème est décrit dans la section 8.5. J'ai lu l'article d'innombrables fois, mais je suis tout simplement pas l'obtenir. Je pense que c'est une mauvaise explication (ce que j'ai lu jusqu'à maintenant, a été beaucoup mieux), mais je n'ai pas été en mesure de comprendre le problème assez bien à chercher une autre explication. Des liens vers de meilleures explications bienvenue!
J'ai trouvé une page avec un texte semblable au livre (peut-être à partir de la première édition de l'ouvrage): La Partition Problème.
Première question: Dans l'exemple dans le livre les partitions sont ordonnés du plus petit au plus grand. Est-ce juste une coïncidence? De ce que je peux voir l'ordre des éléments n'est pas significative pour l'algorithme.
C'est ma compréhension de la récursivité:
Permet d'utiliser la séquence suivante et la partition en 4:
{S1...Sn} = 100 150 200 250 300 350 400 450 500
k = 4
Deuxième question: Voici comment je pense que la récurrence de commencer - ai-je bien compris?
Le 1er récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 250 300 | 350 | 400 | 450 | 500 //done
La 2ème récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 250 | 300 350 | 400 | 450 | 500 //done
La 3e la récursivité est:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 | 250 300 350 | 400 | 450 | 500 //done
La 4ème récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 | 200 250 300 350 | 400 | 450 | 500 //done
La 5ème récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 | 150 200 250 300 350 | 400 | 450 | 500 //done
La 6ème récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 200 250 | 300 | 350 400 | 450 | 500 //done
Le 7e la récursivité est:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 200 | 250 300 | 350 400 | 450 | 500 //done
Le 8e la récursivité est:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 | 200 250 300 | 350 400 | 450 | 500 //done
La 9e récursivité:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 | 150 200 250 300 | 350 400 | 450 | 500 //done
etc...
Voici le code tel qu'il apparaît dans le livre:
partition(int s[], int n, int k)
{
int m[MAXN+1][MAXK+1]; /* DP table for values */
int d[MAXN+1][MAXK+1]; /* DP table for dividers */
int p[MAXN+1]; /* prefix sums array */
int cost; /* test split cost */
int i,j,x; /* counters */
p[0] = 0; /* construct prefix sums */
for (i=1; i<=n; i++) p[i]=p[i-1]+s[i];
for (i=1; i<=n; i++) m[i][3] = p[i]; /* initialize boundaries */
for (j=1; j<=k; j++) m[1][j] = s[1];
for (i=2; i<=n; i++) /* evaluate main recurrence */
for (j=2; j<=k; j++) {
m[i][j] = MAXINT;
for (x=1; x<=(i-1); x++) {
cost = max(m[x][j-1], p[i]-p[x]);
if (m[i][j] > cost) {
m[i][j] = cost;
d[i][j] = x;
}
}
}
reconstruct_partition(s,d,n,k); /* print book partition */
}
Question à propos de l'algorithme:
- Quelles valeurs sont stockées dans le
m
etd
? - Que signifie "coût" signifie? Est-ce simplement le total des éléments de valeurs au sein d'une partition? Ou est-il plus subtil sens?
- BTW, même si vous ne pouvez pas répondre à mes questions, j'aimerais avoir des commentaires sur la qualité de la matière d'origine. J'aimerais une confirmation qu'il n'est pas juste moi qui trouve l'explication des pauvres (Il m'a fait sentir assez stoopid).
- Je ne pense pas que vous trouverez beaucoup de gens ici en mesure de répondre à votre question, sans donner une brève explication du problème que vous devez résoudre. Il existe de nombreuses variantes de problèmes de partitionnement et le collage de longues tables de l'algorithme exécuté par la main n'a pas de halo rendre les choses plus claires.
Vous devez vous connecter pour publier un commentaire.
Être conscient qu'il y a une petite erreur dans l'explication de l'algorithme dans le livre, regardez dans le errata pour le texte "(*) Page 297".
Vos questions:
reconstruct_partition
procédure, à l'aide de la droite de la table dans la figure 8.8 comme un guideEdit:
Voici ma mise en œuvre du linéaire de l'algorithme de partitionnement. Il est basé sur Skiena de l'algorithme, mais dans un pythonic façon; et il renvoie une liste des partitions.
1,1,1,1,1,1,1,1,1
est1,1,1,1,1|1|1,1
, selon le texte, il doit être1,1,1|1,1,1|1,1,1
. Il est possible que j'ai mal interprété la sortie. Si c'est le cas, je le blâme sur le terrible de l'écriture et non pas pour vouloir d'essayer de ma part. Compte tenu de la façon dont beaucoup de bonnes critiques de ce livre a reçu le je suis surpris par cette.</rant>costs = [(max(table[x][j-1] , table[i][0] - table[x][0]),x) for x in xrange(i)]
... 2.(mincost, minx) = min(costs, key=lambda x: x[0])
J'ai mis en œuvre d'Oscar López algorithme sur PHP. N'hésitez pas à utiliser quand vous en avez besoin.
Ce qui suit est une version modifiée de la mise en œuvre de Skienna Linéaire de partitionnement de l'algorithme en python qui n'a pas de calculer le dernier k valeurs de la colonne à l'exception de la réponse elle-même : M[N][K] (une cellule de calcul ne dépend que de la précédente )
Un essai contre l'input {1,2,3,4,5,6,7,8,9} (utilisé dans Skienna de l'exemple dans le livre ), les rendements légèrement différente de la matrice M ( compte tenu de la modification ci-dessus), mais renvoie correctement le résultat final (dans cet exemple, le coût minimum de partitionnement de s en k varie de 17 , et la matrice D est utilisée pour imprimer la liste des diviseurs de positions qui mènent à cet optimum) .