From our popular series "Sex 101" today's lesson is the important topic: What is not a condom? You are surely familiar with the situation, that you are looking around you in the room, searching for a condom. The puzzled glance, shows that the you do not know what a condom looks like. To give you a few hints to arm you for this embarrassing situation, we made an extensive list of what is actually not a condom.

So an to give you a hint what a condom does look like, here is a picture of it. Get them, use them, they are cheap and safe. And have a good damn time:

Posted Fr 10 Mai 2013 18:00:36 CEST

Compilerbau 2

Nachdem ich letztes Semester schon Compilerbau 1 gehört habe, gibts dieses Semester die Fortsetzung. Nachdem wir einen Compiler gebaut haben, der eine Spielzeugsprache zerteilt, parsed, daraus Zwischencode generiert und letztendlich Code für eine spezifische Plattform (z.B. x86 oder die JVM) erzeugt, kommen jetzt die Optimierungen rein. Also Beispielsweise Umformungen auf dem Zwischencode, der unnötige Operationen spart. Zum Beispiel kann man es sich sparen den Index für ein Array zweimal auszurechnen, wenn sich der Offset nicht geändert haben kann.

int arr[31], b;
arr[30] = foo();
b = arr[30];

Hier würde ein naiver Compiler den Offset für das 30. Element (120 Byte offset) zweimal ausrechnen, ein optimiernder Compiler würde ihn erstens nur einmal ausrechnen, und zweitens schon zur Übersetzungszeit ausrechnen.

CPU Design

Eine extrem Spannende Vorlesung in der, man von Grund auf erklärt bekommt, wie man eine CPU baut und welche Probleme einem dabei begegnen werden. Es wird zunächst die Arithmetische Logische Einheit (ALU) gebaut, dann Speicher und es wird weitergehen zu Caches und Multi-Core Architekturen. Das wird also noch richtig spannend.

Das was diese Vorlesung für mich wirklich interessant ist, ist dass ich die Laborübungen dazu mache. Dabei baut man in einer kleinen Gruppe seine eigene CPU in VHDL, also einer Hardwarebeschreibungssprache. Dabei darf man keine angenehmen Sprachkonstrukte von VHDL (wie if oder so modernes Zeugs) benutzen, sondern muss alles diskret aus Gattern aufbauen und vor allem auf das Timing achten. Um davon mal einen Eindruck zu vermitteln, hier ein Stück VHDL aus unserer CPU, der ein Eingangswort negiert, falls ein Bit im Operationswort gesetzt ist:

-- negate the second input value, when bit 1 is set
sub_bitmask <= (others => operation(1));

-- Instanciate an XOR gate with 32 input pins, and negate it with 
-- the sub_bitmask. The output is connected to add_second_operand
negate_i2: entity work.op_xor
    generic map (width => 32)
    port map (
      i1 => i2, i2 => sub_bitmask, o => add_second_operand);

Die fertige CPU wird mit 333MHz laufen, wird Cache haben und gepipelined sein.

Organic Computing

Beim Organic Computing geht es darum, natürliche Gebilde zu betrachten, und aus der Betrachtung Algorithmen und Systeme abzuleiten, die sich gut an ihre Anforderung anpassen können, und nicht allzu spezialisiert sind.

Ein Beispiel, das wir bisher in der Vorlesung machen ist Partikelschwarmoptimierung. Der Partikelschwarm simuliert das Verhalten von irgendwelchen Tierschwärmen, die sich auf irgendeinen Punkt zum Landen einigen wollen. Die PSO ist eine Heuristik zur Lösung von kontinuierlichen Optimierungsproblemen. Also der Frage, wo liegt das Minimum für eine n-stellige Funktion.

Die Population an Partikeln die man erzeugt wird zunächst zufällig verteilt. In jeder Runde misst jedes Partikelchen, den Funktionswert an der Stelle, an der er gerade ist. Ist dieser Wert besser als der bisher beste Wert, den er selbst je besucht hat wird dieses lokale Optimumg geupdated. Ist der Wert auch noch besser als die lokalen Optima aller anderen Partikeln wird ein globales Optimum auch noch geupdated. Nachdem gemessen wurde, werden alle Partikel bewegt: Jedes Partikelchen hat eine aktuelle Geschwindigkeit, zudem wird er vom eignen lokalen Optimum und vom globalen Optimum angezogen. Das ganze noch mit ein bischen Zufall gewürzt und fertig ist der Partikelschwarm.

Es wird in der Vorlesung auch noch Ameisenalgorithmen, PageRank und Peer-to-Peer Netzwerke geben.

Mobile App Development

MAD ist ein Projekt bei dem eine Android App im Team entwickelt werden soll. Meine Gruppe ist ein sieben Köpfiges Team, das FASL weiterentwickeln soll. FASL, eine Skriptsprache für mobile Geräte, die letztes Semester schon von einer anderen Gruppe begonnen wurde. Jetzt soll FASL 0.2 auf Version FASL 1.0 gehoben werden.

