Opensource-Heizungsregelung

In unserer WG haben wir eine Etagenheizung ohne Außentemperaturfühler, und Heizkörper mit einfachen Reglern ohne Thermostat. Das Ganze verstößt nicht nur gegen die Energieeinsparungsverordnung (“Zentralheizungen müssen beim Einbau in Gebäude mit zentralen selbsttätig wirkenden Einrichtungen zur Verringerung und Abschaltung der Wärmezufuhr sowie zur Ein- und Ausschaltung elektrischer Antriebe in Abhängigkeit von der Außentemperatur oder einer anderen geeigneten Führungsgröße und der Zeit ausgestattet werden.” (§ 14), ), sondern ist auch extrem nervig, weil man in den Räumen keine konstante Temperatur halten kann.

Mein Mitbewohner hat sich schon einen elektronischen Heizungsthermostat gekauft (aber noch nicht montiert). Klar, als Wiwi guckt er erstmal, was es auf dem Markt gibt.

Ich finde die Teile irgendwie etwas unflexibel, und wenn man was besseres will (mit zentralem Regler, der die Ventile per Funk steuert), wird man für Steuerung und zwei Regler leicht deutlich über 100 € los. Als Informatiker frage ich mich da: Gibt es da nicht auch eine Open-Source-Lösung? Naja, wohl nichts Fertiges, aber die Möglichkeiten werden schon diskutiert. Gefunden habe ich da eine Diskussion in einem Webforum und in der Newsgroup de.sci.electronics. Werde mir das mal durchlesen und gucken, was realistischerweise machbar ist.

Damit wären ja schon coole Sachen denkbar: Koppelung mit Wettervorhersage, Ferneinschaltung von der Uni aus, bevor man nach Hause kommt, etc. pp.

VMWare: NTFS-Partition vergrößern mit Linux-Bordmitteln

Da ich das Ganze schonmal gemacht habe und nicht mehr ganz zusammenbekomme, wird es dieses Mal notiert.

Erster Schritt: Die VMWare-Platte vergrößern, mit
vmware-vdiskmanager -x 20Gb WindowsXPPro32bit.vmdk

Dann die VM mit einer gparted-Boot-CD starten. Dazu muß man darauf achten, daß das VM-Fenster auch wirklich den Tastatur-Fokus hat und dann beim Power-On der VM auf die Esc-Taste hacken.

gparted startet dann, und man sieht, daß die Platte freien Speicherplatz hat. Mit Resize/Move kann man dann die Partition vergrößern.

Dabei laufen die Schritte

  • calibrate /dev/hda1
  • calculate new size and position of /dev/hda1
  • grow partition from 11.99 GiB to 19.99 GiB
  • check filesystem on /dev/hda1 for errors and (if possible) fix them

problemlos durch, aber bei “grow filesystem to fill the partition” hapert es.

Also ein Terminal starten, und dort erst mal ntfsresize ein paar Infos ausspucken lassen.

Dabei stehen dann unter anderem die aktuelle Größe von “volume” (also Dateisystem) und “device” (also Partition).

Erstmal ntfsresize -n -s /dev/hda1 – Simulation klappt.

Problem: Ich habe das Windows falsch heruntergefahren, Journal ist hinüber, also nochmal Rebooten (also: gleich darauf achten, das Windows sauber herunterzufahren). Das kostet also wieder ein Minuten.

Danach ging es dann ohne “-n” wunderbar. Also reboot eintippen, und gut. Beim nächsten Neustart überprüft Windows dann automatisch das Dateisystem, und dann ist alles fertig – man hat eine größere Platte.

Visual Studio SP1

Gerade habe ich unter Windows mal routinemäßig Updates installiert. Aber für das hier:

Visual Studio 2005 Service Pack 1
Date last published: 4/5/2007
Visual Studio 2005 Service Pack 1 updates Microsoft Visual Studio 2005, Microsoft Visual Studio 2005 Team System, Microsoft Visual Studio 2005 Tools for the Microsoft Office System, and Microsoft Visual Studio 2005 Team Explorer with the latest security and stability enhancements to help keep those systems up-to-date, reliable, and secure. The goal of all of our service packs is to increase the overall quality of the existing product features while maintaining a high level of compatibility. The installation of this service pack might take up to several hours. After you install this item, you may have to restart your computer.
System Requirements
Recommended CPU: Not specified.
Recommended memory: Not specified.
Recommended hard disk space: 6200 MB

