J'ai une demande d'optimisation des coûts que je ne sais pas comment s'il y a la littérature sur. Il est un peu difficile à expliquer, je présente mes excuses à l'avance pour la durée de la question
Il y a un serveur J'accède qui fonctionne de cette façon. P>
sans perte de généralité (juste en normalisant), on peut supposer que Graphiquement, on peut le considérer comme une matrice nxp clairsemée, pour laquelle je veux couvrir les valeurs non nulles avec une sous-matrice rectangulaire: p> Je nommerai g le coefficient faible densité de mon problème (nombre de paires nécessaires sur les paires possibles au total, Il y a quelques observations évidentes: p> T ((r1, ..., rn) x (f1, ..., fp) = a + b * n * p code> p>
b = 1 code> si le coût est: p>
T ((r1, ..., rn) x (f1, ... fp)) = a + n * p code> p>
(r1, f (r1)), ... (rk, f (rk)) code>, une demande qui vient des utilisateurs. Mon programme agit comme un intermédiaire entre l'utilisateur et le serveur (ce qui est externe). J'ai beaucoup de demandes comme celui-ci qui viennent (des dizaines de milliers par jour). Li>
Ul>
for each permutation on rows: (n!)
for each permutation on columns: (p!)
for each possible covering of the n x p matrix: (time unknown, but large...)
compute cost of the covering
g = k / (n * p) code>. Je sais que le coefficient
a code> p>
k * (a + 1) = g * n * p * (a + 1 ) code> li>
a + n * p code> li>
g> g_min = 1 / (a + 1) * (1 + 1 / (n * p)) code> li>
f1 f3 f2
r1 x x
r3 x x
r2 x
6 Réponses :
Je suis sûr qu'il y a un très bon algorithme pour cela quelque part, mais voici mes propres idées intuitives: P>
Approche à quelques rectangles: P>
grandir p>
rétrécir p>
Quad p>
Aussi: garder à l'esprit em> qu'il sera parfois préférable d'avoir deux rectangles em> superposés em> d'un grand rectangle qui est un superset d'entre eux. Par exemple. le cas lorsque deux rectangles se chevauchent dans un coin. P>
Vous n'êtes pas limité aux rectangles.
@ Wrang-Wrang: Oui je suis. @ Artelius, oui, cela est vrai qu'il est peut-être préférable d'avoir des rectangles qui se chevauchent que ceux strictement non émergents. Je teste actuellement une version modifiée de votre solution "Grow". Je démarre un rectangle de 1x1, puis je fusionne les deux rectangles et répétez les deux rectangles moins coûteux (peu coûteux). Il donne une liste linéaire de clusterings sur lesquels je prends le coût minimum dans cette liste. Mais le problème réel n'est pas ici, mais dans les transpositions, je peux faire sur les rangées et les colonnes, ce qui rend la combinatoire exploser (n! * P!, Ne pas comptabiliser la symétrie)
Ah, donc r1, ..., rn ne doit pas avoir à être consécutif? Je pense que ma tête va exploser.
J'envisageais les n enregistrements (lignes) et P champs (COLS) mentionnés dans la demande de l'utilisateur défini sous forme de n points dans l'espace de la dimension p-dimensionnelle ({0,1} ^ p) avec la coordonnée qui étant 1 iff a un X, et Identifiez une hiérarchie de clusters , avec le cluster plus grossier à la racine, y compris tous Le X. Pour chaque nœud de la hiérarchie de la clustering, tenez compte du produit qui couvre toutes les colonnes nécessaires (il s'agit de lignes (n'importe quel sous-node) X cols (n'importe quel sous-node)). Ensuite, décidez de l'autre que de fusionner les couvre-enfants (payant pour toute la couverture), ou de les conserver en tant que demandes séparées. (Les revêtements ne sont pas des colonnes contiguës, mais exactement celles nécessaires; c'est-à-dire penser à un vecteur de bit) p>
Je suis d'accord avec Artelius qui se chevauchent des demandes de produit pourrait être moins chère; Mon approche hiérarchique nécessiterait une amélioration pour incorporer cela. P>
Étant donné que vos valeurs sont rares, car de nombreux utilisateurs demandent des valeurs similaires? La mise en cache dans votre application est-elle une option? Les demandes pourraient être indexées par un hachage qui correspond à la position (x, y), de sorte que vous puissiez facilement identifier les ensembles mis en cache qui tombent dans la zone correcte de la grille. Stocker les ensembles cachés dans un arbre, par exemple, vous permettrait de trouver des sous-ensembles mis en cache minimaux qui couvrent la gamme de demandes très rapidement. Vous pouvez ensuite faire une recherche linéaire sur le sous-ensemble, qui est petit. P>
Bonjour, nous mettons déjà en cache les résultats, bien sûr. Le vrai problème est que nous ne savons pas vraiment comment faire expirer la demande. Ainsi, pour des activités critiques, les systèmes demandeurs ont la possibilité de contourner le cache de certaines valeurs (c'est en fait l'une des causes de la pâte à la portée de la demande).
OK, ma compréhension de la question a changé. Nouvelles idées: p>
stocke chaque ligne comme une longue chaîne de bits. Et paires de cordes de bits ensemble, essayant de trouver des paires qui optimisent le nombre de 1 bits. Cultivez ces paires dans des groupes plus grands (trier et essayer de faire correspondre les très gros les uns avec les autres). Ensuite, construisez une demande qui va frapper le plus grand groupe, puis oublier toutes ces bits. Répétez jusqu'à ce que tout soit fait. Peut-être passer de lignes aux colonnes parfois. P> li>
Recherchez toutes les lignes / colonnes à zéro ou quelques points, points. "Supprimer"-les temporairement. Maintenant, vous regardez ce qui serait couvert par une demande qui les laisse. Maintenant peut-être appliquer l'une des autres techniques et traiter les rangées / cols ignorés par la suite. Une autre façon de penser à cela est la suivante: gérer d'abord les points plus denseurs, puis passer à des pelousser. P> Li> ul>
Sélection des sous-marines pour couvrir les valeurs demandées est une forme de Ensemble de problème de couverture et Par conséquent, NP complète. Votre problème ajoute à ce problème déjà dur que les coûts des ensembles diffèrent. P>
que vous autorisez à permuter les lignes et les colonnes n'est pas un problème si gros, car vous pouvez simplement envisager des soumissions déconnectées. En ligne une, colonnes de quatre à sept et cinq rangées cinq, les colonnes quatre deux sept sont un ensemble valide car vous pouvez simplement échanger la ligne deux et la rangée cinq et obtenir la rangée de la sous-chaîne connectée une, la colonne quatre à la colonne deux, la colonne sept. Bien sûr, cela ajoutera des contraintes - tous les ensembles ne sont pas valables sous toutes les permutations - mais je ne pense pas que ce soit le plus gros problème. P>
L'article Wikipedia donne les résultats de l'inapproximabilité que le problème ne peut pas être résolu en temps polynôme, puis avec un facteur Une liaison inférieure optimiste pour le nombre d'ensembles ignorant les permutations des lignes et des colonnes est Donc, le meilleur que vous puissiez faire est d'utiliser un algorithme heuristique (l'article de Wikipedia mentionne un algorithme gourmandais presque optimal) et accepter qu'il y aura du cas où l'algorithme effectue (très) mauvais. Ou vous allez dans l'autre sens et utilisez un algorithme d'optimisation et essayez de trouver une bonne solution utiliser plus de temps. Dans ce cas, je suggérerais d'essayer d'utiliser a * Recherche . P> 0.5 * log2 (n) code> où
n code> est le nombre de ensembles. Dans votre cas,
2 ^ (n * p) code> est une limite supérieure (assez pessimiste) pour le nombre d'ensembles et de rendements que vous ne pouvez trouver qu'une solution jusqu'à un facteur de
0.5 * N * P code> en temps polynomial (en plus de n = np et ignorant les coûts variables). P>
0.5 * N ^ 2 * P ^ 2 code> donnant un meilleur facteur de
log2 (n) + log2 (P) - 0.5 code>. En conséquence, vous ne pouvez vous attendre qu'à trouver une solution dans votre pire cas de
n = 1000 code> et
p = 200 code> jusqu'à un facteur d'environ
17 code> Dans le cas optimiste et jusqu'à un facteur de
100.000 code> dans le cas pessimiste (ignorant toujours les coûts variables). P>
Merci pour la réponse. Je suis assez conscient que la solution est dure NP, mais je cherche une solution qui fonctionnerait bien dans la pratique. Aussi, après une étude minutieuse, je pense que la formulation de couverture définie n'est pas triviale car 1) la fonction de coût est très particulière 2) les contraintes sont également. Il est temps de commencer une prime!
Je travaille un peu dessus et voici une algorithme de brise de symétrie évidente, o (n ^ 3), et des enregistrements et des champs sont traités séparément) dans un pseudo-code de type Python.
L'idée est trivial: nous commençons par essayer une demande par enregistrement, et nous faisons la fusion la plus méritée jusqu'à ce qu'il ne reste plus rien de digne de fusionner. Cet algo a l'inconvénient évident qu'il n'autorise pas les demandes qui se chevauchent, mais je m'attends à ce qu'elle fonctionne assez bien sur l'affaire réelle (avec le + ceci est O (n3 * p) car: p> le Merci d'avance! P> p> n * (p ^ b) + c * n * p * (1 - g) code> fonction de coût): p>
n code> demandes li>
pendant code> La boucle supprime exactement une demande de la piscine à chaque itération. LI>
pour code> boucle iterate sur le (
NI ^ 2 - NI code>) / 2 paires de demandes distinctes, avec NI passant de n à un dans le pire des cas (lorsque nous fusionnerons tout dans une grande demande). p>
Vous avez un oracle qui vous dit lequel (la rangée, le col) est vide gratuitement?
Vous pouvez nommer les ensembles de lignes et de champs explicitement, c'est-à-dire que vous n'avez pas à spécifier un rectangle contigu dans un système de coordonnées fixes (des permutations de rangées et de cols)?
Re: Ma première question, la réponse est oui, si je comprends correctement les "demandes provenant des utilisateurs".
La réponse à votre deuxième question est également oui. S'il y a une permutation des rangées et des colonnes qui donne un trottoir moins rare, il est généralement meilleur (et je n'ai pas compris votre commentaire sur Artelius, répondit, désolé. Je suis limité à des rectangles contigus sur des permutations de lignes et de colonnes).