Skip to content

Commit be474b3

Browse files
authored
fix (#86)
1 parent 48d8796 commit be474b3

File tree

1 file changed

+153
-22
lines changed

1 file changed

+153
-22
lines changed

_doc/practice/exams/td_note_2025.ipynb

Lines changed: 153 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
{
2222
"cell_type": "code",
23-
"execution_count": 1,
23+
"execution_count": 32,
2424
"metadata": {},
2525
"outputs": [
2626
{
@@ -29,7 +29,7 @@
2929
"np.int64(45)"
3030
]
3131
},
32-
"execution_count": 1,
32+
"execution_count": 32,
3333
"metadata": {},
3434
"output_type": "execute_result"
3535
}
@@ -47,6 +47,60 @@
4747
"distance(table1, table2)"
4848
]
4949
},
50+
{
51+
"cell_type": "markdown",
52+
"metadata": {},
53+
"source": [
54+
"Le minimum serait..."
55+
]
56+
},
57+
{
58+
"cell_type": "code",
59+
"execution_count": 33,
60+
"metadata": {},
61+
"outputs": [
62+
{
63+
"data": {
64+
"text/plain": [
65+
"np.int64(1)"
66+
]
67+
},
68+
"execution_count": 33,
69+
"metadata": {},
70+
"output_type": "execute_result"
71+
}
72+
],
73+
"source": [
74+
"distance(np.array([[18, 18], [7, 8], [8, 6]]), table2)"
75+
]
76+
},
77+
{
78+
"cell_type": "markdown",
79+
"metadata": {},
80+
"source": [
81+
"Et sinon une petite erreur en oubliant la permutation sur les colonnes."
82+
]
83+
},
84+
{
85+
"cell_type": "code",
86+
"execution_count": 35,
87+
"metadata": {},
88+
"outputs": [
89+
{
90+
"data": {
91+
"text/plain": [
92+
"np.int64(7)"
93+
]
94+
},
95+
"execution_count": 35,
96+
"metadata": {},
97+
"output_type": "execute_result"
98+
}
99+
],
100+
"source": [
101+
"distance(np.array([[18, 18], [8, 7], [6, 8]]), table2)"
102+
]
103+
},
50104
{
51105
"cell_type": "markdown",
52106
"metadata": {},
@@ -193,23 +247,23 @@
193247
"cell_type": "markdown",
194248
"metadata": {},
195249
"source": [
196-
"## Q7 - C'est b eaucoup trop long.\n",
250+
"## Q7 - C'est beaucoup trop long.\n",
197251
"\n",
198252
"On prop ose que calculer chaque p ermutation séparément. On cherche donc la meilleure p ermutation qui minimise la distribution de la somme par ligne et par colonne entre les deux matrices. Ecrire une fonctionne qui implémente ce raisonnement.\n"
199253
]
200254
},
201255
{
202256
"cell_type": "code",
203-
"execution_count": 6,
257+
"execution_count": 37,
204258
"metadata": {},
205259
"outputs": [
206260
{
207261
"data": {
208262
"text/plain": [
209-
"((0, 1), (1, 0, 2))"
263+
"((1, 0, 2), (0, 1))"
210264
]
211265
},
212-
"execution_count": 6,
266+
"execution_count": 37,
213267
"metadata": {},
214268
"output_type": "execute_result"
215269
}
@@ -228,8 +282,8 @@
228282
"\n",
229283
"def optimise_fast(table1, table2):\n",
230284
" return (\n",
231-
" optimise_vecteur(table1.sum(axis=0), table2.sum(axis=0)),\n",
232285
" optimise_vecteur(table1.sum(axis=1), table2.sum(axis=1)),\n",
286+
" optimise_vecteur(table1.sum(axis=0), table2.sum(axis=0)),\n",
233287
" )\n",
234288
"\n",
235289
"\n",
@@ -240,7 +294,28 @@
240294
"cell_type": "markdown",
241295
"metadata": {},
242296
"source": [
243-
"Le coût est en $O(i!) + O(j!)$. Pas nécessairement optimal mais beaucoup plus rapide."
297+
"Le coût est en $O(i!) + O(j!)$. Pas nécessairement optimal mais beaucoup plus rapide. On obtient la distance :"
298+
]
299+
},
300+
{
301+
"cell_type": "code",
302+
"execution_count": 38,
303+
"metadata": {},
304+
"outputs": [
305+
{
306+
"data": {
307+
"text/plain": [
308+
"np.int64(7)"
309+
]
310+
},
311+
"execution_count": 38,
312+
"metadata": {},
313+
"output_type": "execute_result"
314+
}
315+
],
316+
"source": [
317+
"p1, p2 = optimise_fast(table1, table2)\n",
318+
"distance(table1[p1, :][:, p2], table2)"
244319
]
245320
},
246321
{
@@ -262,7 +337,7 @@
262337
},
263338
{
264339
"cell_type": "code",
265-
"execution_count": 9,
340+
"execution_count": 39,
266341
"metadata": {},
267342
"outputs": [
268343
{
@@ -304,7 +379,7 @@
304379
},
305380
{
306381
"cell_type": "code",
307-
"execution_count": 14,
382+
"execution_count": 40,
308383
"metadata": {},
309384
"outputs": [
310385
{
@@ -332,49 +407,57 @@
332407
},
333408
{
334409
"cell_type": "code",
335-
"execution_count": 17,
410+
"execution_count": 42,
336411
"metadata": {},
337412
"outputs": [
338413
{
339414
"data": {
340415
"text/plain": [
341-
"((0, 1), (2, 0, 1))"
416+
"((1, 0, 2), (0, 1), np.int64(7))"
342417
]
343418
},
344-
"execution_count": 17,
419+
"execution_count": 42,
345420
"metadata": {},
346421
"output_type": "execute_result"
347422
}
348423
],
349424
"source": [
350425
"def optimise_vecteur_tri(vec1, vec2):\n",
351-
" pos_vec1 = [(v, i) for i, v in enumerate(vec1)]\n",
352-
" pos_vec1.sort()\n",
353-
" return tuple(p[1] for p in pos_vec1)\n",
426+
" # on tri dans l'ordre croissant\n",
427+
" pos_vec1 = sorted([(v, i) for i, v in enumerate(vec1)])\n",
428+
" pos_vec2 = sorted([(v, i) for i, v in enumerate(vec2)])\n",
429+
" # on a deux permutations, il suffit de les composer.\n",
430+
" p1 = list(p[1] for p in pos_vec1)\n",
431+
" p2 = list(p[1] for p in pos_vec2)\n",
432+
" p = [p1[p2[i]] for i in range(len(p1))]\n",
433+
" return tuple(p)\n",
354434
"\n",
355435
"\n",
356436
"def optimise_fast_tri(table1, table2):\n",
357437
" return (\n",
358-
" optimise_vecteur_tri(table1.sum(axis=0), table2.sum(axis=0)),\n",
359438
" optimise_vecteur_tri(table1.sum(axis=1), table2.sum(axis=1)),\n",
439+
" optimise_vecteur_tri(table1.sum(axis=0), table2.sum(axis=0)),\n",
360440
" )\n",
361441
"\n",
362442
"\n",
363-
"optimise_fast_tri(table1, table2)"
443+
"table1 = np.array([[8, 7], [18, 18], [6, 8]])\n",
444+
"table2 = np.array([[18, 18], [7, 9], [8, 6]])\n",
445+
"p1, p2 = optimise_fast_tri(table1, table2)\n",
446+
"p1, p2, distance(table1[p1, :][:, p2], table2)"
364447
]
365448
},
366449
{
367450
"cell_type": "markdown",
368451
"metadata": {},
369452
"source": [
370-
"On revient au problème d'optimisation : $\\lVert AM - B \\rVert^2$. Il faudrait pouvoir forcer les coefficients de la matrice à être 0 ou 1 en ajoutant une contrainte. On utilise pour cela fonction $f(x)=x(1-X)$ qui vaut 0 quand $x \\epsilon \\{0,1\\}$. On cherche donc $M$ qui minimise $\\lVert AM - B \\rVert^2 + \\lambda \\lVert M^2*(1-M)^2\\rVert$ où $*$ est une multiplication terme à terme. Mais résoudre ce problème n'est pas simple. On en restera là pour le moment."
453+
"On revient au problème d'optimisation : $\\lVert AM - B \\rVert^2$. Il faudrait pouvoir forcer les coefficients de la matrice à être 0 ou 1 en ajoutant une contrainte. On utilise pour cela fonction $f(x)=x(1-X)$ qui vaut 0 quand $x \\epsilon \\{0,1\\}$. On cherche donc $M$ qui minimise $\\lVert AM - B \\rVert^2 + \\lambda \\lVert M^2*(1-M)^2\\rVert$ où ``*`` est une multiplication terme à terme. Mais résoudre ce problème n'est pas simple. On en restera là pour le moment."
371454
]
372455
},
373456
{
374457
"cell_type": "markdown",
375458
"metadata": {},
376459
"source": [
377-
"## Q9 - Comment utiliser cette fonction p our implémenter une version plus rapide de la fonction à la question 5."
460+
"## Q9 - Comment utiliser cette fonction pour implémenter une version plus rapide de la fonction à la question 5."
378461
]
379462
},
380463
{
@@ -388,14 +471,62 @@
388471
"cell_type": "markdown",
389472
"metadata": {},
390473
"source": [
391-
"## Q10 - La troisième année, une colonne est coupée en deux : une catégorie est divisée en deux sous-catégorie. Que proposez-vous p our y remédier ?"
474+
"## Q10 - La troisième année, une colonne est coupée en deux : une catégorie est divisée en deux sous-catégorie. Que proposez-vous pour y remédier ?"
475+
]
476+
},
477+
{
478+
"cell_type": "markdown",
479+
"metadata": {},
480+
"source": [
481+
"L'idée est assez simple, on choisit au hasard deux lignes de la seconde matrice et on les aggrège. On utilise la fonction précédente pour en déduire les deux permutations les moins coûteuses puis on conserve le coût de cette permutation. On fait de même pour toutes les paires et on ne garde que la meilleure paire.\n",
482+
"\n",
483+
"Ce n'était pas demandé dans l'énoncé mais on pourait implémenter ce schéma comme suit :"
484+
]
485+
},
486+
{
487+
"cell_type": "code",
488+
"execution_count": 45,
489+
"metadata": {},
490+
"outputs": [
491+
{
492+
"data": {
493+
"text/plain": [
494+
"(np.int64(7), (1, 0, 2), (0, 1), (2, 3))"
495+
]
496+
},
497+
"execution_count": 45,
498+
"metadata": {},
499+
"output_type": "execute_result"
500+
}
501+
],
502+
"source": [
503+
"def optimise_fast_tri_paire(table1, table2):\n",
504+
" best = None\n",
505+
" for i in range(table2.shape[0] - 1):\n",
506+
" for j in range(i + 1, table2.shape[0]):\n",
507+
" table2p = np.zeros(table1.shape, dtype=table2.dtype)\n",
508+
" table2p[:, :] = table2[:-1, :]\n",
509+
" table2p[i, :] += table2[j, :]\n",
510+
" p1, p2 = optimise_fast_tri(table1, table2p)\n",
511+
" t = table1[p1, :][:, p2]\n",
512+
" d = distance(t, table2p)\n",
513+
" if best is None or d < best[0]:\n",
514+
" best = d, p1, p2, (i, j)\n",
515+
" return best\n",
516+
"\n",
517+
"\n",
518+
"table1 = np.array([[8, 7], [18, 18], [6, 8]])\n",
519+
"# on divise par deux les deux valeurs de la dernière ligne\n",
520+
"# et on les réplique\n",
521+
"table2 = np.array([[18, 18], [7, 9], [4, 3], [4, 3]])\n",
522+
"optimise_fast_tri_paire(table1, table2)"
392523
]
393524
},
394525
{
395526
"cell_type": "markdown",
396527
"metadata": {},
397528
"source": [
398-
"L'idée est assez simple, on choisit au hasard deux lignes de la seconde matrice et on les aggrège. On la fonction précédente pour en déduire les deux permutations les moins coûteuses puis on conserve le coût de cette permutation. On fait pour toutes les paires et on ne garde que la meilleure paire."
529+
"Tout est cohérent."
399530
]
400531
},
401532
{

0 commit comments

Comments
 (0)