Bei MAD geht es jedoch nicht nur die blose entwicklung, sondern auch um Agile Methoden zum Projekt Management. Es gibt also jede Woche einen Sprint, bei dem gewisse Tickets abgearbeitet werden sollen, um so die App jede Woche ein Stück vorwärts zu bringen.

Das Projekt ist bisher ganz lustig, und ich habe mit dem Backend Teil geschnappt und kann so meine Erfahrung aus Compilerbau 1 ganz gut einsetzen. Und wenns gut läuft muss ich nicht so viel GUI Code schreiben.

Advanced C++ Programming

Ein kleines Seminar mach ich auch noch. Hier geht es um gewissen Aspekte fortgeschrittener C++ Programierung, die man nicht jedem Anfänger in die Hand drückt. Ich werde 'C++ Meta Template Programming' und 'Continous Integration' machen. Also ein Sprachthema und ein Projektmanagementthema, wobei ich für beide Themen einen Vortrag halten werde.

Posted So 05 Mai 2013 12:43:09 CEST

In zwei Wochen nehme ich auf einem "Symposium Künstliches Leben" an einem Workshop über synthetische Biologie teil. Das ist zwar eigentlich kein Gebiet für das ich bisher wahnsinniges Interesse gezeigt habe, aber finde ich dennoch interessant. Für diesen Workshop soll ich mich auf spezielles Thema, nämlich "Whole-Cell Simulation" vorbereiten. Deswegen habe ich mich etwas in das Thema eingelesen, um zu erfahren wozu das überhaupt gut und sinnvoll ist, und was die Biologen/Mediziner sich davon versprechen.

Wie der Name schon sagt geht es bei Whole-Cell Simulation darum, eine ganze lebende Zelle zu simulieren, samt aller beinhaltetend Stoffwechselwege und Regelkreisläufe. Die Simulation einer ganze Zelle ist ein Schritt weiter in der Entwicklung "In Vivo", am lebenden Organismus; "In Vitro", in Reagenzglas; und jetzt eben "In Silico", nur noch als Simulation im Rechner. Der Begriff "In Silico" ist zum ersten mal, laut der englischen Wikipedia, in einem Workshop Ende der 80er Jahre aufgetaucht.

Zunächst muss man sich klarmachen, welche Mechanismen grundsätzlich in so einer Zelle von statten gehen. Dabei handelt es sich um Umwandlungspfade von einem oder mehreren Stoffen in einen oder mehrere anderen Stoffen. Ein prominentes solches Beispiel unseren eignenen Zellen ist die Glykolyse. Bei der Glykolyse wird in mehreren Zwischenschritten aus Einfachzuckern ATP hergestellt, das der primäre Energieträger in unseren Zellen ist und für viele andere Prozesse und Pfade gebraucht wird. Nun laufen diese chemischen Prozesse nicht so schlagartig ab, wie man sich das meistens vorstellt. Es braucht Zeit, die richtige Temperatur, die Anwesenheit von Katalysatoren kann alles ändern, und selbst dann stellt sich häufig ein irgendwie geartetes gleichgewicht zwischen den Eingangs- und den Ausgangsstoffen ein.

Ein ganz anderer interessanter Mechanismus ist die Proteinsynthese. Dabei wird zunächst aus einem aktiven Gen in der DNA eine Messenger-RNA durch die RNA-Polymerase transkribiert. Hierbei wird tatsächlich nur ein Teil der DNA herauskopiert und in ein anderes Format gebracht. Man kann es, denke ich, wie das Laden eines Programms in den Hauptspeicher sehen. Diese mRNA kann dann den Zellkern verlassen, was die DNA nicht kann, und wird dann an den Ribosomen (molekulare Komplexe die in der Zelle an mehreren Stellen da sind) zu Proteinen umgebaut. Der Mechanismus ist an der Stelle ganz interessant. Proteine sind ja Verbindungen aus mehreren Aminosäuren. In der mRNA werden aus immer drei Basentriplets (ein Codon) eine Aminosäure. Da es vier Basen gibt kann jedes Triplet 3^4 = 64 verschiedene Zustände haben. Allerdings gibt es nicht zu jedem Zustand ein Basentriplett, sondern auch so Dinge wie Stoppcodes bzw. Doppelbelegungen. Man kann sich also die Translation an den Ribosomen wie das assemblieren eines Assemblerprogramms vorstellen. Es entsteht dabei eigentlich keine Herabsetzung des Abstraktionsniveaus. So, was ist hierbei noch interessant für die Whole-Cell Simulation? Ob ein Gen aktiv oder nicht aktiv ist, also ob es zu mRNA transskribiert wird, kann von verschiedensten Faktoren abhängen. Zum Beispiel auch von der Konzentration der erzeugten Proteine. Und voila wir haben einen 1a Regelkreis, den man mit einer Differentialgleichung darstellen kann.

Was dann noch viel mit in diese Art der Simulationen mit reinspielt, sind stochastische Prozesse, ob überhaupt eine Reaktion stattfindet, und inwieweit die Innercelluären Strukturen, die doch einen ganz schön grossen Teil der Zelle ausfüllen, Reaktionen behindern.