muß ich erstmal die Platte vergrößern …

Character Description Language

I just stumbled across some pretty cool project at the junction of linguistics and IT. Of course, again, it concerns Chinese language processing …

The Character Description Language‘s aim is to provide a description language for Han ideographs. The project seems to be well-organized, and they have captured 56k CJK characters, including all from the BMP.

This data would probably be very useful for developing an Input Method Engine using a graphic tablet, or showing the decomposition of characters into their constituent parts. Alas, I have as of yet not been able to find the database – is it commercial stuff (namely, Wenlin) safely locked away from the interested public? That would really be a pity …

Paper eingereicht

Das Wochenende war mal echt Streß. Diverse Nachtstunden habe ich mit der Arbeit an meinem Paper für AGTIVE 2007 verbracht, dazu haben wir uns noch an den Feiertagen (Pfingstsonntag und -montag) im Institut gesprochen, um uns gegenseitig Hilfestellung bei Messungen, Formulierungen etc. zu geben. Gestern war dann Endspurt: 23:00 war die offizielle Deadline (da die wohl bei der Angabe der Zeitzone GMT+1 nicht an die Sommerzeit gedacht haben, eigentlich doch 24:00), bis dahin wurde noch fleißig an den Papers geschraubt. Kurz vor dem echten Endspurt gab es um ca. 20:00 noch Pizza, und nach Abgabe wurde dann eine Flasche Diabetikersekt geleert (das Zeug steht hier haufenweise im Kühlschrank) …

Mal sehen, ob es angenommen wird, cool wär’s ja schon …

Branchen mit SVN

Bruncanchen mit SVN ist ganz einfach, denkt man. Einfach ein svn copy, und im Nu hat man eine neue lazy copy, in der man nach Belieben Änderungen vornehmen kann.

So dachte ich mir auch, als ich das Projekt für meine Studienarbeit vom Kollegen geforkt habe. Aber Pustekuchen – dafür braucht man Schreibzugriffe auf das gemeinsame Oberverzeichnis, die ich nicht hatte. Also Arbeitskopie (Revision 336) ausgecheckt bzw. exportiert, in einen Checkout meines eigenen Pfades kopiert, und wieder eingecheckt. Damit sind dann natürlich die Log-Messages weg.

Heute habe ich dann einen Merge der Änderungen meines Kollegen von Revision 336 bis 476 abgeschlossen. Und was sehe ich da? Er hat die Log-Messages neu hinzugekommener Dateien einwandfrei übernommen. Das also geht von den Berechtigungen her. Wenn ich also statt des nicht erlaubten svn copy einen Merge von r1 bis r336, Ziel: mein Pfad, gemacht hätte, hätte ich (fast?) dasselbe Ergebnis erzielt, also alle Log-Einträge behalten etc. Schon irgendwie merkwürdig …

BFS – generic and fast

This weekend, originally I wanted to implement special BFS procedures for my student job, of course using generic programming and the like. Looking at the normal BFS implementation in Boost I noticed that it needs a ColorMap and allocates one as the default behavior. However, in many applications of breadth-first search one can use another map for this purpose, like one for distance or predecessors, and interpret a special value like -1 or the null pointer as white, i.e. not visited. Then one can no longer distinguish between gray and black nodes, though (I have not understood how this can become relevant for BFS – for DFS it’s clear), but one does not have to anyway in most applications. Doing so, one saves the memory for another map – normally one byte per vertex – and the overhead for updating it.

So I started working on an implementation of the ReadWritePropertyMap concept that is initialized with another map and a value for “white” and when queried for the color of a vertex reads the value of the underlying map and determines whether it is white. Write operations just do nothing. This was not totally easy, as with all this template stuff, even small mistakes lead to very long diagnostics. But the result is now here. So now there remains just the issue with the Koenig lookup, but I hope this will be solved as well …

BFS generisch und schnell

