10 février 2017

bashrc vs bash_profile

Au démarrage de bash son comportement varie suivant qu’il sera avec ou sans login et qu’il sera interactif ou pas. Ce qui nous fait 4 cas à étudier.


   | Non interactif | Interactif |
-----------+----------------+------------|
Sans login |    #0     |    #1      |
-----------+----------------+------------|
Avec login |    #2          |    #3      |
-----------------------------------------+

Pour chaque cas nous allons nous intéressé
- Au fichier exécuté au démarrage  ( ~/.bashrc  ou ~/.bash_profile ou rien)
- A la variable $0 c’est-à-dire  le nom du shell  (avec ou sans - )
- A la variable $- qui donne les paramètres utilisés pour invoquer le shell
- A la variable $TERM
- A la variable $PS1, qui détermine le prompt du shell.

Important: on ne prend pas en compte le fait que sur beaucoup de distributions Linux ~/.bash_profile charge aussi ~/.bashrc.

Cas #3 : shell avec login et interactif.

Ce cas correspond au cas classique d'une connexion à une machine via ssh ou telnet ou directement via la console. Ou encore avec la commande 'su - user'.
Dans tous ces cas on obtient une shell interactif suite à une procédure de login. Il s'agit d'une ouverture de session.
Exécution de ~/.bash_profile$0 = -bash
$- = himBH
TERM=linux
$PS1 est définit

Cas #2 : shell avec login mais non interactif.

En dehors de quelques cas obscurs de l'environnement X le cas le plus classique est l’exécution sur une machine distante de commandes via un pipe avec ssh.
echo date | ssh serveur.exemple.com 
ssh serveur.exemple.com < script.sh
Le shell qui s’exécutera sur serveur.exemple.com sera avec login mais non interactif.
Exécution de ~/.bash_profile$0 = -bash
$- == hB
TERM = dumb
$PS1 n'est pas définit

Cas #1 : shell sans login et interactif

Typiquement cela arrive quand on lance bash depuis un autre shell, ou que l’on exécute screen ou la commande  'su user' ou encore quand on ouvre un terminal X.
Exécution de ~/.bashrc$0 = bash
$- = himBH
TERM = linux
$PS1 est définit
Dans le cas de la commande screen les choses sont un peu différentes :
Exécution de ~/.bashrc$0 = /bin/bash
$- == himBH
TERM = screen.linux
$PS1 est définit

Cas #0 : shell sans login et non interactif

Il s’agit d’un shell exécuté depuis un autre programme pour exécuter un script ou une commande.
C'est typiquement le cas quand on utilise ssh pour exécuter une commande sur une autre machine

ssh server.exemple.com date
Dans ce cas on a :
Exécution de ~/.bashrc
$0 = bash
$- = hBc
TERM = dumb
$PS1 non définit

L’exécution du shell peut aussi être aussi provoquée par un script shell, Perl, php etc…
Dans le cas d’un shell exécuté par Perl on a :
Pas de fichier exécuté
$0 = sh
$- == hBc
TERM = linux
$PS1 non définit
 ATTENTION : L’exécution de bash étant faite par un autre programme il est possible, en passant des paramètres à bash (comme --norc ou --noprofile ou --rcfile) de changer son comportement au démarrage. Donc à vérifier en fonction de qui exécute bash.
NOTE: cela ne concerne pas les  sub-shell qui sont en général utilisés pour exécuter des commandes entre parenthèses. Un sub-shell est un fork et est donc quasiment identique à son parent.  En particulier aucun fichier n’est chargé.

REMARQUES

~/.bash_profile est invoqué à l'ouverture d'une session (shell avec login).
~/.bashrc est invoqué quand la session est deja établie (shell sans login).

Quand $0 (le nom du shell) commence par le signe moins '-' le shell et en mode avec login.

Si $- contient la lettre minuscule 'i' c'est que le shell est en mode interactif.
De même, si $PS1 est définit c'est que l'on est en mode interactif.


Quoi mettre dans .bashrc et dans .bash_profile ?

Si vous avez suivi ce qui précède vous pouvez en conclure que pour un usage général d'un compte :

.bashrc ne doit rien afficher car il est exécuté à chaque invocation du shell par un autre programme. Il n’est pas question d’afficher la blague du jour et le nombre de mails non lu et la température du processeur à chaque fois !
.bashrc doit mettre en place l’environnement nécessaire aux taches programmables, automatisées, scriptables.

.bash_profile commence par exécuter .bashrc et complète pour obtenir une session de travail complète. 

Autrement dit : Faire en sorte que tout marche avec un minimum de chose dans .bashrc et un maximum dans .bash_profile.

Notez que le définition de "tout" varie d'un utilisateur à l'autre ;-)


12 janvier 2017

Partage des moutons