Aber was verspricht man sich konkret von der Simulation einer ganzen Zelle? Zunächst ist klar, wenn die Simulation und das Model der jeweiligen Zelle gut genug ist, kann man damit prima vorhersagen machen, wie sich die Zelle verhalten wird, wenn man an irgendwelchen Rahmenbedingungen spielt. Dies ist auf der einen Seite für die Forschung interessant, weil man damit vielleicht finden kann wie bestimmte Mechanismen funktionieren (wenn die Simulation von der Realität noch abweicht), aber es sollen auch die Wirkungen von Medikamenten simuliert werden. Bisher ist das Vorgehen bei Medikamenten so, dass man sich eine genügend grosse Gruppe von Menschen nimmt, die man mit dem Wirkstoff füttert und schaut, wie sich die Wirkung zeigt. Man geht also Statistisch vor.

Allerdings ist das bei so Krankheiten wie Krebs, was ganz kurz erklärt ein genetischer Defekt in einer Zelle ist, die dazu führt, dass die Zelle nicht mehr stirbt und/oder sich furchtbar schnell teilt. Es sind bis jetzt über hundert Gene bekannt, die die Mechanismen Zellteilung und Zelltod beeinflussen. Zu der Unübersichtlichkeit kommt noch dazu, dass Gene sich nicht monoton verhalten. Also nehme man an, dass es zwei Gene gibt A und B. Ist in einem Menschen Gen A oder Gen B aktiv, dann wirkt das Medikament besonders gut. Allerdings bedeutet dies nicht, dass wenn A und B gleichzeitig an ist, das Medikament besonders gut wirkt. Der Gen-Wirkungs-Einfluss addiert sich nicht, Gene verhalten sich nicht monoton. Unangenehme Sache.

Ein generisches Zellmodell dagegen könnte man mit Teilen des Erbguts des speziellen Patienten füttern (Hier ist wichtig anzumerken, dass DNA Sequenzierung (DNA Pampe -> Textfile) inzwischen ein schneller und relativ billiger Prozess ist, Stichwort Hochdurchsatzverfahren) und dann den Einfluss des Medikaments simulieren. Braucht allerdings alles noch einiges an Rechenzeit. In dem einen Papier haben sie eine E. Coli Bakterie auf GPUs simuliert, und gemeint sie hätten für 1 Stunde Echtzeit, 200 Stunden GPU Zeit verbraten, auf so mehreren Nvidia Teslas.

Und hier noch ein paar weiterführende Links:

  • Laborwelt Artikel
  • Tomita, Masaru. (2001): Whole-cell simulation: a grand challenge of the 21st century. TRENDS in Biotechnology. .
  • Roberts, Elijah ; Magis, Andrew ; Ortiz, Julio ; Baumeister, Wolfgang ; Luthey-Schulten, Zaida. (2011): Noise Contributions in an Inducible Genetic Switch: A Whole-Cell Simulation Study. PLoS Comput Biol. Public Library of Science. 7(3), e1002010
    [doi> 10.1371/journal.pcbi.1002010].
  • Karr, Jonathan ; Sanghvi, Jayodita ; Macklin, Derek ; Gutschow, Miriam ; Jacobs, Jared ; Bolival, Benjamin ; Assad-Garcia, Nacyra ; Glass, John ; Covert, Markus. (2012): A whole-cell computational model predicts phenotype from genotype. Cell. Elsevier. 150(2), 389--401.
Posted So 31 Mär 2013 18:17:37 CEST Tags:

In the last days the webservice bang with friends came up in the media. This is a service were you can say for each of your facebook friends that you are into them. And only if the other person states the same interest, both are informed that there is mutual interest. This ensures that there is no moment, where one person said "I'm interested in you" and the other one denies the request, which can be hurtful. Although it shouldn't a big deal with adult human beings, but hey humans are complicated.

So what is the problem with this here? Clearly the central instance, in this case facebook, that holds the attraction database. What if i don't trust that third instance, or the third instance loses its database. Then my secret would be unveiled, and everybody would know my interest. But we can do better. So let's collect what should be the central points a better protocol must accomplish:

  • No central instance should be necessary to operate the basic version of the protocol.
  • A person who denies a request must not get any information about the choice the other person made.
  • Both parties know at the same time wether the protocol was successful, or not. This prevents, that the protocol is ended when one person knows the answer, and the other one doesn't.

But there are some points the protcol doesn't have to fix:

  • A person with a positive answer, knows that the other one said no. This is just a natural conclusion, since otherwise the protocol would have succeded.
  • It cannot prevent people from lying. But hey, nothing can do that.

So what path should we go to accomplish the goals. The basic outline of the protocol is to generate a common secret between the two parties with Diffie-Hel;lman, which only succeedes if both parties say "yes". Otherwise no common secret should be generated. The second phase utilizes a stepwise challenge-response schema to ensure that both have generated the same secret.