Dieses Wochenende wollte ich eigentlich Spezialbreitensuchmethoden für meinen Hiwi-Job implementieren, natürlich generisch und so. Beim Anschauen der normalen BFS in Boost fiel mir auf, daß das Teil ja eine ColorMap benötigt und standardmäßig eine anlegt. Dabei kann man ja für viele Anwendungen der Breitensuche dafür eine andere Map, zum Beispiel für Distanz oder Vorgänger, verwenden, und einen speziellen Wert, wie -1 oder den Nullpointer, als weiß, also unbesucht, ansehen. Dann kann man zwar nicht mehr zwischen grauen und schwarzen Knoten unterscheiden (mir ist noch nicht ganz klar geworden, welche Relevanz das überhaupt bei BFS haben kann – bei DFS ist es klar), aber das muß man ja in den meisten Anwendungen auch nicht. Damit spart man dann den Speicherplatz für eine weitere Map – immerhin im Regelfall ein Byte pro Knoten – und den Overhead für das Update derselben.

Also hab ich mich daran gemacht, eine Implementierung des Konzepts ReadWritePropertyMap zu erstellen, die mit einer anderen Map und einem “Weiß-Wert” initialisiert wird und bei Anfragen nach der Farbe eines Knoten den Wert aus der zugrundeliegenden Map liest und guckt, ob der Knoten weiß ist. Schreibzugriffe gehen einfach ins leere. Das Ganze war nicht ganz einfach, da mit dem Template-Geraffel auch kleine Fehler zu ellenlangen Fehlermeldungen führen. Aber das Ergebnis ist jetzt hier. Bleibt nur noch die Sache mit dem Koenig-Lookup, aber die wird mir hoffentlich auch jemand beantworten.

Statische Polymorphie dynamisch machen

Modernes C++ benutzt häufig statische Polymorphie, die auf Templates basiert. Das allerdings kann nicht nur zu Code-Bloat führen, sondern macht es auch unmöglich, die Objekte einer Klasse, die ein bestimmtes Konzept modelliert, in einer separat kompilierten Bibliothek zu benutzen – denn die kennt den Typ des Objekts ja nicht.

In graph-tool, genauer in graphml.hpp, bin ich auf eine schöne Musterimplementierung eines Wrappers gestoßen, der gewissermaßen statische Polymorphie in dynmische Polymorphie verwandelt.

Zum Anwendungsfall:

Es geht darum, GraphML-Dateien einzulesen. Dafür hat der Benutzer der Bibliothek ein Objekt einer Klasse, die das Konzept MutableGraph modelliert. Die Klasse mutate_graph stellt dann eine einheitliche Laufzeitschnittstelle für MutableGraphs zur Verfügung, die Wrapper für jeden einzelnen MutableGraph sind dann template class mutate_graph_impl, die von mutate_graph erben. Wo die Schnittstellen dann immer noch unterschiedlich sind, weil sie abhängige Typen verwenden, werden diese in boost::any gewrappt.

Et voilà – wir haben eine einheitliche Schnittstelle für MutableGraphs. Geht analog natürlich für fast beliebige andere Konzepte.

Begleitmaterial

Die Idealvorstellung vieler Profs, die ihre Vorlesungen mit Beamerfolien halten, ist ja vermutlich oft, daß sich die Studenten auf den vorher ausgedruckten Folien Notizen machen. Mag ja sein, daß das was bringt, aber ich weiß da nie, was ich aufschreiben soll. Entweder ist der Stoff eine Ansammlung von Fakten und die Erläuterungen dazu bloßes Rumgelaber, oder aber der Stoff ist so kompliziert, daß ich hinreichend damit beschäftigt bin, ihn zu verstehen und weder die Denkkapazität noch das Stoffverständnis habe, um zu entscheiden, was wichtig ist.

Umso wichtiger, daß man den Stoff hinterher nochmal nachvollziehen kann. Eine Möglichkeit: Der Prof hat seine Vorlesung auf Video aufzeichnen lassen. Suboptimal, denn nochmal will ich mir das Zeug eigentlich nicht anhören müssen. Zweite Möglichkeit: Die Folien sind hinreichend ausführlich und selbsterklärend, daß das geht. Schon besser, aber es fehlt immer noch die zweite Sichtweis, mit der man es dann vielleicht besser versteht. Dritte Möglichkeit: Es gibt ein Buch (oder mehrere Bücher), an die sich die Vorlesung über weite Strecken hält, einschließlich Notationen und Begriffen. Das ist IMO der Idealzustand, weil Bücher meist wirklich aus sich heraus verständlich sind.