Si vous êtes un tant soit peu connu par votre entourage comme étant un matheux ou scientifique vous avez déjà entendu ces phases qui commencent par : « Tiens, toi qui fort en maths … »

Hier une amie est venue me raconter cette histoire :

- Tiens, toi qui est fort en maths, comment ferais tu pour résoudre ce problème :

Dans son testament un berger écrit qu’il lègue ses 17 moutons vivants à ses 3 fils, et indique comment devra se faire le partage :
 - L’aîné héritera de la moitié du troupeau,
 - Le cadet d’un tiers,
 - Le benjamin d’un neuvième.
A la mort du berger le sage du village est chargé d'exécuter le testament.Mais comment faire sachant que :
 - La moitié de 17 =  8,5
 - Le tiers de 17 =  5,66666
 - Le neuvième de 17 =  1,88888
et que les moutons doivent rester vivants !

- Alors, toi qui fort en maths, comment ferais tu à la place du sage ?

J’ai immédiatement répondu qu’il n’y avait pas de solution pour respecter les dernières volontés du berger car, quoique l’on fasse, la moitié de 17 vaudra toujours 8.5 et que l’on ne peut pas tuer des moutons pour les découper.

- Ah, c’est bien les matheux ça. Aucun sens pratique ! Eh bien moi qui suis pourtant nulle en maths je vais te dire comment le sage fait, c’est pourtant facile…

Le sage ajoute généreusement un de ses moutons au troupeau à partager, ce qui fait un troupeau de 18 moutons. Il donne la moitié au fils aîné, donc 9 moutons ; puis donne le tiers au fils cadet, donc 6 moutons et enfin un neuvième, soit 2 moutons, au benjamin. Et comme 9 + 6 + 2 = 17 le 18 ème mouton retourne d’où il vient, c’est-à-dire dans le troupeau du sage.


Avant que je formule ma première critique elle ajouta :

- Les 17 moutons ont bien été partagés sans être dépecés, et le sage n’a pas perdu le mouton qu’il avait prêtait. On est d’accord ?


- Euh … non, on n’est pas d’accord !

D'abord on constate que tout le monde a eu plus que ce qui est prévue par la règle de partage voulue par le berger.

Mais, comme toujours dans ce type de fausse solution, il faut revenir à l’énoncé.

Le berger a donné une règle de partage : 1/2 + 1/3 + 1/9
Mais cette règle de partage représente-t-elle tout le  troupeau ?

Pour le vérifier il faut réduire ces 3 fractions au même dénominateur.
Ce qui donne 9/18 + 6/18 + 2/18 = (9 + 6 + 2)/18 = 17/18

Le berger n’a donc pas prévu de léguer tout son troupeau à ses fils, mais seulement 17/18 c’est-à-dire 94.4444% du troupeau. Une petite partie (1/18) reste en dehors de l’héritage. 

Cette volonté n’est pas respectée par le sage puisque sa solution ne laisse rien après le partage.

En fait le sage a appliqué les proportions (1/2, 1/3, 1/9) sur 18 et non sur 17. Il se trouve que ça tombe juste et qu’il reste un mouton. Ce qui laisse faussement croire que le partage du sage n'a porté que sur les 17 moutons.

Et là mon amie me dit :
- Mais si il a respecté la volonté du berger puisque il restait un mouton à la fin….

On a beau être matheux, dans ces cas, on ne peut pas lutter !

25 avril 2016

Remove GWX

GWX.exe alias « Get Window 10 » c’est à dire « Obtenir Window 10 ».

Ce programme intrusif et qui vous incite à passer à Windows 10, est arrivé sur votre ordinateur sans crier gare via l’auto update de Windows. Pour le désactiver on pourrait agir à ce niveau mais cela ne serait que temporaire et insuffisant par lui-même. Microsoft a déjà publié cette pseudo mise à jour (KB3035583) le 14/mars/2015 et le 19/mars/2016. Donc ça risque encore de revenir.

Les fichiers installés par l’auto update sont dans C:\Windows\System32\GWX. Et aussi dans C:\Windows\SysWOW64\GWX pour les versions 64 bits. (sans oublier des petits bouts dans le gigantesque répertoire C:\Windows\winsxs). On peut les supprimer. Mais c’est un peu compliqué, même si on est admin, car le répertoire appartient à un utilisateur spécial ‘TrustedInstaller’ et pas à l’admin de base.

Il existe une autre solution, moins destructrice, qui consiste à supprimer les taches exécutées automatiquement via le task scheduler (planificateur de tache). Tous les programmes qui sont dans C:\Windows\System32\GWX sont régulièrement exécutés, sous diverses conditions, via le planificateur. Il faut exécuter Taskschd.msc en tant qu’administrateur  et on va supprimer les taches qui sont dans l’arbre aux positions :
  • \Microsoft\Windows\Setup\gwx\*
    et
  • \Microsoft\Windows\Setup\GWXTriggers\*