So let's have a look at the common schema for a Diffie Hellman Key exchange (Image comes from Wikipedia and is Public Domain):

So as you see in the process the schema succedes if both parties start with the same "common paint". Our starting point is now, that each party only then uses the "common paint", when it says "yes", otherwise it uses a different paint. We have to choose the different paint in such a way that, no one can conclude from the published fragments wether i've choosen the right common paint or another one. When both start with the common paint, they have a secret in common, otherwise they won't produce a secret.

So now lets implement this stuff with a good DH algorithm. The most used case of DH is the usage of a prime number p and a generator g, which is a primitive root modulo p. p,g together are the common paint. Everybody chooses a private secret s and calculates gsecret_a mod p, which is published. Then the other one does the same with the received public key reveivedsecret_b mod p = gsecret_a * secret_b mod p.

So now to our protocol again; As a prime number and generator we use a secure prime from RFC3526, which is recommended for DH. So iff the person wants to give a positive answer, it uses the suggested generator, otherwise it uses a random number that is different to the generator. This does ensure the protocol fails, but is it possible to detect whether a person has used the correct generator or a random number? Since the generator is a primitive root, its multiplicative group modulo p are all numbers in [0, p-1]. Therefore our published key could also be generated with the correct generator, when we would have chosen a different secret in the first place. This ensures our deniability.

Now at this point both parties have a key, but nobody knows whether the other one has generated the same key. If one party starts to publish its key the other one would already know whether the protocol has succeeded or not, and could stop the protocol without unveiling if he has the same secret.

Therefore we will do a multiple step challenge response schema, where stepwise everybody has to unveil a bit of information. If the bit is not correct the other party knows that the other one hasn't the same secret. He can stop the protocol, or send random answers. In practice we take rounds. Everyone sends a random number. The other has to encrypt the random number with the generated secret and does send back a bit of information about the result (e.g the lowest bit). With each round of challenge-response we gain more confidence that the other does not only guess the results, but really has generated the same key.

So I believe that with this protocol, we have accomplished all features, we needed. To create deniability you have to play this game also with people you don't have interest in. This ensures that you don't know from the fact that the protocol takes place, that someone is interested in you.

So I have implemented this protocol in python, and wrote an plugin for the irssi IRC program. The source code is on github. Please leave some comments if this shit is broken. I would like to improve it.

Posted So 17 Feb 2013 09:58:38 CET Tags:

Gestern hab ich ja über Selbstmodifizerende Binaries geschrieben. Das möchte ich heute etwas fortsetzen. Allerdings geht es diesmal nicht um dauerhafte Modifikation, sondern um Modifikation die während der Laufzeit bestehen bleibt. Aber theoretisch könnte man beides auch verbinden. Vor längerer Zeit habe ich mal darüber nachgedacht, dass man ja manchmal ein System dynamisch umkonfigurieren will. Dabei werden dann die unterschiedlichen Varianten über eine Wenn-Abfrage ausgewählt:

if (featureA.enabled()) {
    // Feature A;
}
if (featureB.enabled()) {
    // Feature B;
}

Dies führt allerdings dazu, dass zur Laufzeit beständig Funktionsaufrufe an die .enabled() Funktionen gemacht werden. Der dazu passende Assembler sieht dann ungefähr so aus:

 e8 66 05 00 00          call   8048a6e <__enabled_featureA>
 83 f8 17                cmp    $0x17,%eax
 75 ab                   jne    80484c0 <main+0x10>

Jetzt habe ich mir den Spass gemacht die patch-point Bibliothek zu schreiben. Sie löst das Problem dadurch, dass sie die Stelle, an der solche Abfragen stehen entweder durch nop Instruktionen ersetzt, oder durch einen unbedingten Sprungbefehl. Das ganze wird dann noch mit einem bischen synaktischem Zucker gewürzt, und dann sieht der C-Code dazu so aus:

#include <patch_point.h>
#include <stdio.h>
patch_point_list ppl;

void foo() {
    patch_point(&ppl, "pp") {
        printf("enabled\n");
    } else {
        printf("disabled\n");
    }
}

int main() {
    foo();
    patch_point_disable(&ppl, "pp");
    foo();
}