Und diesen Fall darf ich zum Glück gerade bei der Vorbereitung auf die Übersetzerbau-Prüfung erleben. Die Folien von Prof. Goos entsprechen bei vielen “klassischen” Kapiteln inhaltlich sehr stark dem Buch von Goos und Waite: Compiler Construction. Das Buch ist naturgemäß an vielen Stellen um einiges tiefgehender, aber dieser Tiefgang hilft eher beim Verständnis, als daß er verwirrt.

Heute habe ich mir den Zusammenhang zwischen LR(1), LR(0), SLR(1) und LALR(1) reingezogen – und verstanden! Und ich muß sagen: Ein gutes Gefühl!

Fakultätsfest

Für den diesjährigen Tag der Informatik der Fakultät für Informatik der Uni Karlsruhe wurde die Werbetrommel mal richtig ordentlich gerührt: Die Einladung gab es nicht nur in allen möglichen Vorlesungen, nein, auch auf der Website der Uni und sogar der Stadt Karlsruhe erschien ein Hinweis. Zum Glück wurde da aber das Freibier nicht erwähnt, wer weiß, wieviele Leute sonst den Bierstand gestürmt hätten …

Das Vortragsprogramm hab ich dieses Jahr leider verpaßt (auch wenn es laut Oli recht interessant gewesen sein soll), aber zum Fest war ich dann natürlich da.

Eine Portion Häppchen hab ich auch ergattert, wobei ich zum Glück recht weit vorne stand, als ich vorhatte, mir nochwas nachzuholen, war die Schlange ziemlich lang, und danach waren die Häppchen dann alle.

pict2046.jpg

Dafür floß das Freibier wirklich reichlich. Nachdem Frau Prof. Zitterbart um ca. 19:00 das symbolische Faß angestochen hatte, gab es bis 21:30 alle Getränke kostenlos – in der Zeit hatte ich dann drei (oder waren’s vier) Bier und zwei Grape intus. Meine Helferbons für meine Schicht am Bierstand gab es zum Glück auch schon, so daß ich dazu ein leckeres Steakbrötchen essen konnte.

Danach wurde es dann aber schwierig: Ich mußte die Zeit bis zu meiner Schicht um 1 Uhr überbrücken. Und die Stimmung war, gelinde gesagt, ziemlich chillig, obwohl im Zelt (in dem sich kaum jemand aufhielt) eine Band spielte. OK, bis kurz nach zwölf ging es halbwegs, dann nochmal kurz nach Hause, und am Bierstand gab es dann doch noch recht viel zu tun, so daß ich recht schnell wieder wach wurde. Am Stand dann nochmal so drei bis vier Bier konsumiert, zum Glück konnte ich am Samstag ausschlafen (auch wenn’s nicht wirklich erholsam war, viel zu heiß …).

Und mein auf der Wiese verlorenes Brillenetui samt Sonnenbrille fand sich dann am nächsten auch bei den Fundsachen an. Juchu!

C++ und generisches Programmieren

Im Moment beschäftige ich mich gerade mit C++. Im Stroustrup (dem Stroustrup, also The C++ Programming Language. Special Edition.) bin ich inzwischen bei der Standardbibliothek angekommen, parallel habe ich angefangen, C++ Template Metaprogramming. Concepts, Tools, and Techniques from Boost and Beyond zu lesen – übrigens erstaunlich leicht lesbar. Diese C++ In-Depth-Serie scheint sehr empfehlenswert zu sein …