Étonnamment on peu désactiver (Disable) les taches de ...\Setup\gwx, pas celles de ...\Setup\GWXTriggers, par contre on peu toutes les supprimer (Delete).


Il suffit de répéter cela pour chaque tache de .../Setup/gwx et de .../Setup/GWXTriggers.

On reboote et voila : Adieu GWX !



NB le téléchargement de WX prend 3Go




01 avril 2016

alpha-beta

Bien souvent (à mon gout) les explications de l’algorithme alpha-beta manquent de détails. On comprend bien qu’il y a un gain par rapport au mini-max mais on ne sait pas trop comment le formaliser. Je vais donc essayer de synthétiser en détails !

Il faut bien comprendre que l’arbre des positions n’est pas construit dans un premier temps puis analysé dans un second temps. Ce serait très couteux en temps et en mémoire, ce n'est pas nécessaire et de toute façon le but de l'alpha-beta c'est d'en faire le moins possible. L'arbre est analysé au fur et à mesure qu’il est découvert. Ce qui signifie que l’analyse mini-max (ou alpha-beta) n’a qu’une vue partielle de l’arbre.
Par convention, la valeur d’une position dans le graphe est la valeur que lui attribue celui qui a le trait. Autrement dit la valeur d’une position est le gain qu’espère en tirer celui qui doit jouer à partir de cette position.

Étape 1

Vert fait face à la position P0. Soit c’est la position de départ du jeu, soit Rouge vient de jouer et laisse le trait à Vert. Quel gain Vert peut-il espérer tirer de cette position ?


Vert analyse la position P1.1 résultant de son premier coup possible, V1.

Pour juger de la qualité de cette position P1.1, Vert se demande quelles sont les ripostes  possibles de Rouge.

Il analyse le coup R1 de Rouge. Qui redonnerait le trait à Vert non plus en position P0 mais en position P2.1. Après analyse (récursive) de la position P2.1 Vert considère que cette position P2.1 vaut -5 points.

Mais, comme dans les jeux à somme nulle ce qui est bon pour l’un ne l’est pas pour l’autre, les -5 points pour Vert  sont en fait +5 points pour Rouge. Donc pour le moment la position P1.1, vaut du point de vue de Rouge, +5 pts.

Puis Verts envisage le coup R2 de Rouge qui débouche sur la position P2.2 qui, du point de vue de Vert  faut +1 points. Ce qui est mieux que les -5 pts de la position P2. Malheureusement pour Vert, entre R1 et R2 Rouge choisira le coup qui mène à la position la plus forte de son point de vue, donc  R1. Donc la position P1.1 continue de garder un potentiel de +5 pour Rouge.

Enfin, Vert envisage le coup R3 de Rouge qui débouche sur la position P2.3 qui, du point de vue de Vert faut -7 points, et donc +7 points pour Rouge. Bien sûr Rouge préférera ce coup R3 au coup R1 jusqu’à maintenant retenu. Donc la valeur de la position P1.1 passe de +5 à +7.


Première synthèse
: Si Vert joue le coup V1, la position P1.1 qui en résulte vaut, compte tenu de la meilleure riposte de Rouge,  +7 points.  Et donc -7 pour Vert ce qui est pour le moment la valeur de  P0.

Étape 2: mini-max

Vert analyse maintenant son deuxième coup possible à savoir V2. Pour juger de la position P1.2 ainsi obtenue il va étudier les ripostes possibles de Rouge.

Si on faisait le même raisonnement pour P1.2 que pour P1.1, mais avec les valeurs ci-dessous, on trouverait qu’après avoir pris la valeur -3 puis la valeur +9 la valeur de la position P1.2 serait de  +9 pour Rouge.  Ce qui reviendrait à -9 points pour Vert. Et comme Vert a un le coup V1 qui vaut -7 il ne jouera jamais le coup V2 qui vaut -9 donc encore plus mauvais que V1.

Si on faisait ainsi on serait dans la pure logique du mini-max : chacun maximise ses gains que l’autre cherche à minimiser. Mais en appliquant exactement la même logique à P1.2 qu’a P1.1 on ne profite pas pendant l'analyse de P1.2 de ce que l’on a appris pendant l'analyse de P1.1.


Étape 3: alpha-beta

Reprenons l’analyse de  P1.2. On sait qu’après l’analyse du coup V1 la position P0 vaut -7 et que ce que cherche Vert c’est un coup meilleur que -7. Donc tant que P1.2 à une valeur meilleure (du point de vue de Vert) que -7 c’est qu’on est en bonne voie pour que V2 remplace V1.

