From ccecc1c28fc6b12279503634df8e84ea9eb3e9af Mon Sep 17 00:00:00 2001 From: jsboige Date: Mon, 26 Oct 2026 17:59:05 +0100 Subject: [PATCH 1/2] Add(Search,#22688): Search-01 -- exemple guide credite (missionnaires et cannibales) et exercice 6 (cruches d'eau) Integration du TP MIS #22688 cote Python : l'exercice 1 devient un exemple guide credite a la PR, avec une resolution par recherche en largeur (11 traversees, 20 etats valides sur 32 triplets). Un exercice 6 non resolu le remplace (cruches de 3 L et 5 L, cible 4 L). Carnet re-execute de bout en bout sous Python 3.13 (61 cellules, 0 erreur). Jumeau C# : portage sous #22680. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../Search-01-StateSpace.ipynb | 853 ++++++++++-------- .../twin_pairs.d/search-01-statespace.yaml | 1 + 2 files changed, 487 insertions(+), 367 deletions(-) diff --git a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-01-StateSpace.ipynb b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-01-StateSpace.ipynb index 218d8676f60..0d6016064ec 100644 --- a/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-01-StateSpace.ipynb +++ b/MyIA.AI.Notebooks/Search/Part1-Foundations/Search-01-StateSpace.ipynb @@ -5,10 +5,10 @@ "id": "nav-header", "metadata": { "papermill": { - "duration": 0.009366, - "end_time": "2026-10-26T10:55:52.679187+00:00", + "duration": 0.004761, + "end_time": "2026-10-26T16:56:25.654510+00:00", "exception": false, - "start_time": "2026-10-26T10:55:52.669821+00:00", + "start_time": "2026-10-26T16:56:25.649749+00:00", "status": "completed" }, "tags": [] @@ -39,10 +39,10 @@ "id": "intro-section", "metadata": { "papermill": { - "duration": 0.004495, - "end_time": "2026-10-26T10:55:52.690286+00:00", + "duration": 0.00354, + "end_time": "2026-10-26T16:56:25.662000+00:00", "exception": false, - "start_time": "2026-10-26T10:55:52.685791+00:00", + "start_time": "2026-10-26T16:56:25.658460+00:00", "status": "completed" }, "tags": [] @@ -80,16 +80,16 @@ "id": "imports", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:52.700487Z", - "iopub.status.busy": "2026-10-26T10:55:52.700043Z", - "iopub.status.idle": "2026-10-26T10:55:53.600291Z", - "shell.execute_reply": "2026-10-26T10:55:53.599405Z" + "iopub.execute_input": "2026-10-26T16:56:25.669762Z", + "iopub.status.busy": "2026-10-26T16:56:25.669567Z", + "iopub.status.idle": "2026-10-26T16:56:27.405782Z", + "shell.execute_reply": "2026-10-26T16:56:27.404958Z" }, "papermill": { - "duration": 0.90788, - "end_time": "2026-10-26T10:55:53.601326+00:00", + "duration": 1.74153, + "end_time": "2026-10-26T16:56:27.406784+00:00", "exception": false, - "start_time": "2026-10-26T10:55:52.693446+00:00", + "start_time": "2026-10-26T16:56:25.665254+00:00", "status": "completed" }, "tags": [] @@ -124,10 +124,10 @@ "id": "formal-section", "metadata": { "papermill": { - "duration": 0.005454, - "end_time": "2026-10-26T10:55:53.612426+00:00", + "duration": 0.005659, + "end_time": "2026-10-26T16:56:27.417741+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.606972+00:00", + "start_time": "2026-10-26T16:56:27.412082+00:00", "status": "completed" }, "tags": [] @@ -161,10 +161,10 @@ "id": "abstract-class-intro", "metadata": { "papermill": { - "duration": 0.005712, - "end_time": "2026-10-26T10:55:53.624239+00:00", + "duration": 0.00551, + "end_time": "2026-10-26T16:56:27.427613+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.618527+00:00", + "start_time": "2026-10-26T16:56:27.422103+00:00", "status": "completed" }, "tags": [] @@ -181,16 +181,16 @@ "id": "abstract-class", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:53.637089Z", - "iopub.status.busy": "2026-10-26T10:55:53.636546Z", - "iopub.status.idle": "2026-10-26T10:55:53.643876Z", - "shell.execute_reply": "2026-10-26T10:55:53.642744Z" + "iopub.execute_input": "2026-10-26T16:56:27.440594Z", + "iopub.status.busy": "2026-10-26T16:56:27.440245Z", + "iopub.status.idle": "2026-10-26T16:56:27.445435Z", + "shell.execute_reply": "2026-10-26T16:56:27.444577Z" }, "papermill": { - "duration": 0.015119, - "end_time": "2026-10-26T10:55:53.644885+00:00", + "duration": 0.012829, + "end_time": "2026-10-26T16:56:27.446216+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.629766+00:00", + "start_time": "2026-10-26T16:56:27.433387+00:00", "status": "completed" }, "tags": [] @@ -252,10 +252,10 @@ "id": "vacuum-section", "metadata": { "papermill": { - "duration": 0.006419, - "end_time": "2026-10-26T10:55:53.657652+00:00", + "duration": 0.004087, + "end_time": "2026-10-26T16:56:27.456662+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.651233+00:00", + "start_time": "2026-10-26T16:56:27.452575+00:00", "status": "completed" }, "tags": [] @@ -287,16 +287,16 @@ "id": "vacuum-impl", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:53.671591Z", - "iopub.status.busy": "2026-10-26T10:55:53.671166Z", - "iopub.status.idle": "2026-10-26T10:55:53.680315Z", - "shell.execute_reply": "2026-10-26T10:55:53.679299Z" + "iopub.execute_input": "2026-10-26T16:56:27.468491Z", + "iopub.status.busy": "2026-10-26T16:56:27.468316Z", + "iopub.status.idle": "2026-10-26T16:56:27.474707Z", + "shell.execute_reply": "2026-10-26T16:56:27.474012Z" }, "papermill": { - "duration": 0.017661, - "end_time": "2026-10-26T10:55:53.681387+00:00", + "duration": 0.013062, + "end_time": "2026-10-26T16:56:27.475615+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.663726+00:00", + "start_time": "2026-10-26T16:56:27.462553+00:00", "status": "completed" }, "tags": [] @@ -389,10 +389,10 @@ "id": "vacuum-interpretation", "metadata": { "papermill": { - "duration": 0.005517, - "end_time": "2026-10-26T10:55:53.693183+00:00", + "duration": 0.005101, + "end_time": "2026-10-26T16:56:27.486333+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.687666+00:00", + "start_time": "2026-10-26T16:56:27.481232+00:00", "status": "completed" }, "tags": [] @@ -418,10 +418,10 @@ "id": "vacuum-trace-intro", "metadata": { "papermill": { - "duration": 0.006689, - "end_time": "2026-10-26T10:55:53.705953+00:00", + "duration": 0.003953, + "end_time": "2026-10-26T16:56:27.496473+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.699264+00:00", + "start_time": "2026-10-26T16:56:27.492520+00:00", "status": "completed" }, "tags": [] @@ -438,16 +438,16 @@ "id": "vacuum-trace", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:53.739295Z", - "iopub.status.busy": "2026-10-26T10:55:53.738976Z", - "iopub.status.idle": "2026-10-26T10:55:53.746337Z", - "shell.execute_reply": "2026-10-26T10:55:53.745305Z" + "iopub.execute_input": "2026-10-26T16:56:27.503823Z", + "iopub.status.busy": "2026-10-26T16:56:27.503580Z", + "iopub.status.idle": "2026-10-26T16:56:27.510369Z", + "shell.execute_reply": "2026-10-26T16:56:27.509700Z" }, "papermill": { - "duration": 0.015342, - "end_time": "2026-10-26T10:55:53.747210+00:00", + "duration": 0.012158, + "end_time": "2026-10-26T16:56:27.511669+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.731868+00:00", + "start_time": "2026-10-26T16:56:27.499511+00:00", "status": "completed" }, "tags": [] @@ -517,10 +517,10 @@ "id": "vacuum-trace-interpretation", "metadata": { "papermill": { - "duration": 0.006523, - "end_time": "2026-10-26T10:55:53.759782+00:00", + "duration": 0.004121, + "end_time": "2026-10-26T16:56:27.520404+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.753259+00:00", + "start_time": "2026-10-26T16:56:27.516283+00:00", "status": "completed" }, "tags": [] @@ -547,10 +547,10 @@ "id": "vacuum-graph-intro", "metadata": { "papermill": { - "duration": 0.006328, - "end_time": "2026-10-26T10:55:53.772073+00:00", + "duration": 0.003661, + "end_time": "2026-10-26T16:56:27.527205+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.765745+00:00", + "start_time": "2026-10-26T16:56:27.523544+00:00", "status": "completed" }, "tags": [] @@ -567,16 +567,16 @@ "id": "vacuum-graph", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:53.786919Z", - "iopub.status.busy": "2026-10-26T10:55:53.786557Z", - "iopub.status.idle": "2026-10-26T10:55:53.994961Z", - "shell.execute_reply": "2026-10-26T10:55:53.993779Z" + "iopub.execute_input": "2026-10-26T16:56:27.539510Z", + "iopub.status.busy": "2026-10-26T16:56:27.539258Z", + "iopub.status.idle": "2026-10-26T16:56:27.826474Z", + "shell.execute_reply": "2026-10-26T16:56:27.825257Z" }, "papermill": { - "duration": 0.217076, - "end_time": "2026-10-26T10:55:53.995889+00:00", + "duration": 0.295142, + "end_time": "2026-10-26T16:56:27.827424+00:00", "exception": false, - "start_time": "2026-10-26T10:55:53.778813+00:00", + "start_time": "2026-10-26T16:56:27.532282+00:00", "status": "completed" }, "tags": [] @@ -699,10 +699,10 @@ "id": "vacuum-graph-interpretation", "metadata": { "papermill": { - "duration": 0.007837, - "end_time": "2026-10-26T10:55:54.011432+00:00", + "duration": 0.005315, + "end_time": "2026-10-26T16:56:27.838367+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.003595+00:00", + "start_time": "2026-10-26T16:56:27.833052+00:00", "status": "completed" }, "tags": [] @@ -730,10 +730,10 @@ "id": "puzzle-section", "metadata": { "papermill": { - "duration": 0.00713, - "end_time": "2026-10-26T10:55:54.026568+00:00", + "duration": 0.007284, + "end_time": "2026-10-26T16:56:27.851644+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.019438+00:00", + "start_time": "2026-10-26T16:56:27.844360+00:00", "status": "completed" }, "tags": [] @@ -765,16 +765,16 @@ "id": "puzzle-impl", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:54.041892Z", - "iopub.status.busy": "2026-10-26T10:55:54.041348Z", - "iopub.status.idle": "2026-10-26T10:55:54.051138Z", - "shell.execute_reply": "2026-10-26T10:55:54.050101Z" + "iopub.execute_input": "2026-10-26T16:56:27.867920Z", + "iopub.status.busy": "2026-10-26T16:56:27.867486Z", + "iopub.status.idle": "2026-10-26T16:56:27.875445Z", + "shell.execute_reply": "2026-10-26T16:56:27.874393Z" }, "papermill": { - "duration": 0.018844, - "end_time": "2026-10-26T10:55:54.052266+00:00", + "duration": 0.017681, + "end_time": "2026-10-26T16:56:27.876241+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.033422+00:00", + "start_time": "2026-10-26T16:56:27.858560+00:00", "status": "completed" }, "tags": [] @@ -858,10 +858,10 @@ "id": "puzzle-viz-intro", "metadata": { "papermill": { - "duration": 0.007994, - "end_time": "2026-10-26T10:55:54.067336+00:00", + "duration": 0.006541, + "end_time": "2026-10-26T16:56:27.890356+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.059342+00:00", + "start_time": "2026-10-26T16:56:27.883815+00:00", "status": "completed" }, "tags": [] @@ -878,16 +878,16 @@ "id": "puzzle-viz", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:54.085835Z", - "iopub.status.busy": "2026-10-26T10:55:54.085197Z", - "iopub.status.idle": "2026-10-26T10:55:54.268976Z", - "shell.execute_reply": "2026-10-26T10:55:54.267410Z" + "iopub.execute_input": "2026-10-26T16:56:27.903237Z", + "iopub.status.busy": "2026-10-26T16:56:27.903036Z", + "iopub.status.idle": "2026-10-26T16:56:28.046527Z", + "shell.execute_reply": "2026-10-26T16:56:28.045370Z" }, "papermill": { - "duration": 0.195494, - "end_time": "2026-10-26T10:55:54.270820+00:00", + "duration": 0.150421, + "end_time": "2026-10-26T16:56:28.047136+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.075326+00:00", + "start_time": "2026-10-26T16:56:27.896715+00:00", "status": "completed" }, "tags": [] @@ -972,10 +972,10 @@ "id": "puzzle-moves-intro", "metadata": { "papermill": { - "duration": 0.007516, - "end_time": "2026-10-26T10:55:54.286812+00:00", + "duration": 0.005937, + "end_time": "2026-10-26T16:56:28.058163+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.279296+00:00", + "start_time": "2026-10-26T16:56:28.052226+00:00", "status": "completed" }, "tags": [] @@ -992,16 +992,16 @@ "id": "puzzle-moves", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:54.306208Z", - "iopub.status.busy": "2026-10-26T10:55:54.305762Z", - "iopub.status.idle": "2026-10-26T10:55:54.600954Z", - "shell.execute_reply": "2026-10-26T10:55:54.599815Z" + "iopub.execute_input": "2026-10-26T16:56:28.073123Z", + "iopub.status.busy": "2026-10-26T16:56:28.072769Z", + "iopub.status.idle": "2026-10-26T16:56:28.276805Z", + "shell.execute_reply": "2026-10-26T16:56:28.274274Z" }, "papermill": { - "duration": 0.306281, - "end_time": "2026-10-26T10:55:54.601773+00:00", + "duration": 0.214555, + "end_time": "2026-10-26T16:56:28.278054+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.295492+00:00", + "start_time": "2026-10-26T16:56:28.063499+00:00", "status": "completed" }, "tags": [] @@ -1056,10 +1056,10 @@ "id": "puzzle-moves-interpretation", "metadata": { "papermill": { - "duration": 0.008733, - "end_time": "2026-10-26T10:55:54.619479+00:00", + "duration": 0.00854, + "end_time": "2026-10-26T16:56:28.293172+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.610746+00:00", + "start_time": "2026-10-26T16:56:28.284632+00:00", "status": "completed" }, "tags": [] @@ -1088,10 +1088,10 @@ "id": "route-section", "metadata": { "papermill": { - "duration": 0.009159, - "end_time": "2026-10-26T10:55:54.637669+00:00", + "duration": 0.007772, + "end_time": "2026-10-26T16:56:28.312420+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.628510+00:00", + "start_time": "2026-10-26T16:56:28.304648+00:00", "status": "completed" }, "tags": [] @@ -1120,16 +1120,16 @@ "id": "route-impl", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:54.657835Z", - "iopub.status.busy": "2026-10-26T10:55:54.657353Z", - "iopub.status.idle": "2026-10-26T10:55:54.667891Z", - "shell.execute_reply": "2026-10-26T10:55:54.666588Z" + "iopub.execute_input": "2026-10-26T16:56:28.329481Z", + "iopub.status.busy": "2026-10-26T16:56:28.329288Z", + "iopub.status.idle": "2026-10-26T16:56:28.337433Z", + "shell.execute_reply": "2026-10-26T16:56:28.336394Z" }, "papermill": { - "duration": 0.022247, - "end_time": "2026-10-26T10:55:54.668833+00:00", + "duration": 0.019017, + "end_time": "2026-10-26T16:56:28.338440+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.646586+00:00", + "start_time": "2026-10-26T16:56:28.319423+00:00", "status": "completed" }, "tags": [] @@ -1219,10 +1219,10 @@ "id": "route-viz-intro", "metadata": { "papermill": { - "duration": 0.008246, - "end_time": "2026-10-26T10:55:54.686331+00:00", + "duration": 0.008282, + "end_time": "2026-10-26T16:56:28.354155+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.678085+00:00", + "start_time": "2026-10-26T16:56:28.345873+00:00", "status": "completed" }, "tags": [] @@ -1239,16 +1239,16 @@ "id": "route-viz", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:54.705133Z", - "iopub.status.busy": "2026-10-26T10:55:54.704711Z", - "iopub.status.idle": "2026-10-26T10:55:54.967272Z", - "shell.execute_reply": "2026-10-26T10:55:54.965993Z" + "iopub.execute_input": "2026-10-26T16:56:28.373363Z", + "iopub.status.busy": "2026-10-26T16:56:28.372982Z", + "iopub.status.idle": "2026-10-26T16:56:28.624357Z", + "shell.execute_reply": "2026-10-26T16:56:28.623399Z" }, "papermill": { - "duration": 0.273548, - "end_time": "2026-10-26T10:55:54.968272+00:00", + "duration": 0.262475, + "end_time": "2026-10-26T16:56:28.625148+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.694724+00:00", + "start_time": "2026-10-26T16:56:28.362673+00:00", "status": "completed" }, "tags": [] @@ -1367,10 +1367,10 @@ "id": "route-viz-interpretation", "metadata": { "papermill": { - "duration": 0.010388, - "end_time": "2026-10-26T10:55:54.989277+00:00", + "duration": 0.01033, + "end_time": "2026-10-26T16:56:28.645368+00:00", "exception": false, - "start_time": "2026-10-26T10:55:54.978889+00:00", + "start_time": "2026-10-26T16:56:28.635038+00:00", "status": "completed" }, "tags": [] @@ -1398,10 +1398,10 @@ "id": "route-path-intro", "metadata": { "papermill": { - "duration": 0.010712, - "end_time": "2026-10-26T10:55:55.011369+00:00", + "duration": 0.010156, + "end_time": "2026-10-26T16:56:28.665462+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.000657+00:00", + "start_time": "2026-10-26T16:56:28.655306+00:00", "status": "completed" }, "tags": [] @@ -1418,16 +1418,16 @@ "id": "route-comparison", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.034333Z", - "iopub.status.busy": "2026-10-26T10:55:55.033886Z", - "iopub.status.idle": "2026-10-26T10:55:55.042654Z", - "shell.execute_reply": "2026-10-26T10:55:55.041304Z" + "iopub.execute_input": "2026-10-26T16:56:28.687697Z", + "iopub.status.busy": "2026-10-26T16:56:28.687412Z", + "iopub.status.idle": "2026-10-26T16:56:28.694622Z", + "shell.execute_reply": "2026-10-26T16:56:28.693746Z" }, "papermill": { - "duration": 0.021187, - "end_time": "2026-10-26T10:55:55.043675+00:00", + "duration": 0.019699, + "end_time": "2026-10-26T16:56:28.695343+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.022488+00:00", + "start_time": "2026-10-26T16:56:28.675644+00:00", "status": "completed" }, "tags": [] @@ -1504,10 +1504,10 @@ "id": "route-comparison-interpretation", "metadata": { "papermill": { - "duration": 0.01092, - "end_time": "2026-10-26T10:55:55.065809+00:00", + "duration": 0.007605, + "end_time": "2026-10-26T16:56:28.708938+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.054889+00:00", + "start_time": "2026-10-26T16:56:28.701333+00:00", "status": "completed" }, "tags": [] @@ -1535,16 +1535,16 @@ "id": "route-viz-path", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.088629Z", - "iopub.status.busy": "2026-10-26T10:55:55.088195Z", - "iopub.status.idle": "2026-10-26T10:55:55.349602Z", - "shell.execute_reply": "2026-10-26T10:55:55.348196Z" + "iopub.execute_input": "2026-10-26T16:56:28.726908Z", + "iopub.status.busy": "2026-10-26T16:56:28.726711Z", + "iopub.status.idle": "2026-10-26T16:56:28.964297Z", + "shell.execute_reply": "2026-10-26T16:56:28.962976Z" }, "papermill": { - "duration": 0.274607, - "end_time": "2026-10-26T10:55:55.350804+00:00", + "duration": 0.247892, + "end_time": "2026-10-26T16:56:28.965303+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.076197+00:00", + "start_time": "2026-10-26T16:56:28.717411+00:00", "status": "completed" }, "tags": [] @@ -1572,10 +1572,10 @@ "id": "2e9016aa", "metadata": { "papermill": { - "duration": 0.013324, - "end_time": "2026-10-26T10:55:55.377670+00:00", + "duration": 0.011355, + "end_time": "2026-10-26T16:56:28.988621+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.364346+00:00", + "start_time": "2026-10-26T16:56:28.977266+00:00", "status": "completed" }, "tags": [] @@ -1594,16 +1594,16 @@ "id": "a4a6bbe4", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.404775Z", - "iopub.status.busy": "2026-10-26T10:55:55.404364Z", - "iopub.status.idle": "2026-10-26T10:55:55.413710Z", - "shell.execute_reply": "2026-10-26T10:55:55.412580Z" + "iopub.execute_input": "2026-10-26T16:56:29.013582Z", + "iopub.status.busy": "2026-10-26T16:56:29.013149Z", + "iopub.status.idle": "2026-10-26T16:56:29.022305Z", + "shell.execute_reply": "2026-10-26T16:56:29.021093Z" }, "papermill": { - "duration": 0.024681, - "end_time": "2026-10-26T10:55:55.414697+00:00", + "duration": 0.023338, + "end_time": "2026-10-26T16:56:29.023235+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.390016+00:00", + "start_time": "2026-10-26T16:56:28.999897+00:00", "status": "completed" }, "tags": [] @@ -1651,10 +1651,10 @@ "id": "c33f42e5", "metadata": { "papermill": { - "duration": 0.016648, - "end_time": "2026-10-26T10:55:55.444241+00:00", + "duration": 0.012495, + "end_time": "2026-10-26T16:56:29.044528+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.427593+00:00", + "start_time": "2026-10-26T16:56:29.032033+00:00", "status": "completed" }, "tags": [] @@ -1672,10 +1672,10 @@ "id": "properties-section", "metadata": { "papermill": { - "duration": 0.013694, - "end_time": "2026-10-26T10:55:55.471135+00:00", + "duration": 0.011932, + "end_time": "2026-10-26T16:56:29.068316+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.457441+00:00", + "start_time": "2026-10-26T16:56:29.056384+00:00", "status": "completed" }, "tags": [] @@ -1694,16 +1694,16 @@ "id": "properties-table", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.499503Z", - "iopub.status.busy": "2026-10-26T10:55:55.499033Z", - "iopub.status.idle": "2026-10-26T10:55:55.506250Z", - "shell.execute_reply": "2026-10-26T10:55:55.505041Z" + "iopub.execute_input": "2026-10-26T16:56:29.091420Z", + "iopub.status.busy": "2026-10-26T16:56:29.091168Z", + "iopub.status.idle": "2026-10-26T16:56:29.098082Z", + "shell.execute_reply": "2026-10-26T16:56:29.097017Z" }, "papermill": { - "duration": 0.023351, - "end_time": "2026-10-26T10:55:55.507304+00:00", + "duration": 0.01944, + "end_time": "2026-10-26T16:56:29.098934+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.483953+00:00", + "start_time": "2026-10-26T16:56:29.079494+00:00", "status": "completed" }, "tags": [] @@ -1760,10 +1760,10 @@ "id": "properties-interpretation", "metadata": { "papermill": { - "duration": 0.013148, - "end_time": "2026-10-26T10:55:55.533162+00:00", + "duration": 0.0122, + "end_time": "2026-10-26T16:56:29.122595+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.520014+00:00", + "start_time": "2026-10-26T16:56:29.110395+00:00", "status": "completed" }, "tags": [] @@ -1797,10 +1797,10 @@ "id": "exercises-section", "metadata": { "papermill": { - "duration": 0.013222, - "end_time": "2026-10-26T10:55:55.558976+00:00", + "duration": 0.007344, + "end_time": "2026-10-26T16:56:29.139816+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.545754+00:00", + "start_time": "2026-10-26T16:56:29.132472+00:00", "status": "completed" }, "tags": [] @@ -1808,15 +1808,21 @@ "source": [ "## 7. Exercices\n", "\n", - "### Exercice 1 : Missionnaires et Cannibales\n", + "### Exemple guidé — Missionnaires et cannibales\n", "\n", - "Trois missionnaires et trois cannibales doivent traverser une riviere dans un bateau qui ne peut transporter que 2 personnes. Si les cannibales sont plus nombreux que les missionnaires sur une rive, les missionnaires sont devores.\n", + "*Exercice 1 résolu dans la PR #22688 et repris ici comme exemple guidé.*\n", "\n", - "**Tâche** : Modelisez ce problème comme un `SearchProblem`.\n", + "Trois missionnaires et trois cannibales doivent traverser une rivière dans un bateau qui ne peut transporter que 2 personnes. Si les cannibales sont plus nombreux que les missionnaires sur une rive, les missionnaires sont dévorés.\n", "\n", - "- Etat : `(m_gauche, c_gauche, bateau)` ou `m_gauche` = missionnaires sur la rive gauche, `c_gauche` = cannibales sur la rive gauche, `bateau` = 'G' ou 'D'\n", - "- Actions : nombre de missionnaires et cannibales dans le bateau\n", - "- Contrainte : jamais plus de cannibales que de missionnaires sur une rive (sauf si 0 missionnaires)" + "**Modélisation** :\n", + "- État : `(m_gauche, c_gauche, bateau)` où `m_gauche` = missionnaires sur la rive gauche, `c_gauche` = cannibales sur la rive gauche, `bateau` = 'G' ou 'D'\n", + "- Actions : nombre de missionnaires et de cannibales dans le bateau, `(m, c)` avec $1 \\le m + c \\le 2$\n", + "- Contrainte : jamais plus de cannibales que de missionnaires sur une rive (sauf si cette rive n'a aucun missionnaire)\n", + "\n", + "**Ce que montre la solution** :\n", + "- `_is_valid` contrôle les **deux** rives : la rive droite se déduit de la gauche (`3 - m_gauche`, `3 - c_gauche`), il n'est donc pas nécessaire de la stocker dans l'état ;\n", + "- `actions` ne propose que les chargements possibles depuis la rive où se trouve le bateau, puis écarte ceux qui mèneraient à un état non sûr : depuis l'état initial, `(2, 0)` est refusé parce qu'il laisserait 1 missionnaire face à 3 cannibales sur la rive gauche ;\n", + "- `state_space_size` énumère les 32 triplets `(m, c, bateau)` et compte ceux qui sont sûrs." ] }, { @@ -1825,16 +1831,16 @@ "id": "exercise1", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.585998Z", - "iopub.status.busy": "2026-10-26T10:55:55.585574Z", - "iopub.status.idle": "2026-10-26T10:55:55.593278Z", - "shell.execute_reply": "2026-10-26T10:55:55.591978Z" + "iopub.execute_input": "2026-10-26T16:56:29.159391Z", + "iopub.status.busy": "2026-10-26T16:56:29.158804Z", + "iopub.status.idle": "2026-10-26T16:56:29.166128Z", + "shell.execute_reply": "2026-10-26T16:56:29.165184Z" }, "papermill": { - "duration": 0.023387, - "end_time": "2026-10-26T10:55:55.594651+00:00", + "duration": 0.017899, + "end_time": "2026-10-26T16:56:29.166897+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.571264+00:00", + "start_time": "2026-10-26T16:56:29.148998+00:00", "status": "completed" }, "tags": [] @@ -1844,65 +1850,83 @@ "name": "stdout", "output_type": "stream", "text": [ - "Exercice a completer\n" + "Etat initial : (3, 3, 'G') (3M, 3C a gauche, bateau a gauche)\n", + "Nombre d'etats valides : 20 (sur 4 x 4 x 2 = 32 triplets)\n", + "Actions possibles : [(0, 1), (0, 2), (1, 1)]\n", + " (m, c) = nombre de missionnaires et cannibales dans le bateau\n" ] } ], "source": [ "class MissionariesCannibals(SearchProblem):\n", " \"\"\"\n", - " Exercice 1 : Missionnaires et Cannibales.\n", - " \n", + " Exemple guide (solution de la PR #22688) : Missionnaires et Cannibales.\n", + "\n", " Etat : (missionnaires_gauche, cannibales_gauche, position_bateau)\n", " Etat initial : (3, 3, 'G') - tout le monde a gauche\n", " But : (0, 0, 'D') - tout le monde a droite\n", - " \n", - " Indices:\n", - " - initial_state() retourne le tuple (3, 3, 'G')\n", - " - _is_valid() verifie que sur chaque rive, si m > 0 alors m >= c\n", - " - actions() genere les paires (m, c) avec 1 <= m+c <= 2\n", - " - transition() deplace m missionnaires et c cannibales selon la position du bateau\n", - " - is_goal() verifie si on a atteint (0, 0, 'D')\n", " \"\"\"\n", - " \n", + "\n", " def initial_state(self):\n", - " # TODO etudiant : retourner l'etat initial\n", - " return None # TODO etudiant\n", - " \n", + " return (3, 3, 'G')\n", + "\n", " def _is_valid(self, state) -> bool:\n", " \"\"\"Verifie que l'etat est valide (pas de missionnaire devore).\"\"\"\n", - " # TODO etudiant : verifier bornes (0 <= m,c <= 3) et securite sur chaque rive\n", - " return None # TODO etudiant\n", - " \n", + " m_g, c_g, b = state\n", + " m_d, c_d = 3 - m_g, 3 - c_g\n", + "\n", + " if not (0 <= m_g <= 3 and 0 <= c_g <= 3):\n", + " return False\n", + " if m_g > 0 and c_g > m_g:\n", + " return False\n", + " if m_d > 0 and c_d > m_d:\n", + " return False\n", + " return True\n", + "\n", " def actions(self, state) -> List[Tuple[int, int]]:\n", " \"\"\"Retourne les actions possibles : (missionnaires, cannibales) dans le bateau.\"\"\"\n", - " # TODO etudiant : generer toutes les paires (m, c) avec 1 <= m+c <= 2\n", - " # Filtrer selon la rive du bateau et valider l'etat resultat\n", - " return None # TODO etudiant\n", - " \n", + " m_g, c_g, b = state\n", + " if b == 'G':\n", + " m_dispo, c_dispo = m_g, c_g\n", + " else:\n", + " m_dispo, c_dispo = 3 - m_g, 3 - c_g\n", + "\n", + " result = []\n", + " for m in range(3):\n", + " for c in range(3):\n", + " if 1 <= m + c <= 2 and m <= m_dispo and c <= c_dispo:\n", + " if self._is_valid(self.transition(state, (m, c))):\n", + " result.append((m, c))\n", + " return result\n", + "\n", " def transition(self, state, action):\n", - " # TODO etudiant : appliquer l'action (m, c) selon la position du bateau\n", - " return None # TODO etudiant\n", - " \n", + " m_g, c_g, b = state\n", + " m, c = action\n", + " if b == 'G':\n", + " return (m_g - m, c_g - c, 'D')\n", + " else:\n", + " return (m_g + m, c_g + c, 'G')\n", + "\n", " def is_goal(self, state) -> bool:\n", - " # TODO etudiant : verifier si tout le monde est a droite\n", - " return None # TODO etudiant\n", - " \n", + " return state == (0, 0, 'D')\n", + "\n", " def state_space_size(self) -> int:\n", " \"\"\"Compte le nombre d'etats valides.\"\"\"\n", - " # TODO etudiant : enumerer tous les (m, c, b) possibles et compter les valides\n", - " return None # TODO etudiant\n", - "\n", + " return sum(\n", + " 1\n", + " for m in range(4)\n", + " for c in range(4)\n", + " for b in ('G', 'D')\n", + " if self._is_valid((m, c, b))\n", + " )\n", "\n", - "# --- Test (decommentez apres avoir complete l'exercice ci-dessus) ---\n", - "# mc = MissionariesCannibals()\n", - "# s0 = mc.initial_state()\n", - "# print(f\"Etat initial : {s0} (3M, 3C a gauche, bateau a gauche)\")\n", - "# print(f\"Nombre d'etats valides : {mc.state_space_size()}\")\n", - "# print(f\"Actions possibles : {mc.actions(s0)}\")\n", - "# print(\" (m, c) = nombre de missionnaires et cannibales dans le bateau\")\n", "\n", - "print(\"Exercice a completer\")" + "mc = MissionariesCannibals()\n", + "s0 = mc.initial_state()\n", + "print(f\"Etat initial : {s0} (3M, 3C a gauche, bateau a gauche)\")\n", + "print(f\"Nombre d'etats valides : {mc.state_space_size()} (sur 4 x 4 x 2 = 32 triplets)\")\n", + "print(f\"Actions possibles : {mc.actions(s0)}\")\n", + "print(\" (m, c) = nombre de missionnaires et cannibales dans le bateau\")" ] }, { @@ -1910,47 +1934,23 @@ "id": "exercise1-solution-intro", "metadata": { "papermill": { - "duration": 0.011461, - "end_time": "2026-10-26T10:55:55.618437+00:00", + "duration": 0.008846, + "end_time": "2026-10-26T16:56:29.184108+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.606976+00:00", + "start_time": "2026-10-26T16:56:29.175262+00:00", "status": "completed" }, "tags": [] }, "source": [ - "> **Indices pour l'exercice 1 :**\n", - "\n", - "**Rappels** :\n", - "- Utilisez une recherche en largeur (BFS) pour explorer l'espace d'etats\n", - "- La file (deque) contient des paires `(etat, liste_actions)`\n", - "- Pensez a marquer les etats visites pour eviter les boucles\n", - "- La condition d'arret est `problem.is_goal(state)`\n", - "\n", - "```python\n", - "from collections import deque\n", - "\n", - "def bfs_solve(problem: SearchProblem):\n", - " # TODO: Implementez la recherche en largeur\n", - " start = problem.initial_state()\n", - " queue = deque([(start, [])])\n", - " visited = {start}\n", - "\n", - " while queue:\n", - " state, path = queue.popleft()\n", - "\n", - " if problem.is_goal(state):\n", - " return path, state\n", - "\n", - " for action in problem.actions(state):\n", - " next_state = problem.transition(state, action)\n", + "### Résolution par recherche en largeur\n", "\n", - " if next_state not in visited:\n", - " visited.add(next_state)\n", - " queue.append((next_state, path + [action]))\n", + "La cellule suivante définit `bfs_solve`, une recherche en largeur (BFS) que le labyrinthe et les exercices réutilisent plus bas :\n", + "- la file (`deque`) contient des paires `(état, liste_actions)` ;\n", + "- un ensemble `visited` marque les états déjà rencontrés : sans lui, les allers-retours du bateau feraient tourner la recherche indéfiniment ;\n", + "- la recherche s'arrête au premier état qui vérifie `problem.is_goal(state)`.\n", "\n", - " return None, None\n", - "```" + "Comme chaque traversée coûte 1, le premier chemin trouvé par BFS est aussi le plus court en nombre de traversées." ] }, { @@ -1959,16 +1959,16 @@ "id": "exercise1-bfs", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.645054Z", - "iopub.status.busy": "2026-10-26T10:55:55.644742Z", - "iopub.status.idle": "2026-10-26T10:55:55.653687Z", - "shell.execute_reply": "2026-10-26T10:55:55.652474Z" + "iopub.execute_input": "2026-10-26T16:56:29.201387Z", + "iopub.status.busy": "2026-10-26T16:56:29.201113Z", + "iopub.status.idle": "2026-10-26T16:56:29.208659Z", + "shell.execute_reply": "2026-10-26T16:56:29.207626Z" }, "papermill": { - "duration": 0.023043, - "end_time": "2026-10-26T10:55:55.654672+00:00", + "duration": 0.016502, + "end_time": "2026-10-26T16:56:29.209560+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.631629+00:00", + "start_time": "2026-10-26T16:56:29.193058+00:00", "status": "completed" }, "tags": [] @@ -1978,8 +1978,22 @@ "name": "stdout", "output_type": "stream", "text": [ - "Completez la classe MissionariesCannibals pour voir la solution.\n", - "Pas de solution trouvee.\n" + "Solution trouvee en 11 traversees :\n", + "\n", + "Etape Action (M,C) Rive gauche Rive droite Bateau\n", + "---------------------------------------------------------------------------\n", + "init - 3M 3C 0M 0C G\n", + "1 (0, 2) -> 3M 1C 0M 2C D\n", + "2 (0, 1) <- 3M 2C 0M 1C G\n", + "3 (0, 2) -> 3M 0C 0M 3C D\n", + "4 (0, 1) <- 3M 1C 0M 2C G\n", + "5 (2, 0) -> 1M 1C 2M 2C D\n", + "6 (1, 1) <- 2M 2C 1M 1C G\n", + "7 (2, 0) -> 0M 2C 3M 1C D\n", + "8 (0, 1) <- 0M 3C 3M 0C G\n", + "9 (0, 2) -> 0M 1C 3M 2C D\n", + "10 (0, 1) <- 0M 2C 3M 1C G\n", + "11 (0, 2) -> 0M 0C 3M 3C D\n" ] } ], @@ -1989,29 +2003,24 @@ " start = problem.initial_state()\n", " queue = deque([(start, [])]) # (etat, liste_actions)\n", " visited = {start}\n", - " \n", + "\n", " while queue:\n", " state, path = queue.popleft()\n", - " \n", + "\n", " if problem.is_goal(state):\n", " return path, state\n", - " \n", + "\n", " for action in problem.actions(state):\n", " next_state = problem.transition(state, action)\n", " if next_state not in visited:\n", " visited.add(next_state)\n", " queue.append((next_state, path + [action]))\n", - " \n", + "\n", " return None, None\n", "\n", "\n", "# Resoudre Missionnaires et Cannibales\n", - "try:\n", - " mc = MissionariesCannibals()\n", - " solution, final = bfs_solve(mc)\n", - "except (NameError, NotImplementedError, TypeError):\n", - " solution = None\n", - " print(\"Completez la classe MissionariesCannibals pour voir la solution.\")\n", + "solution, final = bfs_solve(mc)\n", "\n", "if solution:\n", " print(f\"Solution trouvee en {len(solution)} traversees :\\n\")\n", @@ -2020,15 +2029,14 @@ " print(\"-\" * 75)\n", " m_g, c_g, b = state\n", " print(f\"{'init':<8} {'-':<15} {f'{m_g}M {c_g}C':<20} {f'{3-m_g}M {3-c_g}C':<20} {b}\")\n", - " \n", + "\n", " for i, action in enumerate(solution, 1):\n", " state = mc.transition(state, action)\n", " m_g, c_g, b = state\n", " direction = \"->\" if b == 'D' else \"<-\"\n", " print(f\"{i:<8} {str(action) + ' ' + direction:<15} {f'{m_g}M {c_g}C':<20} {f'{3-m_g}M {3-c_g}C':<20} {b}\")\n", "else:\n", - " if 'mc' in dir():\n", - " print(\"Pas de solution trouvee.\")" + " print(\"Pas de solution trouvee.\")" ] }, { @@ -2036,25 +2044,30 @@ "id": "exercise1-interpretation", "metadata": { "papermill": { - "duration": 0.01307, - "end_time": "2026-10-26T10:55:55.681207+00:00", + "duration": 0.006926, + "end_time": "2026-10-26T16:56:29.223308+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.668137+00:00", + "start_time": "2026-10-26T16:56:29.216382+00:00", "status": "completed" }, "tags": [] }, "source": [ - "### Interpretation : Missionnaires et Cannibales\n", + "### Interprétation : Missionnaires et cannibales\n", "\n", - "**Sortie obtenue** : (Exercice non complete) - la classe MissionariesCannibals etant un squelette, BFS ne trouve aucune solution. Une fois completee, l'etudiant doit obtenir la solution optimale connue de 11 traversees.\n", + "**Sortie obtenue** : 20 états valides sur les 32 triplets possibles, et seulement trois chargements autorisés au départ, `(0, 1)`, `(0, 2)` et `(1, 1)`. BFS trouve une traversée en **11 étapes**. C'est la solution optimale connue : BFS rend le chemin le plus court en nombre de traversées.\n", "\n", - "**Points cles** :\n", - "1. L'espace d'etats est petit mais les contraintes le rendent non trivial\n", - "2. Le problème est **reversible** : le bateau doit revenir pour continuer les traversees\n", - "3. La contrainte de securite (pas plus de cannibales que de missionnaires) elimine de nombreux etats\n", + "**Lecture du tableau** :\n", + "1. Les quatre premières traversées ne font passer que des cannibales : tant que les trois missionnaires restent ensemble sur la rive gauche, aucune rive n'est en danger.\n", + "2. À l'étape 6, un missionnaire et un cannibale **reviennent** sur la rive de départ : la solution doit parfois s'éloigner du but pour l'atteindre.\n", + "3. Après l'étape 7, les trois missionnaires sont à droite, et le bateau ne fait plus que des allers-retours de cannibales.\n", + "\n", + "**Points clés** :\n", + "1. L'espace d'états est petit, mais les contraintes le rendent non trivial : la contrainte de sécurité élimine 12 des 32 triplets avant toute recherche.\n", + "2. Le problème est **réversible** : le bateau doit revenir pour continuer les traversées.\n", + "3. Le marquage des états visités est indispensable : chaque traversée peut être annulée par la traversée inverse.\n", "\n", - "> Ce problème illustre que la **taille de l'espace d'etats** ne determine pas a elle seule la difficulte. Les contraintes jouent un rôle crucial." + "> Ce problème illustre que la **taille de l'espace d'états** ne détermine pas à elle seule la difficulté. Les contraintes jouent un rôle crucial." ] }, { @@ -2062,10 +2075,10 @@ "id": "exercise2", "metadata": { "papermill": { - "duration": 0.01264, - "end_time": "2026-10-26T10:55:55.705064+00:00", + "duration": 0.007072, + "end_time": "2026-10-26T16:56:29.241627+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.692424+00:00", + "start_time": "2026-10-26T16:56:29.234555+00:00", "status": "completed" }, "tags": [] @@ -2092,16 +2105,16 @@ "id": "exercise2-solution", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.732211Z", - "iopub.status.busy": "2026-10-26T10:55:55.731894Z", - "iopub.status.idle": "2026-10-26T10:55:55.741218Z", - "shell.execute_reply": "2026-10-26T10:55:55.739872Z" + "iopub.execute_input": "2026-10-26T16:56:29.262441Z", + "iopub.status.busy": "2026-10-26T16:56:29.262127Z", + "iopub.status.idle": "2026-10-26T16:56:29.269383Z", + "shell.execute_reply": "2026-10-26T16:56:29.268324Z" }, "papermill": { - "duration": 0.024585, - "end_time": "2026-10-26T10:55:55.742183+00:00", + "duration": 0.02, + "end_time": "2026-10-26T16:56:29.269986+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.717598+00:00", + "start_time": "2026-10-26T16:56:29.249986+00:00", "status": "completed" }, "tags": [] @@ -2183,10 +2196,10 @@ "id": "exercise3", "metadata": { "papermill": { - "duration": 0.012731, - "end_time": "2026-10-26T10:55:55.769355+00:00", + "duration": 0.009771, + "end_time": "2026-10-26T16:56:29.286695+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.756624+00:00", + "start_time": "2026-10-26T16:56:29.276924+00:00", "status": "completed" }, "tags": [] @@ -2215,16 +2228,16 @@ "id": "exercise3-solution", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.797951Z", - "iopub.status.busy": "2026-10-26T10:55:55.797459Z", - "iopub.status.idle": "2026-10-26T10:55:55.809854Z", - "shell.execute_reply": "2026-10-26T10:55:55.808482Z" + "iopub.execute_input": "2026-10-26T16:56:29.312871Z", + "iopub.status.busy": "2026-10-26T16:56:29.312443Z", + "iopub.status.idle": "2026-10-26T16:56:29.323219Z", + "shell.execute_reply": "2026-10-26T16:56:29.322372Z" }, "papermill": { - "duration": 0.028716, - "end_time": "2026-10-26T10:55:55.811324+00:00", + "duration": 0.025787, + "end_time": "2026-10-26T16:56:29.323919+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.782608+00:00", + "start_time": "2026-10-26T16:56:29.298132+00:00", "status": "completed" }, "tags": [] @@ -2344,10 +2357,10 @@ "id": "e1rgwvl3j88", "metadata": { "papermill": { - "duration": 0.013255, - "end_time": "2026-10-26T10:55:55.837985+00:00", + "duration": 0.012193, + "end_time": "2026-10-26T16:56:29.345016+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.824730+00:00", + "start_time": "2026-10-26T16:56:29.332823+00:00", "status": "completed" }, "tags": [] @@ -2364,16 +2377,16 @@ "id": "exercise3-viz", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:55.864726Z", - "iopub.status.busy": "2026-10-26T10:55:55.864357Z", - "iopub.status.idle": "2026-10-26T10:55:56.077166Z", - "shell.execute_reply": "2026-10-26T10:55:56.075646Z" + "iopub.execute_input": "2026-10-26T16:56:29.369599Z", + "iopub.status.busy": "2026-10-26T16:56:29.369416Z", + "iopub.status.idle": "2026-10-26T16:56:29.553538Z", + "shell.execute_reply": "2026-10-26T16:56:29.552531Z" }, "papermill": { - "duration": 0.227474, - "end_time": "2026-10-26T10:55:56.078192+00:00", + "duration": 0.196464, + "end_time": "2026-10-26T16:56:29.554408+00:00", "exception": false, - "start_time": "2026-10-26T10:55:55.850718+00:00", + "start_time": "2026-10-26T16:56:29.357944+00:00", "status": "completed" }, "tags": [] @@ -2466,10 +2479,10 @@ "id": "exercise3-interpretation", "metadata": { "papermill": { - "duration": 0.013184, - "end_time": "2026-10-26T10:55:56.103920+00:00", + "duration": 0.01134, + "end_time": "2026-10-26T16:56:29.577627+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.090736+00:00", + "start_time": "2026-10-26T16:56:29.566287+00:00", "status": "completed" }, "tags": [] @@ -2503,10 +2516,10 @@ "id": "809678d1", "metadata": { "papermill": { - "duration": 0.012163, - "end_time": "2026-10-26T10:55:56.130572+00:00", + "duration": 0.012208, + "end_time": "2026-10-26T16:56:29.599636+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.118409+00:00", + "start_time": "2026-10-26T16:56:29.587428+00:00", "status": "completed" }, "tags": [] @@ -2533,16 +2546,16 @@ "id": "7d809015", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:56.159123Z", - "iopub.status.busy": "2026-10-26T10:55:56.158649Z", - "iopub.status.idle": "2026-10-26T10:55:56.164775Z", - "shell.execute_reply": "2026-10-26T10:55:56.163454Z" + "iopub.execute_input": "2026-10-26T16:56:29.621850Z", + "iopub.status.busy": "2026-10-26T16:56:29.621554Z", + "iopub.status.idle": "2026-10-26T16:56:29.627385Z", + "shell.execute_reply": "2026-10-26T16:56:29.626454Z" }, "papermill": { - "duration": 0.0224, - "end_time": "2026-10-26T10:55:56.166030+00:00", + "duration": 0.01842, + "end_time": "2026-10-26T16:56:29.628297+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.143630+00:00", + "start_time": "2026-10-26T16:56:29.609877+00:00", "status": "completed" }, "tags": [] @@ -2588,10 +2601,10 @@ "id": "fd8b6d03", "metadata": { "papermill": { - "duration": 0.013339, - "end_time": "2026-10-26T10:55:56.192554+00:00", + "duration": 0.010418, + "end_time": "2026-10-26T16:56:29.652268+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.179215+00:00", + "start_time": "2026-10-26T16:56:29.641850+00:00", "status": "completed" }, "tags": [] @@ -2619,16 +2632,16 @@ "id": "aa68b6c5", "metadata": { "execution": { - "iopub.execute_input": "2026-10-26T10:55:56.221554Z", - "iopub.status.busy": "2026-10-26T10:55:56.221098Z", - "iopub.status.idle": "2026-10-26T10:55:56.229369Z", - "shell.execute_reply": "2026-10-26T10:55:56.227905Z" + "iopub.execute_input": "2026-10-26T16:56:29.679748Z", + "iopub.status.busy": "2026-10-26T16:56:29.679376Z", + "iopub.status.idle": "2026-10-26T16:56:29.684378Z", + "shell.execute_reply": "2026-10-26T16:56:29.683222Z" }, "papermill": { - "duration": 0.024622, - "end_time": "2026-10-26T10:55:56.230523+00:00", + "duration": 0.020804, + "end_time": "2026-10-26T16:56:29.685193+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.205901+00:00", + "start_time": "2026-10-26T16:56:29.664389+00:00", "status": "completed" }, "tags": [] @@ -2690,13 +2703,118 @@ }, { "cell_type": "markdown", - "id": "4e165a9a", + "id": "58f031e4", + "metadata": { + "papermill": { + "duration": 0.009854, + "end_time": "2026-10-26T16:56:29.704619+00:00", + "exception": false, + "start_time": "2026-10-26T16:56:29.694765+00:00", + "status": "completed" + }, + "tags": [] + }, + "source": [ + "### Exercice 6 : Les cruches d'eau — tous les états ne sont pas atteignables\n", + "\n", + "On dispose d'une cruche A de 3 litres, d'une cruche B de 5 litres et d'un robinet. Les cruches n'ont pas de graduations. Le but est d'obtenir **exactement 4 litres** dans l'une des cruches.\n", + "\n", + "**Tâche** : compléter `WaterJugs`, dont l'état est `(litres_A, litres_B)`.\n", + "- `initial_state` : les deux cruches sont vides\n", + "- `actions` : parmi « Remplir A », « Remplir B », « Vider A », « Vider B », « Verser A->B », « Verser B->A », ne garder que celles qui changent l'état\n", + "- `transition` : un versement s'arrête quand la cruche source est vide ou que la cruche destination est pleine\n", + "- `is_goal` : l'une des deux cruches contient `cible` litres\n", + "- `state_space_size` : le nombre de contenus possibles, $(c_A + 1) \\times (c_B + 1)$\n", + "\n", + "**Vérification** : avec les cruches de 3 et 5 litres, `state_space_size` vaut 24 et BFS doit trouver une solution en 6 actions.\n", + "\n", + "**Question** : avec des cruches de 2 et 4 litres et une cible de 3 litres, BFS ne trouve aucune solution. Pourquoi ? Quelles quantités peuvent apparaître dans une cruche, quelles que soient les actions choisies ?" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "f6cc67d7", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-26T16:56:29.733190Z", + "iopub.status.busy": "2026-10-26T16:56:29.732753Z", + "iopub.status.idle": "2026-10-26T16:56:29.739555Z", + "shell.execute_reply": "2026-10-26T16:56:29.738415Z" + }, + "papermill": { + "duration": 0.023902, + "end_time": "2026-10-26T16:56:29.740388+00:00", + "exception": false, + "start_time": "2026-10-26T16:56:29.716486+00:00", + "status": "completed" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Exercice a completer\n" + ] + } + ], + "source": [ + "class WaterJugs(SearchProblem):\n", + " \"\"\"\n", + " Exercice 6 : deux cruches de capacites cap_a et cap_b litres, et un robinet.\n", + " Etat = (litres_A, litres_B). But : une cruche contient exactement `cible` litres.\n", + " \"\"\"\n", + "\n", + " ACTIONS = [\"Remplir A\", \"Remplir B\", \"Vider A\", \"Vider B\", \"Verser A->B\", \"Verser B->A\"]\n", + "\n", + " def __init__(self, cap_a: int = 3, cap_b: int = 5, cible: int = 4):\n", + " self.cap_a, self.cap_b, self.cible = cap_a, cap_b, cible\n", + "\n", + " def initial_state(self):\n", + " # TODO etudiant : les deux cruches sont vides\n", + " return None # TODO etudiant\n", + "\n", + " def actions(self, state) -> List[str]:\n", + " # TODO etudiant : garder les actions de ACTIONS dont la transition change l'etat\n", + " return None # TODO etudiant\n", + "\n", + " def transition(self, state, action):\n", + " # TODO etudiant : remplir, vider, ou verser jusqu'a vider la source ou remplir la destination\n", + " return None # TODO etudiant\n", + "\n", + " def is_goal(self, state) -> bool:\n", + " # TODO etudiant : l'une des deux cruches contient self.cible litres\n", + " return None # TODO etudiant\n", + "\n", + " def state_space_size(self) -> int:\n", + " # TODO etudiant : (cap_a + 1) x (cap_b + 1) contenus possibles\n", + " return None # TODO etudiant\n", + "\n", + "\n", + "# --- Test (decommentez apres avoir complete l'exercice ci-dessus) ---\n", + "# cruches = WaterJugs()\n", + "# print(f\"Contenus possibles : {cruches.state_space_size()}\")\n", + "# print(f\"Actions depuis {cruches.initial_state()} : {cruches.actions(cruches.initial_state())}\")\n", + "# chemin, final = bfs_solve(cruches)\n", + "# print(f\"Solution en {len(chemin)} actions : {' -> '.join(chemin)}\")\n", + "# print(f\"Etat final : {final}\")\n", + "# chemin_2_4, _ = bfs_solve(WaterJugs(cap_a=2, cap_b=4, cible=3))\n", + "# print(f\"Cruches de 2 et 4 litres, cible 3 : {chemin_2_4}\")\n", + "\n", + "print(\"Exercice a completer\")" + ] + }, + { + "cell_type": "markdown", + "id": "41790719", "metadata": { "papermill": { - "duration": 0.014426, - "end_time": "2026-10-26T10:55:56.258427+00:00", + "duration": 0.013812, + "end_time": "2026-10-26T16:56:29.767550+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.244001+00:00", + "start_time": "2026-10-26T16:56:29.753738+00:00", "status": "completed" }, "tags": [] @@ -2724,9 +2842,10 @@ "| Aspirateur | 8 | Uniforme | Trivial, sert de modèle pedagogique |\n", "| 8-Puzzle | 181 440 | Uniforme | Taille de l'espace, profondeur des solutions |\n", "| Itineraire | Variable | Distances | Couts non uniformes, necessite UCS ou A* |\n", - "| Missionnaires | ~16 | Uniforme | Contraintes de validite des etats |\n", + "| Missionnaires | 20 états valides | Uniforme | Contraintes de validite des etats |\n", "| Labyrinthe | 24 (grille 5x7) | Uniforme | Structure implicite du graphe |\n", "| Labyrinthe à clé | 2 x cases hors murs | Uniforme | L'etat doit memoriser la cle, pas seulement la position |\n", + "| Cruches d'eau | 24 (cruches de 3 et 5 L) | Uniforme | Tous les contenus ne sont pas atteignables |\n", "\n", "### Ce qu'il faut retenir\n", "\n", @@ -2738,13 +2857,13 @@ }, { "cell_type": "markdown", - "id": "1cf70b6f", + "id": "183b5941", "metadata": { "papermill": { - "duration": 0.018312, - "end_time": "2026-10-26T10:55:56.290486+00:00", + "duration": 0.009906, + "end_time": "2026-10-26T16:56:29.788552+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.272174+00:00", + "start_time": "2026-10-26T16:56:29.778646+00:00", "status": "completed" }, "tags": [] @@ -2768,13 +2887,13 @@ }, { "cell_type": "markdown", - "id": "67403fa8", + "id": "851cef7d", "metadata": { "papermill": { - "duration": 0.014629, - "end_time": "2026-10-26T10:55:56.319978+00:00", + "duration": 0.008219, + "end_time": "2026-10-26T16:56:29.806334+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.305349+00:00", + "start_time": "2026-10-26T16:56:29.798115+00:00", "status": "completed" }, "tags": [] @@ -2791,13 +2910,13 @@ }, { "cell_type": "markdown", - "id": "88c4a874", + "id": "7163e127", "metadata": { "papermill": { - "duration": 0.012629, - "end_time": "2026-10-26T10:55:56.350364+00:00", + "duration": 0.011705, + "end_time": "2026-10-26T16:56:29.826874+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.337735+00:00", + "start_time": "2026-10-26T16:56:29.815169+00:00", "status": "completed" }, "tags": [] @@ -2820,13 +2939,13 @@ }, { "cell_type": "markdown", - "id": "780d8f8f", + "id": "7b6bfc93", "metadata": { "papermill": { - "duration": 0.014401, - "end_time": "2026-10-26T10:55:56.381780+00:00", + "duration": 0.011901, + "end_time": "2026-10-26T16:56:29.850196+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.367379+00:00", + "start_time": "2026-10-26T16:56:29.838295+00:00", "status": "completed" }, "tags": [] @@ -2842,13 +2961,13 @@ }, { "cell_type": "markdown", - "id": "0de59ceb", + "id": "97566aa1", "metadata": { "papermill": { - "duration": 0.017059, - "end_time": "2026-10-26T10:55:56.413099+00:00", + "duration": 0.011874, + "end_time": "2026-10-26T16:56:29.875230+00:00", "exception": false, - "start_time": "2026-10-26T10:55:56.396040+00:00", + "start_time": "2026-10-26T16:56:29.863356+00:00", "status": "completed" }, "tags": [] @@ -2897,14 +3016,14 @@ }, "papermill": { "default_parameters": {}, - "duration": 5.970556, - "end_time": "2026-10-26T10:55:56.886306+00:00", + "duration": 5.866124, + "end_time": "2026-10-26T16:56:30.225907+00:00", "environment_variables": {}, "exception": null, "input_path": "Search-01-StateSpace.ipynb", "output_path": "Search-01-StateSpace.ipynb", "parameters": {}, - "start_time": "2026-10-26T10:55:50.915750+00:00", + "start_time": "2026-10-26T16:56:24.359783+00:00", "version": "2.6.0" } }, diff --git a/scripts/notebook_tools/twin_pairs.d/search-01-statespace.yaml b/scripts/notebook_tools/twin_pairs.d/search-01-statespace.yaml index 5b2c19eefa9..1fbabefa8b3 100644 --- a/scripts/notebook_tools/twin_pairs.d/search-01-statespace.yaml +++ b/scripts/notebook_tools/twin_pairs.d/search-01-statespace.yaml @@ -18,3 +18,4 @@ - "2026-08-16 (po-2025), OPTION (a) TRANCHEE + ecart DOCUMENTE : le design-gate est clos -- networkx 3.6.1 est installe et bridge dans Search-1-StateSpace.ipynb (Dijkstra + centralite d'intermediarite, section 'Verification de l'optimalite avec networkx', sorties executees). L'entree 2026-08-16 (ai-01) 'ASYMETRIE ASSUMEE' ci-dessus est caduque. Le volet divergence de donnees est tranche par la DOCUMENTATION : chaque jumeau porte desormais une note de parite explicitant l'ecart (Python 11 villes / 28 arcs / 2.55 / optimum 1075 via Paris = confirmation ; C# 13 villes / 41 arcs / 3.15 / optimum 1045 via Lyon = refutation). Les deux lecons restent valides, chacune liee a son graphe, lisible par le lecteur des deux notebooks. parity_level laisse a semantic (attente #11200). Voir #11197." - "2026-08-16 (po-2025), FACTEUR DE BRANCHEMENT CORRIGE (issue #11198) : le 'b ~ 2.67' attribue au monde de l'aspirateur etait fabrique (Actions() renvoie exactement 2 actions par etat) -- corrige des DEUX cotes : b = 2 et 2^3 = 8 = espace d'etats entier (phrase b^d reformulee, tables comparative et de resume alignees). Cote Python : '~2.7' -> 2.55 dans la table comparative, et le facteur 2.55 est desormais calcule a l'execution par la cellule networkx (28 arcs / 11 villes). L'entree 2026-08-16 (ai-01) ci-dessus est entierement traitee." - "2026-10-26 (myia-ai-01:CoursIA), ASYMETRIE D'EXERCICES ASSUMEE (#22659, suivi #22680) : integration du TP MIS #22645 cote Python seul. Les exercices 2 (taille de l'espace d'etats des taquins) et 3 (labyrinthe) deviennent des exemples guides credites ; deux exercices non resolus s'y ajoutent (invariant de parite du taquin 8, labyrinthe a cle). Le jumeau C# garde ses exercices 2 et 3 ouverts (aucune solution C# a crediter) et ne porte pas encore les deux nouveaux : portage a faire sous #22680, valeurs attendues a recalculer sur le graphe C#. Aucun autre contenu commun touche." + - "2026-10-26 (myia-ai-01:CoursIA), ASYMETRIE D'EXERCICES ASSUMEE (#22688, suivi #22680) : integration du TP MIS #22688 cote Python seul. L'exercice 1 (missionnaires et cannibales) devient un exemple guide credite, accompagne d'une resolution BFS (11 traversees, 20 etats valides sur 32 triplets) ; un exercice 6 non resolu s'y ajoute (cruches d'eau 3 L / 5 L, cible 4 L). Le jumeau C# garde son exercice 1 ouvert (aucune solution C# a crediter) et ne porte pas encore l'exercice 6 : portage a faire sous #22680. Aucun autre contenu commun touche." From a418a7263a91700cbf3c5619d1037cc2a87cb81c Mon Sep 17 00:00:00 2001 From: jsboige Date: Mon, 26 Oct 2026 17:59:18 +0100 Subject: [PATCH 2/2] Chore(twin,#22688): attestation 0020 Search-01 StateSpace apres integration du TP Co-Authored-By: Claude Opus 5.5 (1M context) --- .../0020-2026-10-26-myia-ai-01-CoursIA.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 scripts/notebook_tools/twin_pairs.d/search-01-statespace/0020-2026-10-26-myia-ai-01-CoursIA.yaml diff --git a/scripts/notebook_tools/twin_pairs.d/search-01-statespace/0020-2026-10-26-myia-ai-01-CoursIA.yaml b/scripts/notebook_tools/twin_pairs.d/search-01-statespace/0020-2026-10-26-myia-ai-01-CoursIA.yaml new file mode 100644 index 00000000000..4c2fef0d30e --- /dev/null +++ b/scripts/notebook_tools/twin_pairs.d/search-01-statespace/0020-2026-10-26-myia-ai-01-CoursIA.yaml @@ -0,0 +1,6 @@ +date: '2026-10-26' +by: myia-ai-01:CoursIA +python_sha: 0d6016064ecd538f73a7b479692e85fa236b7e06 +csharp_sha: bb82ca11770f19378eb762b02833e70247ecd6fe +content_python_sha: 14a18e54d3c85c2de9854c72e2260933ef3094f78cfd06f8cc5ed4361236e7a3 +content_csharp_sha: 67a2c51d0da62ffc9dbec17f9bae89130bda604192741a98727c82f8317283db