Vielleicht sollte ich noch kurz ausholen, wie ich zu C++ gekommen bin. Aus einem Problem bei Hennings 3D-Engine (Dreiecke – wenn möglich – zu Vierecken zusammenfassen, was auf einer geschlossenen Oberfläche immer möglich sei) entwickelte sich die Frage, wie man Matchings in nicht bipartiten Graphen findet. Des Problems Lösung: Der “Paths, Trees, and Flowers”-Algorithmus von Edmonds, Laufzeit: O(|V|*|E|*alpha(|V|*|E|)). Davon habe ich mir dann interessehalber mal das Paper besorgt, erschienen im Canadian Journal of Mathematics. Leider nicht online erhältlich, der Zeitschriftenband sollte aber in der Bibliothek jeder besseren Uni mit Mathe-Fakultät zu finden sein. Das Paper war dann irgendwie ziemlich langatmig, ich habe es immer noch nicht ganz durch :-| . Also habe ich mich auf die Suche nach einer Implementierung dieses Algorithmus gemacht. Fündig wurde ich bei der Boost Graph Library. Da ich in meinem Hiwi-Job Graphenalgorithmen implementiere, hat mich das natürlich gleich interessiert, und generisches Programmieren ist schon ziemlich hochgradig.

Auf meiner Vormerkungsliste in der Unibib (und langfristig auf meiner Anschaffungsliste) steht dann natürlich auch noch The Boost Graph Library: User Guide and Reference Manual. Und ich hoffe ja, hier im Institut auch mal statt dem Java-Rumgemurkse was mit der BGL machen zu können …

DUKATH

Endlich haben wir in der neuen WG Internet.

Mein ipw2100 hatte mit der im Notebook integrierten Antenne zwar richtig viele Netz im Empfang, konnte sich aber zu keinem verbinden.

Aber daß es mit einem richtigen Router, bei dem man ggf. auch eine Außenantenne anschrauben kann, besser funktionieren würde, war eigentlich klar. Also wurde ein Linksys WRT 54 GL angeschafft, der sich im Client Mode zu einem Dukath-Accesspoint verbinden sollte.

Da die Original-Firmware keinen Client Mode unterstützt, haben wir OpenWRT (RC5, White Russian) installiert. Der Router verbindet sich also mit dukath-stmb02, holt sich eine IP und macht NAT für das interne Netzwerk. Das interne Netz besteht übrigens aus einem WLAN, das von einem Netgear WG602 bereitgestellt wird; Hennings PC ist direkt per Kabel angeschlossen. Ins Uninetz (das Netz, in dem der Router seine IP bekommt, ist nur ein Transitnetz mit sehr eingeschränkten Möglichkeiten) kommen die einzelnen Computer dann jeweils einzeln über einen VPN-Client (Cisco 3000 Access Concentrator, der vpnc funktioniert doch irgendwie einfacher als der Client von Cisco. Und für amd64 gibt es den vermutlich eh nicht …). vpnc auf dem Router würde eh keinen Sinn machen – der 300 MHz-Prozessor von Broadcom (MIPS-ISA) kriegt damit bei voller CPU-Auslastung wohl nur 30 kb/s hin.

A propos 30kb/s: Im Originalzustand war das so ungefähr das Maximum bei geschlossenem Fenster. Aber wofür Konservendosen doch gut sein können … Da bekommt die Dipol-Antenne gleich eine ausgeprägte Richtcharakteristik, und den 3W-Antennenverstärker für 700 € (der eh nicht erlaubt wäre) kann man sich auch sparen …

Mal sehen, ob es heute abend noch besser läuft, wenn die zweite Antenne auch mit Konservendose ausgestattet ist …

Endlich fertig

Endlich ist unser Minijava-Übersetzer fertig: Alle Beispielprogramme kompilieren, laufen fehlerfrei durch und geben etwas mehr oder weniger Sinnvolles aus.

Jetzt noch ein paar Debug-Ausgaben wieder entfernen und dann, wenn Pascal aus dem Heimaturlaub zurück ist, vorführen – und damit sollte das Praktikum dann abgeschlossen sein …

Insgesamt hab ich dabei doch sehr viel gelernt, auch wenn es ein Haufen Arbeit war und man sich häufig alleine ganz schön durchbeißen mußte – aber das wird im Berufsleben ja auch nicht anders.

Vermutlich hab ich so ziemlich alle Fehler gemacht, aus denen man bei diesem Praktikum was lernen kann ;-)

Beispiel-Firm-Graph

Lokale Variablen