C’est ce qui ce passe après l’analyse de R4. La valeur de la position P2.4 est de +3 points pour Vert, donc de -3 points pour Rouge au niveau de P1.2, donc à nouveau  de +3 points pour Vert (au niveau de P0). A ce stade la séquence (V2 ; R4) semble meilleure que (V1 ; R3).

Mais quand on analyse  P2.5 découlant du coup R5 on se retrouve avec une valeur de P1.2 de +9 et donc de -9 pour Vert au niveau P0. Bien sûr jamais Vert ne jouera  V2 s’il s’expose à une riposte de Rouge valant -9, alors que Vert a déjà une meilleure solution qui vaut -7.

Tout cela on le sait au moment où on découvre que V2 mène à une situation pire que ce que l’on obtiendrait avec V1. On peut donc arrêter d’analyser les autres coups découlant de  P1.2 puisque déjà Rouge à la réponse qui tue au niveau de P1.2. Inutile de chercher et d'analyser les autres coups valides après  R5.

Important: Si l’on avait analysé R5 en premier on aurait immédiatement abandonné l’analyse de  P1.2. Mais si on avait découvert R5 en dernier on n’aurait fait aucune économie.
  • L’ordre d’analyse des coups a donc un impact sur les possibilités d’élagage de cette méthode. 
  • De plus cette méthode n’est pas applicable pendant l’analyse du premier coup (V1) puisque on n’a aucun repère.
  •  Enfin l’élagage n’est possible que si on analyse à au moins 2 coups de profondeur puisque l’élagage a lieu dans l’analyse des ripostes en se basant sur ce que vaut la position initiale.
De bas en haut, puis de haut en bas :
Au début de l’analyse de P0 (coup V1) on a descendu l’arbre, puis on a analysé les feuilles, puis en remontant on a pu attribuer une valeur à chaque position en utilisant la méthode mini-max : Vert maximise ses gains alors que Rouge minimise les gains de Vert.
Mais dans la suite de l’analyse de P0 (coup V2) on peut, en descendant l’arbre, faire descendre l’information comme quoi Vert cherche un coup meilleur que -7 et que l’on doit abandonner l’analyse d’un coup de Vert dès que l’on sait que sa valeur serra inférieure à cette limite.

L’informatique n’aime pas les cas particuliers :
L’idée que pendant l’analyse du premier coup on ne puisse pas analyser les coups avec la même méthode que pour les autres coups est fort déplaisante à l’informaticien… On va donc harmoniser ces deux situations.
On va analyser le premier coup en faisant comme si l’on avait déjà en notre possession un coup minable dont la note est -1000. On va donc descendre l’arbre dès le premier coup en disant « je cherche pour Vert meilleur que -1000 », tout comme on descend l’arbre au deuxième coup en disant  « je cherche un coup meilleur que -7 ». La tradition informatique appelle cette information ‘alpha’ : « Je cherche un coup meilleur que alpha ». La valeur initiale d’alpha doit représenter une valeur pire que le pire de tous les coups possible pendant le jeu. On aurait envie de dire moins l’infini, mais l’infini n’existe pas en informatique…

Et Rouge dans tout ça ?!
Nous avons raisonné en partant  d’une position P0 où Vert avait le trait. Mais après le coup V1 c’est Rouge qui a le trait face à la situation P1.1. Rien n’empêche de raisonner à partir de P1.1 comme nous l’avons fait à partir de P0, mais en respectant le point de vue de Rouge, qui est l’opposé de celui de Vert.
Rouge descendra donc l’arbre en disant « je suis à la recherche d’un coup meilleur que ‘beta ». On utilise  ‘beta’ pour Rouge afin de ne pas le confondre avec le seuil ‘alpha’ de Vert.
Nous avons donc nos deux adversaires qui descendent l’arbre à la recherche d’un meilleur coup qu’alpha pour l’un, que beta pour l’autre.

Et voilà, vous avez l’algorithme alpha-bêta

01 fonction alpha_beta(Position, profondeur, α, β, couleur)
02   si est_terminal(Position, profondeur, couleur) alors
03     retourner évaluer(Position, couleur)
04   finsi
05
06   pour chaque Enfant de Position faire
07     score := − alpha_beta(Enfant, profondeur+1, −β, −α, -couleur)
08     si score ≥ β alors
09       retourner score        # élagage α/β
10     finsi
11     si score > α alors
12       α = score              # max du mini-max
13     finsi
14   finpour
15
16   retourner
α
17 fin


Attention aux détails !
Ligne #03: l'évaluation de la position est faite du point de vue du joueur courant. Peut importe que ce soit le programme ou son adversaire.
Ligne #07; Notez bien les 4 changements de signes et le changement de position de  α et β.
Les 3 premiers changements signes viennent du fait que ce qui est bon pour l'un est mauvais pour l'autre. (- couleur voulant dire la couleur opposée)