Initial commit.
This commit is contained in:
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = sage
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
6
docs/_static/figure1
vendored
Normal file
6
docs/_static/figure1
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
+-------------+-----------+-----------+-----------+-----------+-----------+
|
||||
| 0 | 1 | 2 | 3 | 4 | 5 |
|
||||
+-------------+-----------+-----------+-----------+-----------+-----------+
|
||||
| Muet ou très peu bavard | | | Très bavard |
|
||||
+-------------+-----------+-----------+-----------+-----------+-----------+
|
||||
BIN
docs/_static/figure1.png
vendored
Normal file
BIN
docs/_static/figure1.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
3
docs/_static/figure2
vendored
Normal file
3
docs/_static/figure2
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
+----+-----+---------------------+
|
||||
| ID | NOM | NIVEAU DE BAVARDAGE |
|
||||
+----+-----+---------------------+
|
||||
BIN
docs/_static/figure2.png
vendored
Normal file
BIN
docs/_static/figure2.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
9
docs/api.rst
Normal file
9
docs/api.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
***
|
||||
API
|
||||
***
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
api/*
|
||||
8
docs/api/engine.rst
Normal file
8
docs/api/engine.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
.. _engine:
|
||||
|
||||
========
|
||||
Engine
|
||||
========
|
||||
|
||||
.. autoclass:: sage.Engine
|
||||
:members:
|
||||
8
docs/api/interface.rst
Normal file
8
docs/api/interface.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
.. _interface:
|
||||
|
||||
=========
|
||||
Interface
|
||||
=========
|
||||
|
||||
.. automodule:: sage.interface
|
||||
:members:
|
||||
8
docs/api/seatingplan.rst
Normal file
8
docs/api/seatingplan.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
.. _seatingplan:
|
||||
|
||||
===========
|
||||
SeatingPlan
|
||||
===========
|
||||
|
||||
.. autoclass:: sage.SeatingPlan
|
||||
:members:
|
||||
8
docs/api/student.rst
Normal file
8
docs/api/student.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
.. _student:
|
||||
|
||||
========
|
||||
Student
|
||||
========
|
||||
|
||||
.. autoclass:: sage.Student
|
||||
:members:
|
||||
194
docs/conf.py
Normal file
194
docs/conf.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
# sys.path.insert(0, os.path.abspath('../spoticla/'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'SAGE (Seating plAn GEnerator)'
|
||||
copyright = '2018, Jeff LANCE'
|
||||
author = 'Jeff LANCE'
|
||||
|
||||
# The short X.Y version
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '0.5'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinxcontrib.napoleon',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.viewcode',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'fr'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path .
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
# html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'spoticladoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'spoticla.tex', 'spoticla Documentation',
|
||||
'Jeff LANCE', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'spoticla', 'spoticla Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'spoticla', 'spoticla Documentation',
|
||||
author, 'spoticla', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
epub_author = author
|
||||
epub_publisher = author
|
||||
epub_copyright = copyright
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
3
docs/getting-started.rst
Normal file
3
docs/getting-started.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
**************
|
||||
Pour commencer
|
||||
**************
|
||||
11
docs/index.rst
Normal file
11
docs/index.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
#####################
|
||||
SAGE's documentation!
|
||||
#####################
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
intro
|
||||
getting-started
|
||||
api
|
||||
references
|
||||
483
docs/intro.rst
Normal file
483
docs/intro.rst
Normal file
@@ -0,0 +1,483 @@
|
||||
########
|
||||
À propos
|
||||
########
|
||||
|
||||
|
||||
|
||||
*************
|
||||
Problématique
|
||||
*************
|
||||
|
||||
*Contexte: Élèves d'une classe, places assises dans une salle*
|
||||
|
||||
*Contraintes:
|
||||
Le niveau de bavardage d'un élève, les liens sociaux entre élèves*
|
||||
|
||||
Comme tout enseignant j'ai été et je suis encore confronté au problème de la
|
||||
gestion de classe et plus précisément aux interactions efficaces ou inefficaces
|
||||
des élèves au sein d'une classe.
|
||||
|
||||
En effet, les associations d´élèves bavards entre eux peuvent mettre à mal une séance.
|
||||
Dissocier une binôme productif peut l'être également.
|
||||
|
||||
Pour "régler" cela, la démarche consiste à créer un plan de classe afin de diriger
|
||||
ou limiter les liens que peuvent avoir les élèves entre eux durant une séance.
|
||||
Ainsi, j'ai tenté plusieurs fois de casser les bavardages entre plusieurs
|
||||
camarades en les disposant dans la classe à divers endroits et ce dans le
|
||||
but d'arriver à un équilibre entre bonne dynamique du groupe classe du point
|
||||
de vue de l'ambiance et du travail et la limitation des bavardages, de l'inattention.
|
||||
|
||||
Voulant également passer la certification ISN, il me fallait trouver un projet
|
||||
qui m'intéressait et qui semblait pertinent pour le dossier à présenter.
|
||||
|
||||
|
||||
|
||||
*****************
|
||||
Solution proposée
|
||||
*****************
|
||||
|
||||
*La solution proposée doit:
|
||||
- utiliser Python
|
||||
- être simple d'utilisation (IHM, import de la liste des élèves,...)
|
||||
- proposer un placement automatique des élèves en fonction de certaines contraintes
|
||||
- permettre d'éditer cette solution de positionnement ou d'en créer une
|
||||
- permettre de modifier les contraintes*
|
||||
|
||||
|
||||
|
||||
**********
|
||||
Conception
|
||||
**********
|
||||
|
||||
|
||||
1ère phase de recherche
|
||||
=======================
|
||||
|
||||
J'ai tout d'abord commencé par faire des recherches sur cette thématique.
|
||||
Au hasard de mes recherches, je suis tombé sur une application web, `xperprof`_,
|
||||
permettant de génerer un plan de classe.
|
||||
Cette application propose une fonction de positionnement aléatoire des élèves et
|
||||
notamment la capacité de ne pas soumettre certaines tables à l'algorithme et ainsi
|
||||
créer des zones vide autour de certains élèves.
|
||||
Une première idée d'algorithme m'est venue : le positionnement aléatoire.
|
||||
|
||||
J'ai toutefois continué mes recherches et ai vu une analogie de mon projet avec
|
||||
un jeu d'échec.
|
||||
Un article du blog de `Jean-François GAZET`_ au sujet la création d'un jeu d'échec m'a apporter quelques idées
|
||||
pour mon développement. Il m'a aider à définir quelques éléments de l'implémentation, à savoir :
|
||||
|
||||
- l'IHM: mode console ou graphique ?
|
||||
- la façon de représenter un élève, un plan de classe
|
||||
- la notion de "critères" que j'ai requalifié de "contraintes" pour mon projet
|
||||
- la stratégie algorithmique pour proposer une solution
|
||||
|
||||
Restait un élément à préciser : le format de données utilisé pour contenir la liste des élèves.
|
||||
Mais ce dernier point n'était qu'une formalité.
|
||||
|
||||
|
||||
IHM
|
||||
===
|
||||
|
||||
J'ai tout de suite souhaité que mon application fonctionne en mode console pour deux raisons :
|
||||
|
||||
- la première :
|
||||
Pour moi une application doit pouvoir fonctionner en mode console et pouvoir proposer
|
||||
une interface graphique au besoin.
|
||||
J'espérais ainsi passer la majeure partie du temps pour développer l'API et passer le reste sur
|
||||
l'Interface-Homme-Machine.
|
||||
- la seconde (qui est une conséquence de la première) :
|
||||
Compte-tenu du délai qui m'était imposé je ne voulais pas passer trop de temps dans l'apprentissage
|
||||
d'une librairie graphique.
|
||||
|
||||
|
||||
Format de la liste des élèves
|
||||
=============================
|
||||
|
||||
Afin de charger directement dans l'application une liste des élèves à manipuler,
|
||||
il est nécessaire de choisir un format de fichier.
|
||||
|
||||
Le format **.csv** est celui retenu, de part sa simplicité à le générer.
|
||||
Le séparateur de champ sera le point-virgule.
|
||||
|
||||
L'en-tête du ficher élèves est la suivante :
|
||||
|
||||
.. figure:: _static/figure2.png
|
||||
:align: center
|
||||
:scale: 60 %
|
||||
|
||||
|
||||
Classes ``Student`` et ``SeatingPlan``
|
||||
======================================
|
||||
|
||||
Dans le contexte de la classe, un **élève** est un individu portant certains attributs, comme
|
||||
un nom, un prénom, une liste d'amis dans cette même classe ou à l'extérieur,...
|
||||
Un **plan de classe** également peut porter certaines propriétés, comme ses dimensions,
|
||||
la liste des sièges disponibles, leurs occupants,...
|
||||
|
||||
Ces deux éléments peuvent de surcroît interagir.
|
||||
|
||||
Il est alors apparu évident de considérer, d'un point de vue informatique, ces notions
|
||||
comme des structures de données à part entière.
|
||||
Ainsi leur définition, leur création, leur manipulation s'en trouveraient facilitées.
|
||||
|
||||
Dès lors, le choix du paradigme de programmation orientée objet a été décidé.
|
||||
|
||||
Deux classes, ont donc été définies pour cela :
|
||||
|
||||
- la classe ``Student``, pour définir les élèves
|
||||
- la classe ``SeatingPlan``, pour définir le plan de classe
|
||||
|
||||
Student
|
||||
-------
|
||||
|
||||
Un élève est défini par :
|
||||
|
||||
- son nom
|
||||
- un niveau de bavardage
|
||||
- une liste d'amis
|
||||
|
||||
::
|
||||
|
||||
def __init__(self, name, chat_lvl=0, friends=[]):
|
||||
""" Instancie un objet plan de classe.
|
||||
|
||||
:param name:
|
||||
Nom de l'élève.
|
||||
:type name: str
|
||||
:param chat_lvl:
|
||||
Coefficient ou niveau de bavardage.
|
||||
:type chat_lvl: int
|
||||
:param friends:
|
||||
Liste d'amis.
|
||||
:type friends: list
|
||||
"""
|
||||
self.name = name
|
||||
self.chat_lvl = chat_lvl
|
||||
self.friends = friends
|
||||
|
||||
SeatingPlan
|
||||
-----------
|
||||
|
||||
Un plan de classe est défini par :
|
||||
|
||||
- un nombre de rangées
|
||||
- un nombre de colonnes
|
||||
- une "cartographie" de la classe
|
||||
|
||||
À l'origine, la cartographie de mon plan de classe prenait la forme d'une liste
|
||||
imbriquée, comme dans `jepychess`_.
|
||||
Cette représentation a évolué pour une structure plus souple et surtout en adéquation
|
||||
avec celle utilisée dans l'algorithme de calcul.
|
||||
|
||||
::
|
||||
|
||||
def __init__(self, row=5, col=8):
|
||||
""" Instancie un objet plan de classe.
|
||||
|
||||
:param row:
|
||||
Nombre de rangées dans la classe.
|
||||
:type row: int
|
||||
:param col:
|
||||
Nombre de colonnes dans la classe.
|
||||
:type col: int
|
||||
:param mapping:
|
||||
Représentation du plan de la classe.
|
||||
:type mapping: dict
|
||||
"""
|
||||
self.row = row
|
||||
self.col = col
|
||||
self.mapping = {(i, j): None for i in range(row)
|
||||
for j in range(col)}
|
||||
|
||||
|
||||
Les contraintes
|
||||
===============
|
||||
|
||||
Les contraintes sont les conditions suivant lesquelles on accepte que deux
|
||||
élèves soient voisins dans le plan de classe.
|
||||
|
||||
Pour commencer, celles-ci seront "naïves". C'est-à-dire qu'elles seront basées
|
||||
sur une valeur entière représentant le niveau de bavardage de l'élève.
|
||||
Puis, elles sreont redéfinies pour prendre appui sur les relations sociales
|
||||
entre les élèves (qui est ami avec ami).
|
||||
|
||||
Ainsi, deux élèves pourront être voisins si la différence entre leur niveaux
|
||||
respectifs de bavardage est d'au moins une valeur fixée.
|
||||
De la même manière, deux élèves pourront être voisins, si leur lien social
|
||||
est minimal.
|
||||
|
||||
Les niveaux ou coefficients de bavardage seront définis comme suit :
|
||||
|
||||
.. figure:: _static/figure1.png
|
||||
:align: center
|
||||
:scale: 60 %
|
||||
|
||||
|
||||
2nde phase de recherches : l'algorithme ?
|
||||
=========================================
|
||||
|
||||
Balbutiements
|
||||
-------------
|
||||
|
||||
Initialement, en me basant sur l'exemple de `xperprof`_, j'ai réalisé un placement
|
||||
aléatoire sous contrainte, des élèves dans le plan de classe.
|
||||
Le résultat fût concluant mais chaque lancement de cet algorithme produisait une seule proposition
|
||||
qui pouvait ou non, être complète en raison de contraintes parfois trop fortes.
|
||||
|
||||
La première difficulté est ainsi apparue: satisfaire des contraintes tout en proposant des solutions possibles.
|
||||
|
||||
L'algorithme **alpha-beta** cité dans le blog de `Jean-François GAZET`_ m'a dirigé vers les méthode de résolution
|
||||
de jeu d'échec, de dames ou plus généralement de problèmes NP-complet.
|
||||
Mais également sur le fait de considérer les différentes étapes de recherche de complétion du plan de classe comme
|
||||
un arbre de recherche.
|
||||
|
||||
Mes diverses lectures ainsi que des recherches sur l'Internet m'ont amené au problème des N-Reines.
|
||||
Diverses méthodes de programmation permettent de résoudre ce problème : comme la programmation par contraintes.
|
||||
|
||||
Résoudre un problème de satisfaction de contraintes... ?
|
||||
--------------------------------------------------------
|
||||
|
||||
J'ai vu la résolution de ma problématique comme un problème de satisfaction de contraintes et me suis mis en
|
||||
quête de réponses concernant la programmation par contraintes.
|
||||
|
||||
Plusieurs possibilités
|
||||
|
||||
Je me suis alors tourné vers un algorithme avec retour sur trace.
|
||||
|
||||
L'algorithme au final
|
||||
---------------------
|
||||
|
||||
Validateur de contraintes
|
||||
"""""""""""""""""""""""""
|
||||
|
||||
::
|
||||
|
||||
def respect_constraints(self, seat, student, seatingplan, solution):
|
||||
"""Indique si une place associée à une élève satisfait aux
|
||||
contraintes, à savoir si :
|
||||
|
||||
- l'élève n'a pas déjà été positionné
|
||||
- la place n'est pas déjà occupée
|
||||
- la place est libre, que son voisinage est composé de bons voisins
|
||||
en termes de bavardages.
|
||||
|
||||
:param seat:
|
||||
Place que l'on veut associer à un élève.
|
||||
:type seat: tuple
|
||||
:param student:
|
||||
Élève que l'on veut associer à une place.
|
||||
:type student: Student
|
||||
:param seatingplan:
|
||||
Plan de classe.
|
||||
:type seatingplan: SeatingPlan
|
||||
:param solution:
|
||||
Associations 'place - élève' valides.
|
||||
:type solution: dict
|
||||
|
||||
:rtype: bool
|
||||
|
||||
.. todo::
|
||||
- Modifier le traitement des contraintes de façon à tolérer
|
||||
un certains nombre de voisins ne satisfaisants pas aux
|
||||
contraintes.
|
||||
- Ajouter les liens sociaux comme contraintes supplémentaires.
|
||||
"""
|
||||
# L'association en cours est supposée valide
|
||||
result = True
|
||||
# Si l'élève en cours a déjà été traité, l'association est invalide
|
||||
if student in solution.values():
|
||||
result = False
|
||||
# return False
|
||||
# Si la place en cours a déjà été traitée, l'association est invalide
|
||||
elif seat in solution.keys():
|
||||
result = False
|
||||
# return False
|
||||
else:
|
||||
# Si non, veŕifions le voisinage de la place
|
||||
# Récupérons le voisinage de la place en cours
|
||||
neighbourhood = self.get_neighbourhood(seatingplan,
|
||||
seat,
|
||||
self.NEIGHBOURHOOD_RADIUS)
|
||||
|
||||
for neighbour_seat in neighbourhood:
|
||||
# On ne teste les contraintes que sur les sièges déjà occupés
|
||||
# donc sur ceux faisant déjà partie des solutions
|
||||
if neighbour_seat in list(solution.keys()):
|
||||
# On récupère l'élève du siège voisin
|
||||
neighbour = solution[neighbour_seat]
|
||||
|
||||
# Lequel de l'élève en cours ou du voisin
|
||||
# est le plus bavard ?
|
||||
max_chat_lvl = max(student.chat_lvl,
|
||||
neighbour.chat_lvl)
|
||||
|
||||
# Les contraintes portent sur la différence de
|
||||
# coefficient de bavardage entre deux voisins:
|
||||
if max_chat_lvl == 5:
|
||||
result = result and self.are_safe_neighbours(
|
||||
student,
|
||||
neighbour,
|
||||
self.DELTA_FOR_MAX_CHAT_LVL_5)
|
||||
|
||||
elif max_chat_lvl == 4:
|
||||
result = result and self.are_safe_neighbours(
|
||||
student,
|
||||
neighbour,
|
||||
self.DELTA_FOR_MAX_CHAT_LVL_4)
|
||||
|
||||
elif max_chat_lvl == 3:
|
||||
result = result and self.are_safe_neighbours(
|
||||
student,
|
||||
neighbour,
|
||||
self.DELTA_FOR_MAX_CHAT_LVL_3)
|
||||
|
||||
elif max_chat_lvl == 2:
|
||||
result = result and self.are_safe_neighbours(
|
||||
student,
|
||||
neighbour,
|
||||
self.DELTA_FOR_MAX_CHAT_LVL_2)
|
||||
|
||||
elif max_chat_lvl == 1:
|
||||
result = result and self.are_safe_neighbours(
|
||||
student,
|
||||
neighbour,
|
||||
self.DELTA_FOR_MAX_CHAT_LVL_1)
|
||||
|
||||
else:
|
||||
result = result and True
|
||||
# Le siège voisin n'est pas occupé, il est donc valide
|
||||
result = result and True
|
||||
# retournons la validité de l'association
|
||||
return result
|
||||
|
||||
Le solveur
|
||||
""""""""""
|
||||
|
||||
::
|
||||
|
||||
def solve(self, seatingplan, students_list):
|
||||
"""Cherche pour une liste de places et une liste d'élèves, un ensemble
|
||||
de dispositions dans un plan de classe respectueuses de certaines
|
||||
contraintes décrites dans la fonction 'respect_constraints' ci-dessus.
|
||||
|
||||
:param seatingplan:
|
||||
Plan de classe.
|
||||
:type seatingplan: SeatingPlan
|
||||
:param students_list:
|
||||
Liste d'élèves à positionner dans le plan de classe.
|
||||
:type students_list: list
|
||||
:param solution:
|
||||
Solution de placement proposée.
|
||||
:type solutions: dict
|
||||
|
||||
:return:
|
||||
Disposition des élèves dans le plan de classe.
|
||||
:rtype: generator
|
||||
"""
|
||||
# Liste des places
|
||||
seats_list = list(seatingplan.mapping.keys())
|
||||
|
||||
# Quantités de places et d'élèves à traiter
|
||||
number_of_seats = len(seats_list)
|
||||
number_of_students = len(students_list)
|
||||
|
||||
# On stocke nos associations 'place - élève' dans un dictionnaire
|
||||
solution = {}
|
||||
|
||||
# Indexes de départ dans nos listes de places et d'élèves
|
||||
idx_seat = 0
|
||||
idx_student = 0
|
||||
|
||||
# Retour sur trace (backtracking)
|
||||
backtrack = False
|
||||
# Fin du parcours
|
||||
end = False
|
||||
|
||||
# On commence notre recherche
|
||||
while not end:
|
||||
# On ne revient pas encore en arrière
|
||||
while not backtrack:
|
||||
# Place à traiter
|
||||
current_seat = seats_list[idx_seat]
|
||||
# Élève à traiter
|
||||
current_student = students_list[idx_student]
|
||||
|
||||
# L'association 'place - élève' est-elle satisfaisante ?
|
||||
if self.respect_constraints(current_seat,
|
||||
current_student,
|
||||
seatingplan,
|
||||
solution):
|
||||
# Oui, alors associons l'élève à cette place
|
||||
solution[current_seat] = current_student
|
||||
|
||||
# Est-ce qu'on a traité tous les élèves dans
|
||||
# notre parcourt ?
|
||||
if (idx_student == number_of_students-1):
|
||||
# Oui, alors renvoyons notre solution
|
||||
yield {p: s for p, s in solution.items()}
|
||||
del solution[current_seat]
|
||||
|
||||
# A-t'on traité toutes les places ?
|
||||
if (idx_seat != number_of_seats-1):
|
||||
# Non, on passe à la suivante
|
||||
idx_seat = idx_seat + 1
|
||||
else:
|
||||
# Oui, on revient en arrière
|
||||
backtrack = True
|
||||
else:
|
||||
# Non, on passe au suivant en recommençant à la
|
||||
# première place
|
||||
idx_seat = 0
|
||||
idx_student = idx_student + 1
|
||||
|
||||
# Les contraintes n'ont pas été satisfaites,
|
||||
# il nous reste des places à traiter
|
||||
elif (idx_seat != number_of_seats-1):
|
||||
# On passe à la suivante
|
||||
idx_seat = idx_seat + 1
|
||||
|
||||
else:
|
||||
# Si non, on revient en arrière
|
||||
backtrack = True
|
||||
|
||||
# Sommes-nous remonté jusqu'au premier élève ?
|
||||
end = (idx_student == 0)
|
||||
|
||||
# On revient sur nos pas...
|
||||
while (backtrack and not end):
|
||||
# Prenons l'élève précédent
|
||||
idx_student = idx_student - 1
|
||||
current_student = students_list[idx_student]
|
||||
# On récupère (et on enlève des solutions) la place qui lui
|
||||
# est associée
|
||||
current_seat = list(solution.keys())[list(solution.values())
|
||||
.index(current_student)]
|
||||
solution.pop(current_seat)
|
||||
idx_seat = seats_list.index(current_seat)
|
||||
|
||||
# Il nous reste des places
|
||||
if (idx_seat != number_of_seats-1):
|
||||
# Prenons la place suivante et stoppons notre retour
|
||||
# en arrière
|
||||
idx_seat = idx_seat + 1
|
||||
backtrack = False
|
||||
# Ou nous sommes revenu au premier élève, on stop là
|
||||
elif idx_student == 0:
|
||||
end = True
|
||||
|
||||
|
||||
|
||||
********************************
|
||||
Bilan et améliorations possibles
|
||||
********************************
|
||||
|
||||
L'algorithme fonctionne bien dès lors que l'échantillon d'élèves n'est pas trop grand.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.. _xperprof: https://www.xperprof.fr/generateur_plan_de_classe
|
||||
.. _Jean-François GAZET: https://fr.jeffprod.com/blog/2014/comment-programmer-un-jeu-dechecs.html
|
||||
.. _jepychess: `Jean-François GAZET`_
|
||||
9
docs/references.rst
Normal file
9
docs/references.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
**********
|
||||
Références
|
||||
**********
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
references/bibliography
|
||||
17
docs/references/bibliography.rst
Normal file
17
docs/references/bibliography.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
*************
|
||||
Bibliographie
|
||||
*************
|
||||
|
||||
.. rubric::
|
||||
|
||||
.. [CAC+14] A. Cohen, J-P. Archambault, C. Cimelli, "Informatique et sciences du numérique - Edition spéciale Python !",
|
||||
Eyrolles, 2014
|
||||
|
||||
.. [GRU17] J. Grus, "Data Science par la pratique : Fondamentaux avec Python",
|
||||
Eyrolles, 2017
|
||||
|
||||
.. [SWI12] G. Swinnen, "Apprendre à programmer avec Python 3",
|
||||
Eyrolles, 2012
|
||||
|
||||
.. [LeG14] V. Le Goff, "Apprenez à programmer en Python", 2e Édition,
|
||||
OpenClassrooms - ex-Site du Zéro, 2014
|
||||
6
docs/references/webography.rst
Normal file
6
docs/references/webography.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
***********
|
||||
Webographie
|
||||
***********
|
||||
|
||||
.. _xperprof: https://www.xperprof.fr/generateur_plan_de_classe
|
||||
.. _Jean-François GAZET: https://fr.jeffprod.com/blog/2014/comment-programmer-un-jeu-dechecs.html
|
||||
Reference in New Issue
Block a user