Was mir gerade mal wieder bei meinem Hiwi-Job aufgefallen ist, als ich mit altem Code zu tun hatte: Viele Leute scheinen irgendwie davon auszugehen, daß lokale Variablen irgendwie teuer sind …

Entsprechend steht dann sowas wie

m.insert(obj.get(i), obj.get(i).value());

statt

Typ tmp = obj.get(i);
m.insert(tmp, tmp.value());

Lokale Variablen werden üblicherweise in Registern gehalten, nur wenn die nicht reichen, auf dem Stackframe. Zwischenergebnisse in Ausdrücken müssen ja auch irgendwo gespeichert werden, sind also im Prinzip das gleiche wie alias-freie lokale Variablen. Wenn man sich einen Datenflußgraphen anschaut, macht es daher auch überhaupt keinen Unterschied – normalerweise.

Im vorliegenden Fall liegt der Unterschied darin, daß im ersten Fall get(i) zweimal, im zweiten Fall dagegen nur einmal aufgerufen werden muß. Natürlich kann es semantische Unterschiede geben, wenn get() nicht seiteneffektfrei ist. Aber als Programmierer sollte man das wissen. Der Compiler dagegen weiß es nicht so ohne weiteres, und kann es außer in ganz trivialen Fällen auch nicht vernünftig feststellen, muß es also meist bei zwei Aufrufen belassen, die nicht durch common subexpression elimination beseitigt werden können.

Wir halten fest: Das zweite Beispiel ist besser lesbar und resultiert jedenfalls nicht in schlechterem Code als das erste.

Do no evil

Do no evil – das ist ja bekanntlich die (öffentlich vertretene) Philosophie von Google.

Und dieses gute Unternehmen mit ethischen Prinzipien filtert nun in China politisch “heikle” Themen wie Taiwan oder Tibet. Da hat man sich mit dem Reformkommunismus chinesischer Prägung (in normalem Deutsch: Staatskapitalismus) ja hervorragend arrangiert.

Immerhin wird das nun Thema einer Anhörung des US-amerikanischen Senats-Unterausschusses für weltweite Menschenrechte.

Softwareprozesse

So langsam verstehe ich, was der Sinn von “Schnell funktionierenen Code erzeugen” und “Falls nötig, refaktorisieren” in Softwareprozessen wie XP ist. Erst, wenn man man mit einem (selbst geschriebenen) Grundgerüst eines Frameworks eine (funktionierende) Anwendung geschrieben hat, weiß man, was im Framework fehlt. Und zwar sieht man dies daran, wo der Code der Anwendung Redundanzen enthält, die man dadurch beseitigen kann, daß man im Framework geeignete Abstraktionen zur Verfügung stellt.

IMO kann man das auch nicht vorausplanen. Man weiß eben nicht vorher, welche Abstraktionen sinnvoll sind. Versucht man es dennoch, erhält man im Regelfall ein Framework, das entweder nicht zu durchschauen ist, weil es eine enorm komplexe Schnittstelle hat, so daß man eine weitere Schicht darüber braucht, um diese Komplexität zu handlen (beliebtes Anti-Pattern: Add an extra layer of indirection), oder es bietet nicht die richtigen Funktionen, so daß die Anwendung schließlich ein einziger Workaround ist (oder man wieder mal eine zusätzliche Schicht eingefügt hat).

Das Ganze formalisieren zu wollen, ist meines Erachtens zum Scheitern verurteilt. Um die nötigen Abstraktionen bestimmen zu können, muß erstmal etwas Konkretes da sein. Das nötige Fingerspitzengefühl, um zu wissen, wieviel Konkretes da sein muß, ist wohl ein wichtiger Schritt in der Entwicklung jedes Programmierers.

Unnötig zu sagen, daß man sowas in einer Vorlesung (Softwaretechnik) ganz sicher nicht lernt – die bis jetzt knapp 140 Stunden Programmier-Hiwi-Job haben da deutlich mehr gebracht.

Achja, das “Standard”-V-Modell mit Entwurfsphase und Programmierern, die stur nur das ihnen zugewiesene Modul betrachten, stelle ich mir doch arg langweilig vor. So möchte ich nicht arbeiten müssen.