Dabei sieht das patch_point macro etwas seltsam aus, aber es wird vom Präprozessor zu einem if (__patch_point(&ppl, "pp") == 23 gemacht. Nach dem komplieren sieht der Code ungefähr so aus, wie das Assembler-Fragment oben. Die Funktion __patch_point sucht sich dann über die Rücksprungaddresse die Stelle im Code raus, wo diese Instruktionen stehen. Nach dem ersten Aufruf, patcht sich der Funktionsaufruf selbst raus, und speichert die Stelle und weitere Informationen in der patch point Liste ab. Der Code sieht dann so aus:

 90 90 90 90 90          nop nop nop nop nop
 e9 99 02 00 00          jmp    804878d <main+0x10>

Mit dem Aufruf zu patch_point_disable Wird der jmp Befehl wieder rausgepatcht, und der Code im Speicher sieht dann so aus:

 90 90 90 90 90          nop nop nop nop nop
 90 90 90 90 90          nop nop nop nop nop
Posted Di 22 Jan 2013 21:19:01 CET Tags:

Mir ist gerade so ein Gedanke gekommen. Eine Geschichte die ich mir mal vor Jahren ausgedacht habe um in einem kleinen Programmiercontest an der Uni schneller zu sein als alle anderen. Die Aufgabe damals war es ein sort(1) zu schreiben, das schneller ist als das Standard GNU sort und schneller als die sorts aller anderen Teilnehmer. Was die Sache die ich hier beschreiben werde erst ermöglicht hat, war, dass man nur auf gewissen Listen schnell sortieren musste, nicht auf beliebigen Listen.

Also die Idee war folgende: Beim ersten mal laufen sortiert man ganz normal, egal wie langsam, aber man merkt sich die Umsortierungen, die es braucht um eine sortierte Datei zu erzeugen. Und zwar im Binary selbst. Also muss man hierfür sein eigenes Binary modifizieren, damit der in-binary Cache aufgefüllt wird.

/**
  * @param: self - path to the binary (probably argv[0])
  * @param: 
  * @return: Pointer to beginning of the mmaped executable
  */
char *open_self(char *self, int *size) {
    // We open the binary in readonly mode, because
    // we cannot open it read/write, since the kernel locks executed files.
    int fd = open(self, O_RDONLY);
    if (fd < 0) return NULL;

    struct  stat fdinfo;
    /* Stat the filedescriptor and check if it is a actual file */
    assert ( fstat(fd, &fdinfo) != -1);
    *size = fdinfo.st_size;
    char *ptr = mmap(NULL, fdinfo.st_size + 5,
                     PROT_READ, MAP_SHARED,
                     fd, 0);
    // delete our own binary, since we cannot open it read/write, but
    // we can delete it, and add another binary instead
    if (unlink(self) < 0)
        return NULL;

    // create a new binary, that is executable
    int newfd = open(self, O_CREAT | O_RDWR, 0755);
    if (newfd < 0)
        return NULL;

    // make the new binary the right size
    if (ftruncate(newfd, *size) == -1)
        return NULL;
    char *newptr = mmap(NULL, fdinfo.st_size,
                        PROT_READ | PROT_WRITE, MAP_SHARED,
                        newfd, 0);
    if (!newptr)
        return NULL;

    // copy the old binary content to the new file
    memcpy(newptr, ptr, fdinfo.st_size);

    return newptr;
}

Hier zunächst die Funktion die es einem erlaubt das eigene Binary zu modifizieren, dazu muss das laufende Programm zunächst die Datei löschen, aus der sie inkarniert wurde, um danach eine neue Datei mit selbem Inhalt anzulegen. Das muss so gemacht werden, weil der Kernel es einem nicht erlaubt das eigene Binary schreibend zu öffen.

/**
   Simply find an byte pattern in the binary.
 */
int* find_pattern(int* start, int size, int marker, int marker1) {
    for (int i = 0; i< size -1; i++) {
        if (start[i] == marker && start[i+1] == marker1)
            return &start[i];
    }
    return NULL;
}

struct nodename {
    int marker[2];
    char nodename[255];
};

static struct nodename nodename = { {0xDEADBEEF, 0x55555555} };


int main(int argc, char *argv[]) {
        int self_size;
        if (nodename.marker) {
            int *self = (int *)open_self(argv[0], &self_size);
            int *datasection_foobar = find_pattern(self, self_size/4,
                                                   0xDEADBEEF, 0x55555555);
            if (datasection_foobar) {
                printf("binary is unmodified until now. Let's remember,"
                       "where we were run in the first place\n");
                struct utsname buf;
                uname(&buf);
                printf(".data.nodename.nodename = \"%s\"\n", buf.nodename);

                // Copy the name of the machine into the binary
                struct nodename * nodename = (struct nodename *)datasection_foobar;
                strcpy(nodename->nodename, buf.nodename);

                // Remove the marker from memory structure, to disable
                // this code path forever.
                nodename->marker[0] = 0;
                nodename->marker[1] = 0;
            }
        }
        printf("nodename.nodename = \"%s\"\n", nodename.nodename);
}

Hier dann der Rest des Beispielprograms, dass dan den zurückgegebenen Zeiger verwendet um ein Pattern zu finden. Wird das Pattern gefunden läuft man zum ersten mal und man "cached" sich im eigenen Binary, auf welcher Maschine man das erste mal ausgeführt wurde. Beim zweiten Aufruf ist der marker nicht mehr da und dieser Code Pfad ist nicht mehr da. Die Ausgabe sieht dann so aus:

$ gcc main.c  -std=c99 

$ ./a.out
binary is unmodified until now. Let's remember, where we were run in the first place
.data.nodename.nodename = "terminus"
nodename.nodename = ""

$ ./a.out
nodename.nodename = "terminus"

Die main.c gibts dann hier

Posted Mo 21 Jan 2013 23:07:48 CET Tags:

Ich esse gerne Sushi. Und vor allem mache ich gerne selber Sushi für Freunde und mich. Und weil ich es so gerne selber mache, und manche Leute denken, dass das irgendeine Geheimwissenschaft ist, wollte ich mal meine Vorgehensweise beim Sushi machen niederschreiben. Und so einige Erfahrungen aus der Ecke nicht-traditioneller Sushi Fillings erzählen. Wenn ich hier von Sushi rede meine ich hauptsächlich maki, also Sushi, dass ein Filling hat, dann Reis und aussen mit einem Nori-Blatt umwickelt ist (geröstete Algenblätter). Also das was man sich als Westeuropäer unter Sushi vorstellt.

Also die Vorgehensweise ist relativ einfach: Das wichtigste ist den Reis zu kochen. Dazu nimmt man normalerweise speziellen Sushi-Reis, den man im Asialaden bekommt. Vor dem kochen muss man Sushi-Reis waschen, weil das ganze sonst zu klebrig wird, und nur noch an den Fingern klebt. Wenn der Reis mit etwas weniger Wasser als normal (1.5 Tassen Wasser auf 1 Tasse Reis) gekocht ist, schüttet man eine gesättigte Reisessiglösung darüber und rührt sie ein. Die Reisessiglösung macht man ganz einfach selber indem man in eine passende Menge Reisessig (gefühlt so eine dreiviertel Tasse für 2 Tassen trockenen Reis) solange Zucker einrührt, bis sich dieser auch nicht mehr unter rühren auflößt. Der fertige Reis muss jetzt noch kalt werden (Tipp: Lasst ihn kalt werden, sonst verbrennt man sich die Finger, ich weiß wovon ich rede).

Nun kommt auf ein Nori-Blatt, dass mit der glänzenden Seite nach unten auf die Bambusmatte gelegt wird, ca. ein halber Zentimeter von der Reispampe, wobei man einen Zentimeter in die Richtung in die man Rollen will Platz braucht um das ganze wieder zu zukleben. Zum verteilen des Reis sollte man seine Hände in kaltem Wasser nass machen, sonst hat man Sushi auf den Händen und nicht am Blatt. Auf das ganze kommt dann das Filling, das ganze wird gerollt, der Zentimeter Nori-Blatt auf dem kein Reis ist mit Wasser angefeuchtet und das ganze zugeklebt. Die Rolle noch in Stücke schneiden und schon ist man fertig. Alles garkein Hexenwerk, man braucht nur etwas Erfahrung, die man aber auch recht schnell macht. Das ganze ist relativ geduldig was Fehler angeht.

Nun kommen wir aber zu den Erfahrungen die ich mit nicht ganz traditionellem Sushi gemacht habe. Weil der Sushireis im Asialaden doch relativ teuer ist, im Vergleich zu normalen Reis, habe ich das ganze mal mit Milchreis-Reis probiert. Das ist, wie der Sushi-Reis, ein Rundkornreis und kostet etwa ein Drittel vom Sushi-Reis. Man kann seinen Sushi-Reis auch damit Strecken, funktioniert wunderbar. Nur dass ich bei reinem Milchreis-Reis den Reis nicht gewaschen hab, damit er genug klebt.

Als nicht-traditionelle Fillings kann ich Erdbeeren empfehlen. Dafür wurde ich schon als Sushi-Gott bezeichnet, aber ich glaub das war leicht übertrieben, weil andere das auch schon machen. Was wahrscheinlich noch nicht so viele gemacht haben ist Sushi mit geräucherter Bratwurst die in Scheiben geschnitten ins Sushi kommt. Das ist echt ziemlich gut. Hervorragend eignen sich auch Karotten mit Erdnussbutter. Gebratene Banane ist auch recht lecker.

Noch so ein Tipp zum Wasabi: Zum Würzen der fertigen Sushi-Stücke kommt noch ein Schälchen Soja-Soße und Wasabi auf den Tisch. Ich kaufe meistens Wasabi-Paste. Weil die aber doch recht zäh und konzentriert ist, und nicht jeder so sehr auf den Schmerz von Wasabi steht wie ich, mische ich den Wasabi noch mit Reisessig zu einer dünneren Soße, damit es sich leichter eintunken lässt.

Insider: Übrigens dürfen sich alle auf der Silvesterparty in Berlin auf Sushi, zubereitet von mir freuen.

Posted So 30 Dez 2012 02:10:07 CET Tags:

Ich komme aus dem schreiben garnicht mehr raus. Aber mir kam auch noch der Gedanke, dass ich ja mal schreiben könnte, was ich dieses Semester so an Veranstaltungen in der Uni höre. Vielleicht regt es ja jemanden dazu an sich für die ein oder andere Richtung zu interessieren.

Echtzeitsysteme

Natürlich musste ich auch dieses Semester etwas von meinem Lehrstuhl, also dem Ort an dem ich neben der Fachschaft die meiste Zeit in der Uni verbringe. Gemeint ist hierbei natürlich der Lehrstuhl 4 - Verteilte Systeme und Betriebssysteme, wo ich momentan mit am DanceOS Projekt arbeite.

Aber zu Echtzeitsysteme: Hier wird, vornehmlich aus der Anwendersicht eines Echtzeitbetriebssystems, gezeigt, welche Mechanismen und Vorangehensweisen man vollführt um sicherzustellen, dass eine gewisse Aufgabe bis zu einem gewissen Zeitpunkt ausgeführt worden ist. Das ist ja mein "normalen" Betriebssysteme ja eher nicht gegeben, weil die Schedulen einen Task halt dann, wenn es gerade am besten ins Konzept passt und wenn der Task dann seine Deadline reisst hat er halt Pech gehabt. Wie gesagt geht es in der Veranstaltung eher um das Anwenden eines Echtzeitbetriebssystems, und nicht um den Bau eines solchen.

Diese Rechtzeitigkeit braucht man vor allem bei der Steuerung von technischen Anlagen (Autos, Industrieanlagen, Fertigung). Aber das ganze ist leider auch Militärtechnik, und da kommt auch viel Geld in dem Bereich her. Also zweischneidiges Schwert, aber richtig interessantes Themengebiet.

Übersetzerbau 1

Das ist eine mit der coolsten Informatikveranstaltungen, die ich bisher in meinem Studium gehört habe. Und wie der Name schon sagt, es geht darum zu verstehen, was ein Compiler tut und in den Übungen wird auch selbst ein Compiler für eine kleine Kunstsprache gebaut.

Zum einen wird in der Vorlesung erst einmal der ganze Kanon von der lexikalischen Analyse, Parsen, Typprüfung, Zwischencodeerzeugung, Registervergabe und Maschienencoderezeugung vorgesungen (und das in der echt guten Vortragsweise von Herrn Phillipsen).

Zum anderen wird in der Übung ein Compiler für die sehr vereinfachte und an C angelehnte Sprache "E" in Java gebaut. E hat Funktionen, Kontrollstrukturen, die Typen int und real sowie Arrays. Was das ganze besonders lustig macht: Man arbeitet ständig mit dem weiter, was man in der letzten Aufgabe gemacht hat. Es gibt also nicht ständig eine neue Vorgabe, wo man kurz das template einfüllt, sondern man immer weiter mit seinem eigenen Mist arbeiten muss.

Diese Vorlesung ist auch daran Schuld, dass ich meinen ersten Weihnachtsfeiertag damit verbracht habe unserem Compiler (den wir in Zweiergruppen bauen) beizubringen floating-point Arithmetik mit SSE Befehlen auf X86 beizubringen, sowie eine bessere Registervergabe zu bauen, als wie die einfache die in der Aufgabe vorgesehen war. Hier ist auf jeden Fall viel Bastel- und Reinnerdpotential da.

Auf jedenfall eine Hörempfehlung für jeden Informatiker in Erlangen.

Advanced Programming Techniques

Ja, C++ 2011 für Einsteiger. Eigentlich ist die Veranstaltung ja für Computional Enigeers gedacht, aber wir dürfen das auch hören. Ist jetzt nicht so da ultra dicke Brett, aber man lernt noch ein paar Feinheiten über C++. Gut man muss vielleicht auch dazu sagen, dass ich seit Jahren C++ programmiere, könnte vielleicht auch daran liegen, dass ich nicht brennend vor Begeisterung bin.

Grundkurs Theoretische Philosophie

Nachdem ich im Master Philosophie als Nebenfach mache, weil man muss ja auch mal was nicht-technisches Machen, und nicht nur irgendwelche naturwissenschaftlichen Nebenfächer, muss ich auch diesen Kurs belegen. Um es kurz zusammen zu fassen: Es gibt Anwesenheitspflicht, die Tatsache dass Philosophie-Erstsemester noch keine Logik hatten ist schlimm, und man muss bis auf Sitzen nicht viel für seinen Schein machen. Größerer Erkenntnisgewinn, außer mal nen groben Überblick über die Felder der Philosophie zu bekommen, springt dabei nicht raus. Dafür hat man die Freunde wundervolle Diskussionen von Studenten, die ihre Begriffssemantik nicht klargezogen bekommen, zu genießen.

Handlungen und Wertungen

Bei dieser Vorlesung geht es um die Theorie, wie Handlungen innerhalb des Verstandes motiviert werden, was die Bedingungen sind, dass es zu einem handlungswirksamen Wunsch kommt. Und was ich bisher am spannendsten fand: Was ist Willensfreiheit (nach Frankfurt)?

Am Anfang hatte ich etwas den Eindruck, dass das ganze ne lasche Veranstaltung wird, nachdem der Dozent die Angewohnheit hat jede, und ich betone jede, seiner Aussagen irgendwie zu relativieren, also fast jede. Und das ist genau so, oder vielleicht auch nicht. Aber inzwischen gefällt mir die Vorlesung recht gut. Bald ist Prüfung. Man wird sehen, was daraus wird.

Grundlagen der Erkenntnistheorie

Das ist sicherlich die beste Vorlesung die ich in Philosophie momentan habe. Der Vortragsstil von Professor Ernst ist einfach ziemlich gut. Aber zum Inhalt, was ist Erkenntnistheorie?

Zunächsteinmal kommt die skeptische Frage, die wir uns manchmal alle Stellen (vor allem nachdem man Matrix gesehen hat): Was können wir überhaupt wissen? Und wer sagt nicht, dass alles was wir meinen zu sehen uns nur von einem Dämonen eingesagt wird, und die Welt in Wirklichkeit ganz anders aussieht. Das ist jetzt an sich eine nicht so fruchtbare Frage, aber man kommt damit auch auf so Fragestellungen: Was sind die notwendigen und hinreichenden Bedingungen für Wissen (gerechtfertigte wahre Überzeugung ist ein guter Anfang)?

Mal sehen wie dabei die Prüfung wird. Aber sicher auch nicht so arg schwer, weil Gruppenprüfung und unbenotet und eh wenig ECTS.

Posted Sa 29 Dez 2012 15:02:38 CET Tags:

Nun gibt es seit längerer Zeit wieder mal einen Blogpost von mir. Nachdem ich seit nunmehr 3 Monaten in einer WG wohne, nachdem ich Ende August aus meiner alten Wohnheimswohnung ausziehen musste und ich 2 Monate etwas entwurzelt war, dachte ich mir ich schreib mal was dazu.

Damit es aber nicht was total nutzloses wird, womit keiner was anfangen kann und ich nur meine persönlichen Dinge auskotze, dachte ich mir ich beschreibe mal das WG-Abrechnungssystem, dass wir bei uns implementiert haben. Das ganze kommt der Idee nach hauptsächlich vom Daniel Lohmann. Gut die grundlegende Idee ist die folgende: Jeder hat ein virtuelles Konto, auf dass er durch das einkaufen von Gemeinschaftsgütern Geld einzahlt. Gemeinschaftsgüter sind bei uns so ziemlich alles was essen angeht. Mit den gesammelten Ausgaben werden am Ende des Monats die Beträge ausgeglichen.

Nun wäre es jedoch unfair das ganze einfach durch die Anzahl der Personen zu teilen, weil Menschen unterschiedlich häufig da sind. Deswegen trägt jeder am Ende des Monats die Anzahl der Tage ein, die er da gewesen ist. Aus diesen Anwesenheitstagen und den Gesamtausgaben kann man dann einen Tagessatz berechnen, mit dem dann die Ausgleichszahlungen getätigt werden. Über diese Anwesenheitstage kann man es dann auch abfackeln, wenn Leute ständig bei einem in der Wohnung rumhängen und mit essen. Ich habe bisher den Eindruck, dass das ganze bei uns recht gut funktioniert und die Vorteile eines gemeinsamen Einkaufs sind einfach ziemlich gross (Vor allem weil immer Dosenmais und Tomatenzeugs da ist), wenn es denn funktioniert.

Da ich mich bei uns um diese Abrechnung kümmere hab ich das ganze natürlich getooled. In Emacs org-mode :-)

