Nemhardy wrote:Après avoir tapé un peu trop d'une traite, je me rends compte que c'est peut-être
un poil long, pour pas grand chose non plus… mais je voulais présenter un peu toute ma démarche, qui peut rester intéressante si vous n'avez jamais entendu parler de programmation linéaire, ou d'utilisation de
glpk… Ne serait-ce que pour voir comment ça peut servir… On va dire que ça va dans le sens de PC qui peut servir à introduire à différents concepts autour de l'informatique !
Un jour je mettrai ce genre de post trop long dans un blog qui n'existe pas encore…
)
Donc, personnellement, j'ai atteint un score de 225,699.
Mon approche a été encore une fois (comme l'an dernier déjà…
) pas d'une extrême intelligence d'analyse de l'instance qui nous était donnée, mais c'était un premier jet et je voulais voir jusqu'où on pouvait aller avec, avant de passer à autre chose… ce que je n'ai pas fait par une lecture trop peu lucide des modalités du concours… Enfin, passons là dessus !
Déjà pour ceux qui connaissent, l'intitulé rappelle bien vite le problème
Illumination dispo sur
http://www.primers.xyz, où le but est aussi d'allumer un maximum d'interrupteurs à l'aide d'un ensemble d'interrupteurs branchés en va-et-vient ; ici la nuance c'est l'aspect continu dans l'actionnement des interrupteurs, puisqu'on passe de boutons dans
Illumination à des potentiomètres ici.
Même s'il semble que ça peut rendre le problème plus compliqué (l'espace des configurations augmentant alors de manière assez incontrolée), il s'avère que pas mal de problèmes sont en fait plus facile à résoudre lorsqu'on vit dans un espace continu (typiquement dans un tel espace, on peut «glisser» d'une configuration l'autre sans soucis, et, avec un peu de chance, avoir notre fonction objectif continue le long du glissement, nous ouvrant alors la voie à de l'optimisation en glissant de manière maligne parmi les configurations, là où dans un espace certes plus réduit, mais discontinu, il est plus difficile de lier deux configurations différentes, puisque ça revient à faire des sauts, et un peu tout comme n'importe quoi peut se passer lors de ces sauts).
Dans un premier temps j'ai essayé de résoudre des versions simplifiées du problème, pour voir les scores qu'on peut tout de même en tirer. En lisant l'analyse faite par Hackcell plus haut (encore une fois, c'était chouette de partager ça !
), un problème simplifié qui vient à l'esprit peut être le suivant :
On cherche à allumer toutes les ampoules (
ie. à faire passer
la valeur des ampoules au dessus de 1, chacune), tout en minimisant la
somme des valeurs des interrupteurs (ça peut paraître un premier moyen
de limiter le gaspillage).
On n'a aucune garantie que ce problème simplifié va donner quoi que ce soit de bon vis à vis du problème initial, mais ça me semblait un bon début pour prendre le tout en main.
Si on étudie un peu le fonctionnement des ampoules et de leurs potentiomètres, on s'aperçoit que la valeur de chaque ampoule n'est autre que la somme des valeurs des potentiomètres qui la commandent, en particulier c'est une combinaison linéaire de ces valeurs. La fonction que l'on cherche à minimiser l'est aussi : bingo ! On a en fait là
un programme linéaire à résoudre, et ça, et bien on sait bien faire ! Des solveurs efficaces existent déjà, et normalement on n'a plus qu'à encoder notre problème pour un de ces solveurs et voir ce qu'il nous sort. C'est ce que j'ai fait pour ce premier problème simplifié, en utilisant le solveur
glpk. Mon encodage du problème en
MathProg ressemble à ça :
Show/Hide spoilerAfficher/Masquer le spoiler
- Code: Select all
set potentiometres := (0 .. 29);
var pot{p in potentiometres};
set ampoules := (0 .. 251);
var amp{a in ampoules};
param amp_vers_pot{a in ampoules, p in potentiometres};
minimize consommation: sum{p in potentiometres} pot[p];
s.t. reseau{a in ampoules}:
amp[a] = sum{p in potentiometres} amp_vers_pot[a,p]*pot[p];
s.t. allume{a in ampoules}:
amp[a] >= 1;
s.t. plage_potentiometre{p in potentiometres}:
0 <= pot[p] <= 1;
solve;
printf 'config = [';
printf '%.3f', pot[0];
for {p in (1..29)}
printf ', %.3f', pot[p];
printf ']\n';
data;
param amp_vers_pot: 0 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 :=
0 1 1 0 0 1 1 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 1 0 0 1 1 0 0 0 0 1
2 0 0 1 1 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 1
3 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 0 0 1 0
4 1 0 1 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0
5 0 0 1 1 0 1 1 0 0 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 1 0 0
6 0 0 0 1 1 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 1 1
7 0 0 1 0 0 1 1 1 1 0 0 0 1 0 1 1 1 0 0 1 0 0 1 1 0 0 0 0 0 1
8 1 0 1 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0 0 0 0 1
9 0 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 0 0 0 0 0 1 0
10 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 0 1 1 0 1 1 0 1 1 0 0 0
11 1 1 0 0 0 0 0 0 1 1 0 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 1 1
12 1 0 1 1 0 0 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1
13 0 1 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 1 1 1 0 0 1 1 1 0
14 0 0 0 0 1 1 0 1 0 1 0 0 1 1 1 0 0 0 1 0 1 1 0 1 1 1 1 1 0 0
15 0 1 1 1 1 0 1 1 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0
16 1 0 0 0 1 1 1 1 0 1 1 1 0 1 0 1 0 0 1 1 0 0 0 0 0 0 1 1 0 0
17 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0 1 0
18 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 0 1 1 1 1 1 0 0 1 0 1 1 0 0 0
19 1 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 1
20 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 0 1
21 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1 1 0 1 1
22 1 0 1 1 1 1 0 1 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1
23 0 0 1 1 1 1 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0
24 1 0 0 1 0 0 1 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 0 0 1 0 0 0 1
25 0 0 1 0 0 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0
26 0 0 0 1 0 0 1 1 1 0 1 1 1 0 0 1 1 1 0 0 1 1 0 0 1 1 1 0 1 1
27 1 1 0 1 1 0 0 1 0 1 0 0 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 1 1 0
28 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0
29 1 0 0 0 0 1 0 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 0
30 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1 1 0 1 1 1 0 0
31 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 0 1 1 0 0 0 0 0 0
32 1 0 1 1 0 1 1 1 0 0 0 0 0 0 1 0 1 0 0 1 1 1 1 0 1 0 0 0 0 0
33 1 1 1 1 0 1 0 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1 1 1 1
34 1 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 0 1 1 0 1 0 0 1 0 1 0 1 1 1
35 1 1 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 1 0 1 0 0 1 0 0 1 0 0 1 1
36 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1
37 0 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 1 1 1 0 0 1 0 0 0 1 1
38 1 1 0 0 1 1 1 1 0 1 0 0 1 0 0 1 0 0 0 1 0 1 1 1 1 1 1 0 0 1
39 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0
40 0 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 0
41 0 0 1 0 0 0 0 0 1 0 1 1 1 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0
42 0 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0
43 1 1 1 0 1 1 1 0 0 1 1 1 1 1 0 0 1 0 1 0 0 0 0 0 1 0 0 1 0 1
44 0 1 1 1 1 1 1 0 0 0 1 1 0 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 0
45 0 1 1 0 1 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 1 0 1 1 0 0 0 0
46 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 1 0 0 0 0 1
47 1 0 0 1 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 0 0
48 1 1 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 1 0 1 1 1 0
49 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1 0
50 1 0 1 1 1 1 0 1 0 0 1 0 0 0 0 1 0 1 1 0 1 0 1 0 0 0 1 1 0 0
51 1 1 1 1 1 0 0 1 0 1 0 1 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0
52 0 0 0 1 1 0 1 1 0 1 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 1
53 1 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 0 1 0 0 0 1
54 1 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 0 0 1 0 1 1 0 1 1 0 1 0 0 0
55 1 0 1 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 1 1 1 1 1 1
56 0 1 1 0 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 0 1 1 1 1 0 1 1 0
57 0 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 1
58 1 0 1 0 1 1 1 0 1 0 1 1 0 0 0 1 1 1 0 0 1 1 1 1 1 1 0 1 0 0
59 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 1 0 0 0 1
60 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1 1 1 1
61 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 1 1 0 0
62 1 1 0 0 1 0 1 1 0 0 1 0 1 1 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 1
63 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 1 1 0 0 1 1 0
64 1 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0
65 1 1 0 0 1 1 0 0 0 0 0 0 1 1 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 1
66 0 1 0 1 0 0 1 1 0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 0 1 1 0 1 0 0
67 1 0 0 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1
68 1 1 1 0 0 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 1 0 0 1 1 1 0 0 1 1
69 0 1 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 0 0
70 0 0 1 1 1 0 1 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 1 1 0 0 0 0 0
71 1 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 0 0 1 0 0 1 0 0 0 1 0 0
72 0 0 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1
73 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 1 1 0
74 0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0
75 1 1 1 0 1 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1
76 0 1 1 0 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1
77 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0
78 0 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 1 0 0 1 1 1 1 0 1 1 1 1 1
79 1 0 0 1 1 1 1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 0 0 1 1 0 1 0
80 0 0 0 0 0 1 1 0 1 1 0 0 0 0 1 0 0 0 1 1 0 1 0 0 1 0 0 0 1 1
81 0 0 0 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 1 1 1 1 1 0 0 0 0 1 0
82 1 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 1 0 1
83 1 1 1 0 1 0 0 1 0 1 1 1 1 0 1 0 1 0 0 0 1 0 0 1 0 1 0 1 1 1
84 1 1 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 1 1 0 1 1 1 0 1 1 1 0
85 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0 1 1 0 1 1 0 0 0 0 1 1 1 0
86 0 0 1 1 1 0 1 1 1 1 0 0 1 1 0 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1
87 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 0 0 0 0 1 0 1 1 1 1 0 1 1 1 0
88 1 1 0 1 0 0 0 1 1 1 0 0 1 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 1 1
89 0 0 1 0 1 0 0 1 1 1 0 1 0 1 1 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0
90 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 1 1 1 0 0 1 0 1 1 0 1 0 0 1 1
91 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 1 1 0 1 1 1 0 1 1
92 0 0 1 1 0 1 0 1 1 1 0 1 0 1 1 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1
93 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 0 1 0 1 1 1 0 0 0 1
94 0 0 1 1 0 1 0 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 1 1 0 0 1 0 1 1
95 1 1 1 0 1 0 1 0 1 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1
96 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0
97 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 1 0
98 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 1 1 0 1 1 1 1 1 0 0 1 0
99 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1 1 1 0
100 0 0 1 1 1 1 1 1 0 0 0 1 0 1 1 1 1 0 1 0 0 0 1 0 0 0 1 0 0 1
101 0 1 1 1 1 1 1 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 1 0 1
102 1 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0
103 1 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0
104 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0
105 0 1 0 0 0 0 0 1 0 1 1 1 0 1 0 1 1 1 0 1 1 0 0 1 0 0 0 0 0 0
106 1 0 1 1 1 0 0 0 1 0 0 1 1 0 1 1 1 0 1 1 1 0 1 1 0 0 1 1 0 1
107 1 0 0 0 0 0 1 1 0 1 1 0 1 1 0 0 1 0 0 1 1 0 1 1 0 0 0 1 1 0
108 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 0 0 1 1 1 0
109 0 1 0 1 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1
110 1 0 0 0 1 1 0 0 1 0 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0
111 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0
112 0 0 0 0 0 1 0 1 0 0 1 1 0 1 0 1 0 0 0 1 1 1 0 1 0 1 0 0 1 0
113 1 0 1 1 0 0 1 1 0 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 0 1 0 1 1 0
114 0 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 1 1 1 1 1 0 0
115 1 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0
116 1 0 0 1 1 1 1 0 1 0 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1
117 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 1 1 1
118 1 1 1 1 0 0 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0
119 0 1 1 1 1 0 0 1 0 1 1 0 0 1 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 0
120 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 1 0 1 1
121 0 1 1 1 1 1 1 1 0 1 0 1 0 0 1 1 1 1 1 0 1 0 0 0 0 1 0 0 0 1
122 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0
123 0 0 0 0 1 1 1 0 1 1 0 1 0 0 1 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0
124 1 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 1 1 1 1 0 0 0 0 0 1 0 0
125 0 1 1 1 1 0 0 1 0 0 1 1 1 1 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 1
126 0 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0 1 1 0
127 1 1 1 1 1 0 0 1 1 1 1 0 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 0 0 0
128 1 0 0 1 1 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1
129 0 0 0 0 0 1 0 1 0 0 0 1 1 0 1 1 1 1 0 1 0 0 0 1 1 0 1 0 1 0
130 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 1 0
131 0 1 1 0 0 1 1 1 0 1 1 0 1 0 1 1 1 1 0 1 1 1 0 1 0 0 0 1 1 0
132 1 0 1 1 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 1 0 1 0
133 0 1 0 1 0 0 1 0 0 0 0 1 0 1 1 0 1 0 1 0 1 1 1 0 1 1 1 0 0 1
134 1 1 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 0 0 1 0 1 1 0 0
135 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 0
136 1 0 1 0 1 0 0 0 0 0 1 1 0 0 1 1 1 0 1 1 0 0 1 0 1 1 1 1 1 1
137 1 1 0 1 0 1 0 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 1 1 0 0
138 1 1 1 1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 0 1 1 0 1 0 0 1 0 1 0 1
139 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0 1
140 0 1 0 0 1 1 1 1 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 0 0 1 0 0 1 1
141 1 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 0 0 1 0 0
142 1 0 1 0 0 1 1 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 1 1 0 1 1 0 1 0
143 0 0 0 1 1 1 1 1 0 0 1 1 1 1 0 0 1 1 0 1 1 1 0 0 0 1 1 1 0 0
144 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 0
145 0 1 1 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 0 0 0 0 1 1 0 1 0 1 0 0
146 0 1 0 1 1 0 1 1 1 1 1 0 0 1 0 0 0 1 1 0 1 1 0 0 1 0 1 1 1 1
147 0 1 1 1 0 1 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1
148 0 0 0 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 1 0 1 1 0 1 1 0 1 0 0 1
149 0 0 0 0 1 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1
150 1 0 1 1 0 0 1 0 0 1 1 0 0 1 1 0 0 0 0 0 1 0 1 0 1 1 1 1 1 0
151 0 1 1 1 1 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 0 1 1 0 1 1 1 0 1 0
152 1 0 1 0 1 0 0 1 1 1 0 0 1 0 1 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0
153 1 1 1 0 0 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 1 1 1 1 0 0 0 1 1 0
154 0 0 1 1 1 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 0 1 1 0
155 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 0 1 1 0
156 1 1 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 1 0 1 1 0 0 1 0 0 1 0 1 0
157 1 0 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 0 1 1 0 1 0
158 0 1 0 1 0 1 1 0 1 1 1 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 0 0 0
159 0 1 1 0 1 1 0 1 1 1 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1
160 0 0 1 1 1 1 1 0 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 0
161 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 0
162 1 0 0 0 0 1 0 0 1 1 0 1 1 1 1 1 1 0 0 1 1 1 1 0 0 1 1 0 1 0
163 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 1 1 0 1 0 1 0 0 1 0 0 0 1
164 0 1 1 1 1 1 0 1 1 0 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 1 1 0 0
165 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 1
166 0 0 1 0 1 0 1 1 1 1 1 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 1
167 0 1 1 0 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 1 1 1
168 1 0 0 1 1 0 1 1 0 1 1 1 0 1 0 0 0 0 0 1 1 0 1 1 0 1 0 0 1 1
169 0 1 1 0 1 1 1 0 1 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1 0 1 1 1 0 0
170 0 0 1 0 1 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 1
171 0 0 1 1 1 1 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 0 0 1 0 0 1 1 0 0
172 0 0 0 0 1 1 1 0 1 0 0 0 0 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 1 1
173 1 0 1 1 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 1 1 0 0 1 1
174 1 0 1 0 1 1 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 1 1
175 1 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0
176 1 1 0 0 0 0 0 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 0 0 1 0 1
177 1 0 1 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 1 1 0 1 0 0 1 1 0 1 0 1
178 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1 1 0 1 1 1 0 0 0 1 0 0 1 1 1
179 0 0 0 1 1 0 1 1 0 0 0 0 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 0 0 0
180 0 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 1 0 1 0 0 0 0 1 1 1 0 1 0 1
181 0 1 1 1 0 1 0 0 1 0 0 1 0 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 1
182 0 0 0 1 1 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 1 1 1 0 0 1 1 1 1 1
183 0 1 0 0 0 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1 0 0 0 0 1 0 0
184 0 0 0 1 0 0 0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 0 1 0
185 1 0 0 1 0 1 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 0 1 0 0 0 0
186 0 1 1 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 1 0 1 0 1 0 0 0 1
187 0 0 1 1 1 0 1 0 1 0 0 1 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 1 0 0
188 0 0 0 0 0 0 1 1 0 0 1 1 0 1 1 0 0 1 1 0 1 0 1 0 0 0 0 0 0 1
189 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 1 1 0 1 1 1 1 1 1 1 0 0 1 0 0
190 1 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1
191 0 1 0 1 0 0 0 1 1 1 1 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0
192 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 0
193 0 0 0 1 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0 1 1 0 1 0 1 0
194 0 0 1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1
195 1 1 1 1 0 0 0 1 0 1 1 0 1 1 0 1 1 1 0 0 0 0 0 1 0 1 0 1 1 0
196 1 0 1 0 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 1 0 1 1 1 1
197 0 0 1 0 1 0 1 0 1 1 1 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 1 0 0 1
198 0 0 1 1 0 1 0 1 0 1 1 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0
199 1 0 0 1 0 0 0 0 1 0 1 1 1 0 1 0 1 0 0 1 0 0 1 1 0 0 0 1 0 1
200 0 1 0 1 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 1 1 1 0 1 1 1
201 1 0 0 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0
202 0 1 1 1 1 0 1 0 1 0 1 0 1 1 1 0 0 1 0 0 1 1 1 0 1 0 1 1 1 0
203 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0 1 0 1 0 0 0
204 1 0 1 1 0 0 0 1 0 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 1 1
205 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 0 1 0 0
206 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 1 1 0 0 1 1 0 0 1 0 0 1 0 0 1
207 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1
208 1 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0
209 1 0 0 0 1 0 0 1 1 1 1 0 1 0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0
210 1 0 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0 1 1 0 1 1 0 0 0 1 1 1 0 0
211 1 0 0 0 0 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 1 1
212 0 1 1 1 0 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 1 1 1 0
213 1 0 0 0 1 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1
214 0 0 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1
215 0 1 1 1 0 0 1 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 0 0
216 0 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 0 1 1 0 1 0 1 0 0 0 0 1 0 1
217 1 1 0 0 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 1 0 1 0 1
218 0 0 1 1 0 1 0 0 0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 1 0 0 1 0 0
219 1 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 1 0 1 1 0 0 1 1
220 1 0 1 0 1 0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 1 0 0
221 1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0 1 1 0 0 0 0
222 0 0 0 0 1 1 0 1 0 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0
223 1 0 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 0 1 1 1 1 0 1
224 1 0 0 1 0 1 1 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1
225 1 0 1 0 1 1 1 0 0 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 1
226 0 0 0 1 0 1 1 1 0 0 0 1 0 1 0 1 0 0 0 1 1 1 0 1 0 1 0 0 0 0
227 1 0 1 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 1 0 0 1 0 1
228 0 0 0 0 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 0 0 1 1 0 0 0 0 1 1 0
229 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 0
230 0 1 0 1 1 1 1 1 1 1 0 1 1 0 0 0 0 1 1 1 1 1 1 0 1 1 1 0 1 0
231 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 1 0
232 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 0 1 1
233 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 0 1 1 0 1 1
234 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1 0 1 1 1
235 1 0 1 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1
236 1 1 1 1 1 1 1 0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 1 0 0 0 0
237 0 0 1 0 0 1 1 0 1 0 1 0 1 1 0 0 1 0 0 1 0 1 1 1 0 1 1 1 0 1
238 1 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 1 0 0 0 0 1 0
239 1 1 1 1 0 0 1 0 1 0 1 0 1 0 0 1 1 1 1 0 0 1 1 0 1 1 1 0 0 1
240 0 1 0 0 1 0 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 1 1 0 1 0 0 0 0 0
241 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 0 1 1 1 0
242 0 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 1 0 0 1 1 1 0 1 0 0 0 1 0 1
243 0 1 0 1 0 1 1 1 0 0 1 0 0 1 1 0 0 1 1 0 0 0 1 0 0 0 0 1 1 1
244 0 1 1 0 1 0 1 0 0 0 1 1 1 1 1 0 1 1 0 1 0 0 0 1 1 0 1 0 1 0
245 0 1 0 1 1 1 1 1 1 0 1 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 1
246 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 1 1 1 1
247 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 1 1 0
248 0 1 0 0 1 0 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 1 0
249 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 1 1 1
250 0 0 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 0
251 0 1 1 1 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 0;
end;
Je détaille rapidement ce qu'il se passe là, je me dis que ça peut toujours servir à quelqu'un qui aurait un bout de programme linéaire à encoder et résoudre un jour.
Donc, sans détailler trop la syntaxe, on déclare là les tableaux
potentiometres
et
ampoules
qui contiennent juste la liste des indices des ampoules et potentiomètres en jeu dans le problème, qui vont permettre d'itérer avoir à hardcoder les plages
(0 .. 29)
et
(0 .. 251)
à chaque fois… question de bon goût juste ! Ensuite on déclare les variables
pot
et
amp
, qui sont en fait des familles de variables respectivement indexées par
potentiometres
et
ampoules
, et qui vont permettre d'encoder la valeur à laquelle on règle chaque potentiomètres et les valeurs correspondantes des ampoules. On ajoute aussi un gros tableau de paramètres qui permet de lier chaque ampoule aux interrupteurs qui la contrôlent (à bien sûr ne pas taper à la main, mais bidouiller un peu le script
forcecas.py
pour le générer
). Ne reste plus alors qu'à décrire le programme linéaire que l'on veut résoudre :
- Code: Select all
minimize consommation: sum{p in potentiometres} pot[p];
s.t. plage_potentiometre{p in potentiometres}:
0 <= pot[p] <= 1;
s.t. reseau{a in ampoules}:
amp[a] = sum{p in potentiometres} amp_vers_pot[a,p]*pot[p];
s.t. allume{a in ampoules}:
amp[a] >= 1;
solve;
Comme on l'a dit plus tôt, on veut minimiser l'intensité totale en sortie des potentiomètres, c'est ce qu'indique la première ligne : on minimise la somme des
pot[p]
pour
p
qui décrit
potentiometres
. On indique ensuite les contraintes qui spécifient notre problème (les
s.t.
sont à lire comme
such that, c'est à dire
tel que en français) : on veut que chaque potentiomètre ait une valeur entre 0 et 1 (ce sont les contraintes
plage_potentiometre{p}
, on a une telle contrainte par potentiomètre), que chaque ampoule ait la valeur qui lui soit attribuée par le réseau de potentiomètres (contrainte
reseau
, on utilise à cet endroit notre gros tableau de correspondance et calcule simplement la bonne combinaison linéaire des valeurs des potentiomètres) et enfin que chaque ampoule soit allumée (donc de valeur supérieure ou égale à 1) (ce sont les contraintes
allume{a}
). L'important est que toutes nos contraintes ainsi que ce que l'on veut maximiser ou minimiser soit linéaire en les variables que l'on a déclarées.
Je ne sais si c'est très clair ou utile à tous tout ça, mais je voulais montrer un peu la tête d'un fichier en MathProg, je trouvais ça sympa !
Les quelques lignes restantes sont juste là pour formater la sortie du programme (je voulais récupérer une ligne que je n'avais plus qu'à coller dans un fichier python et qui spécifierait les valeurs de chaque interrupteurs) et ne sont pas très intéressantes.Il ne reste plus qu'à lancer le solveur sur notre programme avec
glpsol --math programme_simple.mathprog
. On obtient instantanément la ligne
config = [0.023, 0.223, 0.023, 0.000, 0.164, 0.132, 0.139, 0.191, 0.115, 0.146, 0.081, 0.094, 0.359, 0.083, 0.038, 0.159, 0.000, 0.000, 0.000, 0.001, 0.242, 0.158, 0.064, 0.156, 0.078, 0.105, 0.000, 0.000, 0.123, 0.068]
Là tout content on se décide à tester cette solution du problème simplifié comme solution du problème initial et là, déception… On obtient un score d'à peine un peu plus de 204. Plus en détail, on a :
- Code: Select all
All+Grill:232+20/252
Alimentat:2.989247311827957
Pertes :0.0
Gaspillag:123.46236559139786
On constate que l'on allume bien toutes les ampoules, comme prévu, enfin en tout cas elles sont toutes à une valeur plus grande que 1, mais certaines sont grillées (on pouvait s'y attendre, vu qu'on a jamais dit à notre programme de faire attention à ça). En plus, malgré notre minimisation de la valeur totale en sortie des interrupteurs, le gaspillage reste significatif : c'est normal, puisque le gaspillage dépend de ce que font les ampoules du courant en sortie, et non simplement de la valeur de la sortie. Il va falloir raffiner.
Premier raffinement assez intuitif qui vient à l'esprit : éviter de griller des ampoules. Pour ce faire, il suffit
a priori juste de changer
s.t. allume{a in ampoules}: amp[a] >= 1;
en
s.t. allume{a in ampoules}: 1 <= amp[a] <= 2;
. On relance le solveur, et obtient là la sortie suivante
LP HAS NO PRIMAL FEASIBLE SOLUTION
. Bon. En gros, ça nous apprend qu'il n'existe aucune configuration de potentiomètre telle qu'on puisse allumer les 252 ampoules en même temps sans en griller aucune, même si ça ne nous avance pas vraiment, je trouve intéressant qu'on puisse obtenir ce genre d'information aussi facilement.
À partir de là, on peut penser à plusieurs pistes : on peut essayer de déterminer le nombre minimal d'ampoule que l'on accepte de griller tel qu'on puisse allumer toutes les autres. On sait que ce nombre est plus grand que 0, et inférieur à 20 (on a trouvé qu'on pouvait tout allumer en en grillant 20, avec notre premier programme). Si ce nombre est entre 1 et 5, on peut espérer le trouver relativement rapidement en bruteforcant les cas possibles (c'est à dire en testant toutes les configurations où on autorise explicitement telle et telle ampoule à être grillées), mais s'il est plus grand, ça me paraît plus délicat en passant par un bruteforce du genre. Je n'ai pas fait cette analyse comme ça, mais je me dis
a posteriori que ça doit être intéressant !
J'ai plutôt petit à petit intégré les aspects du problème initial dans mon problème réduit. Je ne vais pas tout détailler, mais notamment si on regarde un peu plus en détail, le problème initial n'est pas non plus si continu (et donc pas si linéaire…) que ça, le score étant calculé différemment selon des paliers de valeurs pour les ampoules (entre 0 et 1, entre 1 et 2 puis entre 2 et l'au-delà). En fait on peut ruser un peu pour encoder ce genre de notions dans le programme linéaire : en MathProg, on peut forcer certaines variables à valoir soit 0 soit 1, par exemple avec
var est_allume{a in ampoules}, binary;
. Il faut toujours se rappeler que l'on a pas le droit d'utiliser des conditions ou des fonctions comme
min
ou
max
ou autre dans un programme linéaire, ou tout doit être… et bien linéaire ! On peut ruser comme je le disais : si vous maximisez la somme des
est_allume[⋅]
, avec les contraintes
est_allume[a] <= amp[a]
, lorsque
amp[a]
sera supérieure à 1 (donc l'ampoule allumée), et bien comme on cherche à ce que la somme des
est_allume[⋅]
soit maximale, on aura tout intérêt à mettre toutes les variables correspondant à des ampoules allumés à une valeur la plus grande possible, ici 1. En revanche lorsque l'ampoule est éteinte, c'est que
amp[a]
est inférieure strictement à 1, et donc
est_allume[a]
ne pourra pas prendre d'autre valeur que 0. En revanche abuser de telles valeurs booléennes tend à augmenter la complexité du problème, pour les raisons décrites plus tôt (le solveur doit encaisser les «sauts», ce qui revient globalement à énumérer des possibilités, même s'il est assez malin pour pouvoir faire ça assez vite dans pas mal de cas, il ne peut pas tout faire, en particulier pas résoudre des problèmes NP-complets plus vite que la musique !
)
Le programme qui m'a permis d'atteindre la solution que j'ai soumise est le suivant (je ne l'ai pas trop nettoyé, donc il est peut-être pas très très lisible, mais bon, il reprend grosso modo les idées décrites plus tôt), avec quelques trucs hardcodés parce-que sur le moment ça me semblait intéressant… sûrement… x)
Show/Hide spoilerAfficher/Masquer le spoiler
- Code: Select all
set switches := (0 .. 29);
var s{k in switches};
set bulbs := (0 .. 251);
param b2s{i in bulbs, k in switches};
var b{i in bulbs};
var sig{i in bulbs}, binary;
var alpha{i in bulbs};
maximize score: sum{i in bulbs}sig[i] - sum{i in switches}alpha[i];#s[i];
s.t. alp{i in bulbs}: alpha[i] >= 0;
s.t. alpi{i in bulbs}: alpha[i] >= b[i]-1.66;
s.t. foo{i in bulbs}: b[i] = sum{k in switches} b2s[i,k]*s[k];
s.t. lit{i in bulbs}: b[i] >= sig[i];
s.t. still{i in bulbs}: b[i] <= 1.9;
s.t. rest{k in switches}: 0 <= s[k] <= 1;
solve;
printf 'aff = [';
printf '%.3f', s[0];
for {k in (1..29)}
printf ', %.3f', s[k];
printf ']\n';
data;
param b2s: 0 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 :=
0 1 1 0 0 1 1 0 1 0 1 0 0 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 0 0 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 1 0 0 1 1 0 0 0 0 1
2 0 0 1 1 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 1
3 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 0 0 1 0
4 1 0 1 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0
5 0 0 1 1 0 1 1 0 0 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 1 0 0
6 0 0 0 1 1 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 1 1
…
…
…
248 0 1 0 0 1 0 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 1 0
249 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0 1 1 1
250 0 0 1 0 0 1 0 0 1 1 1 0 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 0
251 0 1 1 1 0 0 1 0 1 0 1 1 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 0;
end;
Le score 225,699 que l'on obtient n'est pas trop mal, et on l'obtient en quelques secondes, mais il faut savoir qu'il y a quelques soucis qui font que l'approche que j'ai développée jusque là ne permettrait pas je pense de faire bien mieux. Déjà le côté continu des potentiomètres est en fait discutable puisque, notamment pour les raisons qu'a bien et gentiment décrites Critor plus tôt, ceux-ci prennent en fait leurs valeurs dans une plage de 94 valeurs possibles, ça peut sembler suffisant pour approximer du continu, mais cela adjoint aux paliers pose un soucis : globalement on va essayer de faire coller les valeurs des ampoules le plus possibles à la valeur 1.0, le truc c'est que lorsqu'on ajoute des arrondis, et bien on peut avoir tendance à passer très légèrement en dessous de 1.0, et même si c'est peu, c'est suffisant pour changer de palier (l'ampoule n'est plus allumée, et donc le calcul du score erroné). Si on voulait tout de même tout encoder on s'approcherait de plus en plus de la résolution d'un problème vraiment NP-Complet, encodé dans un programme linéaire, et donc un truc qui prend beaucoup trop de temps, en tout cas on ne gagne pas grand chose à passer par un solveur linéaire.
Je me suis amusé à lancer une version plus précise sur une grosse machine pendant un week-end, pas grand chose n'a eu le temps d'en sortir, sinon de la RAM occupée…
Comment ça je squatte la RAM du serveur ? :E
Enfin voilà, sans tous les petits détails, c'était globalement mon approche, je suis curieux de voir ce qu'on pu faire les autres, surtout que le score optimal semble être bien approché (puisqu'on a deux soumissions à 227,647 par deux personnes différentes)…