Die Abrechnung sieht dann am Ende so aus:

| Alle        |   192.85 | Tagessatz |      2.50 |           |           |
|             | Ausgaben | gemeinsam | eingehend | ausgehend | ausgleich |
| NAME 1      |    33.36 |    -37.57 |      0.00 |    -48.25 |    -52.46 |
| NAME 2      |    12.60 |    -37.57 |     89.12 |   -118.45 |    -54.30 |
| NAME 3      |    29.83 |    -47.59 |    199.93 |    -25.05 |    157.12 |
| NAME 4      |   117.06 |    -45.08 |     35.26 |   -132.56 |    -25.32 |
| NAME 5      |     0.00 |    -25.05 |      0.00 |      0.00 |    -25.05 |

Diese Auflistung wird dann aus der Liste der Ausgaben automatisch generiert. Und das System hat auch eine praktische Intra-WG-Überweisungsfunktion. Den Source-Code dafür gibts auch

Posted Sa 29 Dez 2012 00:35:57 CET Tags:

Last week I attended a practical course in astronomy at the Dr. Remeis Astronomical Institute in Bamberg. The course took nearly two weeks, where the groups had to do some experiments and write protocols afterwards. It was not only work, but we also took a few great pictues.

Booth pictures were shot with an 40cm Schmidt-Cassegrain telescope. The first one ist the M101 (also called Pinwheel Galaxy). It was taken with an raw CCD camera with 11 Megapixel. We've done 4 pictures (Luminance, Red, Green, Blue) in total (plus some calibration pictures), which took nearly 2 hours. The ready assembled picture is really good (be aware that you cannot see M101 with your bare eye, because it is too dark). The second one was done with the EOS Camera of a friend (rupran) and shows (surprise) the moon.

UPDATE: I've also found through wikipedia, some Hubble Images of M101

Posted Mi 04 Apr 2012 20:36:42 CEST Tags:

This blog is powered by ikiwiki