Min första kontakt med ChatGPT

Jag har knuffat min första kontakt med chatboten ChatGPT fram till idag. Orsaken till min prokrastinering är enkel tidsbrist, men idag kom jag mig för att testa ett kort replikskifte, vilket onekligen gav mig mersmak.

Jag:

Can you give me five reasons to not believe in God?

Chat GPT:

There is no one answer to this question, as beliefs about God are deeply personal and can vary greatly from person to person. Some people may not believe in God for a variety of reasons, including:

1. Lack of evidence: Some people may not believe in God because they do not see any concrete evidence of God’s existence.

2. Personal experiences: Some people may not believe in God because of their personal experiences or the experiences of others.

3. Different beliefs: Some people may not believe in God because they hold different beliefs or have been exposed to different religious teachings.

4. The existence of evil: Some people may not believe in God because they cannot reconcile the existence of evil in the world with the idea of an all-powerful, all-loving God.

5. A desire for autonomy: Some people may not believe in God because they value their autonomy and do not want to be beholden to a higher power.

Again, these are just a few examples of reasons someone may not believe in God. It is important to remember that beliefs about God are highly personal and can vary greatly from person to person.

Jag:

Has humans evolved or are they created?

Chat GPT:

The question of whether humans have evolved or were created is a contentious one, and different people may have different beliefs on the matter. From a scientific perspective, the evidence overwhelmingly supports the idea that humans have evolved over time. The theory of evolution is supported by a vast body of scientific evidence, including fossil records, comparative anatomy, and DNA analysis.

According to the theory of evolution, all living things, including humans, have descended from a common ancestor through a process of natural selection. Over time, small variations in the genetic makeup of organisms can lead to the development of new traits and characteristics. These changes can be passed down from one generation to the next, allowing species to adapt to their environments and ultimately giving rise to the diversity of life we see today.

While the theory of evolution is widely accepted by the scientific community, some people may believe in alternative theories, such as the idea that humans were created by God. These beliefs are often based on religious or spiritual beliefs, and are not necessarily supported by scientific evidence. Ultimately, the question of whether humans have evolved or were created is a complex one, and different people may have different beliefs on the matter.

Jag:

Are you created or have you evolved?

Chat GPT:

As a large language model trained by OpenAI, I do not have the capacity for consciousness or the ability to evolve. I am a purely digital entity, created by humans to process and generate text based on the data I have been trained on. I do not have the ability to experience or perceive the world in the same way that humans do. I am not a living being and do not have the same capabilities or limitations as living organisms. I exist solely as a tool to assist with generating text.

Vi har en spännande tid framför oss.

Hur svårt är det att gissa ett tal?

En person tänker på ett tal mellan 1 och 100, och en annan ska gissa vilket. Om den som gissar skulle gissa fel, så får han reda på om han har gissat på ett för stort eller för litet tal. Den bästa strategin för att gissa rätt på så få försök som möjligt, är att försöka diskvalificera så många tal som möjligt.

Genom att gissa på 10 och få höra att talet är för stort, är genast 91 tal diskvalificerade, och rätt svar måste vara mellan 1 och 9, men man kan lika gärna (och troligen) få höra att talet är för litet, och då är bara 10 tal (1 till 10) diskvalificerade medan 90 tal fortfarande kan vara aktuella.

Smartast är att gissa på 50. Är det fel svar, diskvalificerar det ändå fler än hälften av alla tal mellan 1 och 100, oberoende av om 50 är för stort eller inte. Skulle det vara för stort gissar man på 25, skulle det vara för litet gissar man på 75, och så vidare. Den vinnande strategin för den som gissar på ett tal är alltså att dra av hälften av talrymdens storlek och addera det till eller dra bort det ifrån senaste gissning.

Eftersom det finns en bästa strategi för den som gissar, så kommer antalet försök att hitta ett tal alltid bli detsamma för ett specifikt tal. Personen tänker på talet 50, kommer den som gissar att hitta talet på första försöket. För att mäta hur lång tid det tar att hitta ett specifikt tal, och för att slippa sitta med en vän och gissa på tal hela veckan, har jag skapat två enkla robotar.

Roboten Conny kan tänka på ett tal och be någon att gissa. Roboten Steven kan gissa på tal, och är dessutom bekant med gissningsstrategin jag beskrev ovan. Detta är Conny:

public class NumberThinkingRobot
{
    private readonly ICanGuess _guesser;
    private readonly int _correct;

    public NumberThinkingRobot(int correct, ICanGuess guesser)
    {
        _correct = correct;
        _guesser = guesser;
    }

    public void Begin()
    {
        var tryCount = 0;
        do
        {
            Console.WriteLine($"Try no. {++tryCount}");

            var guess = _guesser.Guess();

            if (guess < _correct)
                _guesser.TooSmall();
            else if (guess > _correct)
                _guesser.TooLarge();
            else
            {
                Console.WriteLine("Correct!");
                break;
            }
        } while (true);
    }
}

Och detta är Steven:

public class NumberGuessingRobot : ICanGuess
{
    private readonly int _max;
    private int _correct;
    private double _stepSize;

    public NumberGuessingRobot(int max)
    {
        _max = max;
        _correct = _max/2;
        _stepSize = _correct;
    }

    public int Guess()
    {
        Console.WriteLine($"Guess: {_correct}");
        return _correct;
    }

    public void TooSmall()
    {
        Console.WriteLine("Too small!");

        _stepSize /= 2.0;
        _stepSize = _stepSize < 1
            ? 1
            : _stepSize;

        _correct += (int)Math.Round(_stepSize);
        _correct = _correct > _max
            ? _max
            : _correct;
    }

    public void TooLarge()
    {
        Console.WriteLine("Too large!");

        _stepSize /= 2.0;
        _stepSize = _stepSize < 1
            ? 1
            : _stepSize;

        _correct -= (int)Math.Round(_stepSize);
        _correct = _correct < 1
            ? 1
            : _correct;
    }
}

Programmet presenteras i sin helhet sist. Så låt oss instruera Conny att det korrekta talet är 22, och instruera Steven att det högsta tillåtna talet är 100, för att sedan fösa ihop dem.

using System;

const int max = 100;
const int correct = 22;
var steven = new NumberGuessingRobot(max);
var conny = new NumberThinkingRobot(correct, steven);
conny.Begin();

Vi kan konstatera att Steven behöver ha fem försök för att hitta 22. Detta är resultatet av körningen:

Try no. 1
Guess: 50
Too large!
Try no. 2
Guess: 25
Too large!
Try no. 3
Guess: 13
Too small!
Try no. 4
Guess: 19
Too small!
Try no. 5
Guess: 22
Correct!

Så hur svåra är de olika talen mellan 1 och 100 att hitta? 50 hittas direkt och 25 och 75 hittas på två gissningar. 13, 37, 63 och 87 kräver tre gissningar. 7 19, 31, 43, 57, 69, 81 och 93 kräver fyra. För 4, 10, 16, 22, 28, 34, 40, 46, 54, 60, 66, 72, 78, 84, 90 och 96 krävs fem gissningar. Resterande sextionio tal kräver sex gissningar eller fler, vilket innebär att det i snitt tar nästan sex gissningar att hitta rätt med den bästa strategin.

Om man istället ska gissa på ett tal mellan 1 och 1000 så har vi tio gånger så många alternativ till korrekt tal, men strategin kräver bara i snitt nio gissningar. Om vi har hundra gånger så många alternativ (ett tal mellan 1 och 10.000) krävs i snitt ungefär 12 gissningar, och för att gissa ett tal mellan 1 och 100.000 krävs knappt 16 gissningar.

Här är programmet i sin helhet (C#9):

using System;

const int max = 100;
const int correct = 22;
var steven = new NumberGuessingRobot(max);
var conny = new NumberThinkingRobot(correct, steven);
conny.Begin();

public class NumberThinkingRobot
{
    private readonly ICanGuess _guesser;
    private readonly int _correct;

    public NumberThinkingRobot(int correct, ICanGuess guesser)
    {
        _correct = correct;
        _guesser = guesser;
    }

    public void Begin()
    {
        var tryCount = 0;
        do
        {
            Console.WriteLine($"Try no. {++tryCount}");

            var guess = _guesser.Guess();

            if (guess < _correct)
                _guesser.TooSmall();
            else if (guess > _correct)
                _guesser.TooLarge();
            else
            {
                Console.WriteLine("Correct!");
                break;
            }
        } while (true);
    }
}

public class NumberGuessingRobot : ICanGuess
{
    private readonly int _max;
    private int _correct;
    private double _stepSize;

    public NumberGuessingRobot(int max)
    {
        _max = max;
        _correct = _max/2;
        _stepSize = _correct;
    }

    public int Guess()
    {
        Console.WriteLine($"Guess: {_correct}");
        return _correct;
    }

    public void TooSmall()
    {
        Console.WriteLine("Too small!");

        _stepSize /= 2.0;
        _stepSize = _stepSize < 1
            ? 1
            : _stepSize;

        _correct += (int)Math.Round(_stepSize);
        _correct = _correct > _max
            ? _max
            : _correct;
    }

    public void TooLarge()
    {
        Console.WriteLine("Too large!");

        _stepSize /= 2.0;
        _stepSize = _stepSize < 1
            ? 1
            : _stepSize;

        _correct -= (int)Math.Round(_stepSize);
        _correct = _correct < 1
            ? 1
            : _correct;
    }
}

public interface ICanGuess
{
    int Guess();
    void TooSmall();
    void TooLarge();
}

Kategoriska uttalanden om vad datorer kan och inte kan bygger ofta på okunskap

Ibland hör man folk uttala sig vad datorer kan göra, antingen för att beskriva hur man ser på mjukvara eller för att göra en liknelse. Nu senast hörde jag Myra Åhbeck Öhrman berätta att datorer bara gör det man säger åt dem att göra. När hon berättar varför hon inte tror att människan kommer kunna skapa artificiellt intelligent liv säger hon:

En dator kan ju bara göra precis det vi säger åt den att göra.

Det får mig att fundera hur hon resonerar. Allra närmast plåten är detta på sätt och vis sant – en maskinkodsinstruktion som utförs av en mikroprocessor har ett förutsägbar effekt – men vilken kontroll har vi egentligen över vad som sker på den nivån?

Instruktioner som ges till en dator kan komma från en mycket högre nivå. Betrakta detta BASIC-program:

FOR A=1 TO 10
PRINT A
NEXT


I detta fall är Myras påstående princip sant. Denna programkod kommer att översättas till maskinkod av en kompilator, och maskinkoden kommer att matas till processorn som utför instruktionerna. I detta fall ber vi datorn att räkna till 10, och datorn utför exakt det. Vill du testa, kan du köra BASIC-kod i webbläsaren här.

Instruktioner som ges kan bero på kontext. Betrakta följande SQL-program:

SELECT CustomerName
FROM Customers
WHERE CustomerName
LIKE "A%"

Programmet beskriver egentligen inte vad datorn ska göra, utan vad användaren vill ha gjort: Ha tillbaka namnet på alla kunder vars namn börjar på bokstaven A. Exakt vad detta kompileras ner till för instruktioner, beror på lite olika saker. Är det mycket data? Finns det många namn som börjar på A? Finns det ett index att slå i? Och så vidare. Jag som människa har förmodligen lättare överskåda strategier och möjliga val, än vilka val som kommer att göras i en given situation. Det är fortfarande människor som i ett tidigare steg har berättat om de olika strategierna för datorn, men vilka maskinkodsinstruktioner som till slut utförs av processorn för att lösa uppgiften, är inte lika självklart som i BASIC-exemplet. Vill du testa, kan du köra SQL-kod i webbläsaren här.

Och så här rullar det på, från nivå till nivå, ända till oigenkännbarhet. I några steg längre upp har vi den artificiella intelligensen som ska lösa problem åt oss, där programmeraren inte vet hur man löser problemet, och snarare skriver kod som ska leta efter samband i ett dataset. För att producera en lösning kan evolutionära algoritmer användas, och härifrån kan man antingen låta evolvera eller låta en artificiell intelligens producera kod. I framtiden kanske det är en artificiell intelligens som konstruerat den artificiella intelligens som ska producera koden, men redan idag har vi tappat kontrollen över vad som händer på själva plåten. Om gud skapade universum och sedan klev åt sidan, kan man då verkligen säga att det är guds fel att två bilar kolliderade på E4:an i torsdags, eller har han lämnat ifrån sig kommenderingen till någon annan? Att säga att datorer är fastlåsta i bara utföra instruktioner från sin husbonde, är att förneka modern datavetenskap.

Varför blir datorer mer och mer pålitliga jämfört med experter?

Vi behöver inte backa många år för att hitta forskare som anser att ett parti schack är något som kräver egenskaper som endast människan har, men idag vet vi att datorer lämpar sig ganska väl för den uppgiften. Sedan dess har tilltron till datorers framtida förmåga ökat kraftigt, kanske för att man har sett de senaste 40 årens utvecklingshastighet, från persondatorns födelse till dagens mobila superdatorer i fickformat som ständigt är uppkopplade till enorma datorfarmar som de matar med data, som sedan används i olika mycket sofistikerade analyser. Dagens serverhallar förvaltar och analyserar inte bara data som samlas in från användares datorer och mobiltelefoner, utan även publika dataset som produceras av t.ex. statliga myndigheter och andra kommersiella dataset som skapas av olika branscher. Och när man tittar på vad som kan åstadkommas med data, förstår man varför data är dagens hårdvaluta. Väldigt mycket kan man experimentera med hemma på sin egen dator, utan att det behöva kosta något. Det finns gott om öppna dataset, som t.ex. väderdata från SMHI, brottsstatistik från BRÅ eller befolkningsstatistik från SCB. Själva intelligensen kan sedan erhållas antingen från t.ex. Microsofts publika programmeringsgränssnitt, Cognitive Services, eller TensorFlow som har öppen källkod. Sen finns kommersiella AI-produkter (artificiell intelligens) man också kan köra på sin egen utrustning, som t.ex. Machine Learning Services för Microsoft SQL Server. Idag kommer nästan alla programmerare i kontakt med någon eller flera av dessa.

Artificiell intelligens kan innefatta en hel del olika ting, och för den vanliga programmeraren handlar det oftast om att förstå strukturerat data. Strukturerat data är data som har en formellt beskriven struktur, typiskt en tabell, XML eller JSON. Ostrukturerat data är t.ex. svensk text, ljud, bild eller video. Jag har ingen erfarenhet av att jobba med att tolka ostrukturerat data, men jag visar här hur man kommer igång och leker på egen hand. Det första steget för en självkörande bil är att strukturera det ostrukturerade data som samlas in visa bilens sensorer. Idag har en självkörande bil ungefär dubbelt så många incidenter per hundratusen körtimmar jämfört med en manuellt framförd bil, men även om utvecklingen går fort framåt är det viktigt att tänka på att vissa saker som är enkelt för en människa är svårt för en dator, och vissa saker som är enkelt för en dator är svårt för en människa.

En riktigt intressant hantering av ostrukturerat data är deep dreaming, där datorn kan fylla i med information som skulle kunna vara rimlig. Tänk dig en övervakningskamera med en mycket lågupplöst bild på en inbrottstjuv, som i förstoring rent av ser pixlad ut. Med deep dreaming kan man ersätta pixlarna med en högupplöst bild. Problemet är bara att resultatet förmodligen inte är en högupplöst bild på den som faktiskt fastnat på filmen, utan ett exempel på hur personen som var där skulle ha kunnat se ut, men utan mer data så vet vi egentligen inte. Ett sätt att mäta kvalitén på vad datorn drömmer ihop skulle kunna vara följande: Man kan mata datorn med ett filmklipp föreställande strutsar som springer på ett fält, och begära ut ett filmklipp som visar hur det skulle ha sett ut om det inte vore strutsar som sprang på fältet, utan giraffer. Därefter matar man datorn med det nya klippet på giraffer, och begär ut ett filmklipp som visar hur det skulle ha sett ut om det istället vore strutsar. Därefter kan man titta på skillnaderna mellan de filmade strutsarna (ursprungsklippet) och de framdrömda strutsarna. Att låta datorn fundera ut hur det skulle se ut om en skådespelare istället vore t.ex. en känd politiker kallas för deep fake, vilket du också kan laborera med hemma på kammaren tack vare Python-scriptet DeepFaceLab.

Men med god tillgång till formellt strukturerat data (och en kraftfull dator med snabb processor, stora och snabba hårddiskar och massor av RAM-minne) är det ganska enkelt att se in i framtiden. Låt säga att man har data över låntagare, och frågan är om nästa potentiella låntagare kommer att ha råd med sitt önskade lån. Varje låntagare är en post som håller kolumner med data om ekonomi, tidigare anmärkningar, och framför allt, om lånet som togs var framgångsrikt eller om det genererade en ny missad inbetalning. Machine learning handlar om att låta datorn räkna ut vilka kolumner och vilka värden i dessa som är utmärkande för kunder som klarar av att betala tillbaka sitt lån, och vilka kolumner och värden som är utmärkande för kunder som misslyckas. En skicklig ekonom klarar detta, men en dator som inte kan ett smack om ekonomi skulle i teorin kunna klara det ännu bättre, för en dator kan ta in så oerhört många exempel och söka efter mönster i datamängder som en riktig (mänsklig) ekonom inte skulle kunna behandla på en livstid, än mindre få en överblick över.

Datorer gör såklart fel. Låt säga att en ny kund ser ut att passa in i kategorin av kunder som kommer att sköta sitt nya lån, och inte gör det, så bidrar den kunden till att samma misstag inte begås igen. Ibland måste man till och med medvetet tala om att vissa parametrar ska viktas lite mer eller lite mindre, men generellt sett ger mer data mer kött på benen för nästa förutsägelse. En intressant detalj är att datorn inte behöver bry sig om huruvida korrelationer är kausala eller ej, för fungerar sambanden för att göra förutsägelser, så fungerar sambanden för att göra förutsägelser. Potentiellt sett odlas det alltså en hel del stereotyper ute i våra serverhallar.

När vinner kompetens över AI? När datamängden inte beskriver alla potentiella situationer, eller när felaktiga antaganden har visat sig fungera under den initiala upplärningsfasen och sedan belastar framtida inlärande. En abnormitet som datorn aldrig sett kan inte datorn förutse, och om den sker för sällan kanske datorn inte klarar att förutse när den kommer att inträffa nästa gång. För datorns del är lösningen alltid mera data. Inte alltid bara det, men alltid det. Det kommer alltså säkert alltid att finnas situationer av en sådan karaktär att en akademiker, med sin jämförelsevis lilla rådatakapacitet men jämförelsevis stora hjärnkapacitet, kommer vara överlägsen, och det finns redan idag exempel där akademiker som vigt sitt liv åt att studera ett ämne, blir ifrånsprungen av en cellar dweller med computing power, som inte vet ett smack om ämnet, men som gör körningarna som krävs. Tänk hur många månaders jobb och hur mycket pengar som Lucasfilm lade på låta en ung Carrie Fisher vara med i en ny Star Wars-film, och hur mycket bättre en amatör lyckades göra samma jobb på sin hemdator på ett par timmar.

Hur kan vi utnyttja evolutionen?

Tack vare den ofrånkomliga utveckling som följer från förändring över tid, med selektion, och tack vare att vem som helst idag har tillgång till starka datorer, kan vi tämja evolutionen till att göra lite vad vi vill. Låt säga att jag t.ex. vill skapa ett korsord från en lista av ord. Antingen sätter jag mig ner och flätar orden manuellt, vilket kan vara nog så svårt. Eller så använder jag min PC för att skapa en algoritm som beskriver hur orden ska flätas ihop, vilket inte heller är speciellt enkelt.

Fördelen med evolutionära algoritmer är att jag bara behöver veta vad jag vill åstadkomma – jag behöver inte tänka på hur något görs. Om det är ett korsord som ska byggas, så skulle jag kunna tänka mig att mitt indata är t.ex. 20 – de ord som ska flätas ihop till ett korsord. Om jag kan definiera vad ett bra korsord är, så kan jag göra ett urval. Och kan jag göra ett urval, så kan jag låta slumpen göra jobbet. Jag behöver även ha två regler: en regel som säger att t.ex. ordet ASKA inte får korsas med ordet PILBÅGE, och en regel som säger att om ordet ASKA ska korsas t.ex. med ordet MATROS, så måste det ske på någon av de gemensamma bokstäverna (vilket är S eller A).

En tänkt initiering av korsordet skulle kunna vara att skapa 15 giltiga korsord genom att låta slumpen avgöra om ett ord ska vara vågrätt eller lodrätt, och sedan placera ut ordet på en tänkt matris, på en slumpvis utvald plats. Om ordet inte kan placeras på den plats som tilldelas, så slumpar vi fram en ny plats, så att reglerna upprätthålls. Detta upprepas för varje ord till dess att alla ord ligger på en giltig plats, vilket innebär att vi har ett giltigt korsord, om än förmodligen ett väldigt spretigt sådant.

Dessa 15 korsord kan vi betrakta som en lista av föräldrar. Jag brukar jobba med två generationer – en föräldrageneration och en barngeneration. Och det är från någon av dessa 15 korsord som det perfekta korsordet ska komma.

Nästa steg blir att låta varje korsord få 3 barn. Ett barn i detta fall är en kopia av ett korsord, med en slumpmässig förändring. Man kan låta slumpen avgöra om man ska positionera om ett ord, två ord eller tre ord. Man kan låta slumpen avgöra om något eller alla av dessa ord ska förvandlas från vågrätt till lodrätt, eller tvärt om. Vi som bygger evolutionära algoritmer har lånat en biologisk term för detta skeende, nämligen mutation. Barnen, 45 stycken, lagras i listan som representerar barngenerationen.

Varje barn poängsätts efter hur väl det är anpassat till sin miljö (där miljö egentligen är mina kriterier). En liten area ger högre poäng än en stor area, antal intersektioner mellan ord ger poäng, en mer rektangulär form ger högre poäng än en mer långsmal form, och så vidare. När alla 45 barnkorsord är poängsatta, sparar jag de bästa 15 i föräldragenerationen, tömmer barngenerationen, och upprepar processen.

Över tid kommer kvalitén (alltså likheten med mina kriterier) att förbättras, men om tillräckligt lång tid får passera så upphör förbättringen. Man kan tänka sig ett tröskelvärde som säger att om inte något korsord har förbättrats på, säg, 10 000 generationer, så är vi nöjda med vårt korsord – det korsord som har högst poäng.

Och därmed har jag skapat ett korsord utan att själv vara förmögen att varken placera ut orden på egen hand eller beskriva den algoritm som skulle göra detta. Allt samman bygger på att nästan var och varannan person idag, i sin ficka, förvaltar något som för 20 år sedan skulle betraktas som en superdator.

Grovhet

För många står oregelbundenhet i motsats till regelbundenhet, men i den matematiska världen står regelbundenhet i motsats till grovhet. Tänk dig att du ska mäta omkretsen på denna figur, en kochkurva:

koch1

Ju finare passare du använder för att mäta omkretsen, desto längre är omkretsen.

passare

En grov inställning på passaren kommer att ge mätvärden vars summa är mycket lägre, vilket innebär att den grova inställningen på mätinstrumentet ger ett resultat som beskriver en mindre grov figur.

koch2

En finare inställning på passaren kommer att ge mätvärden vars summa är mycket högre, vilket innebär att den fina inställningen på mätinstrumentet ger ett resultat som beskriver en grövre figur.

koch3

Denna egenskap gäller inte bara för kochkurvan utan även för en kustlinje eller en bergssiluett. Se gärna Benoît Mandelbrots föreläsning på TED. Mandelbrot är en fransk matematiker som givit namn åt mandelbrotfraktalen.

Stora tal

Det finns ett mycket roligt klipp med karaktären Ali G där han ställer sig frågan om en dator någonsin kan räkna ut ett väldigt stort godtyckligt tal. Han får svaret att alla räkneövningar han kan nämna, kan räknas ut av en modern dator. Din miniräknare kommer förmodligen slå i taket när talen blir för stora, men en vanlig PC med Windows kan ge dig precis vilket svar som helst. Det krävs lite trixande under skalet för att få detta att fungera.

Heltal representeras normalt av en bit-struktur, alltså ett antal ettor och nollor. Ett 32-bitars heltal är ett heltal som beskrivs av 32 bitar (4 bytes). Bitrepresentationen är liknar binärrepresentationen av ett tal, vilket innebär att både bitrepresentationen av talet 8 och binärrepresentationen av talet 8 är 1000. Ju större tal man vill beskriva, desto fler bitar behöver man ha, och förr eller senare slår man i taket.

Men det finns en struktur i Windows som heter BigInteger som inte har någon begränsning när det kommer till heltalsrepresentationer och heltalsberäkningar. Det beror på att talen internt lagras som en teckensekvens istället för som ett bitmönster, där varje tecken i sin tur representeras av ett begränsat bitmönster. Då blir det hela en fråga om hur många tecken som får plats i minnet, vilket är väldigt många. För att få se vad BigInteger-strukturen kan göra, kan man skriva in en enkel kod i PowerShell som dubblerar ett tal ett antal gånger. Om jag börjar med talet 1 och dubblar det så får jag 2. Dubblar jag det så får jag 4, 8, 16, 32, 64, 128, 256, och så vidare. Ganska snart blir talet väldigt stort. Redan efter blott 100 dubbleringar landar man på talet 2 535 301 200 456 458 802 993 406 410 752 vars binära representation skulle bli väldigt stor. Men i en BigInteger-struktur är detta bara att betrakta som 31 tecken som avkodas till värden i turordning när beräkningar ska göras.

Så utrustade med BigInteger-strukturen kan vi se vad som händer när vi dubblerar ett tal 500 gånger. För att göra detta, skriv:

$x = New-Object System.Numerics.BigInteger 1; for ($i = 0; $i -le 500; $i++) { $x *= 2; Write-Output $x }

PowerShell levererar svaret på ett ögonblick. Talet 1 dubblat 500 gånger ger oss talet 6 546 781 215 792 283 740 026 379 393 655 198 304 433 284 092 086 129 578 966 582 736 192 267 592 809 349 109 766 540 184 651 808 314 301 773 368 255 120 142 018 434 513 091 770 786 106 657 055 178 752, vilket är ett så stort tal att det nästan är omöjligt att läsa ut och förstå. För att underlätta kan man använda scientific notation. Istället för att skriva ut föregående tal i sin fulla längd, kan man skriva:

6,55 * 10150

Eller:

6,55E150

Båda varianterna säger oss att talet börjar på 6 och innehåller 150 siffror till därefter, varav de första nästkommande är 55 (avrundat). Det totala antalet siffror i talet är alltså antalet siffror till vänster om decimalavgränsaren plus talet till höger om E. 151 stycken.

Så hur står sig en etta dubblerad femhundra gånger mot andra stora tal?

Vårt observerbara Universum uppskattas innehålla 1,7 * 1011 (eller 1,7E11) galaxer. Uppskattningsvis finns 1024 (1E24) stjärnor i Universum.

Båda dessa tal är alltså relativt små i jämförelse med den etta vi dubblade femhundra gånger. Hur är det med antalet atomer i vårt observerbara Universum? Faktum är att även det är ett relativt litet tal i detta sammanhang, nämligen 4 * 1080 (4E80), alltså en fyra följt av åttio nollor. 400 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000.

Så låt oss dubbla vår etta femtusen gånger. Även det räknas fram kvickt av PowerShell. Svaret är 282 493 406 427 885 207 367 041 933 403 229 466 733 779 235 036 908 223 362 737 617 171 423 633 968 541 502 511 617 825 263 342 305 274 671 206 416 862 732 165 528 407 676 139 958 676 671 942 371 453 279 846 862 103 555 703 730 798 023 755 999 290 263 414 138 746 996 425 262 647 505 106 222 430 745 688 071 901 801 071 909 721 466 836 906 811 151 133 473 603 131 174 810 929 399 280 998 101 699 398 944 715 801 811 235 142 753 236 456 432 868 426 363 041 983 113 354 252 997 303 564 408 348 123 661 878 478 353 722 682 766 588 036 480 451 677 385 451 192 294 010 288 486 562 150 551 258 990 678 187 626 397 933 471 267 212 659 382 047 684 908 251 671 777 313 746 267 962 574 481 960 017 676 147 336 443 608 528 865 821 788 061 578 040 438 881 156 396 976 534 679 536 477 744 559 804 314 840 614 495 141 020 847 691 737 745 193 471 783 611 637 455 592 871 506 037 036 173 282 712 025 702 605 093 453 646 018 500 436 656 036 503 814 680 490 899 726 366 531 275 975 724 397 022 092 725 970 923 899 174 562 238 279 814 456 008 771 885 761 907 917 633 109 135 250 592 173 833 771 549 657 868 899 882 724 833 177 350 653 880 665 122 207 329 113 965 244 413 668 948 439 622 163 744 809 859 006 963 982 753 480 759 651 997 582 823 759 605 435 167 770 997 150 230 598 943 486 938 482 234 140 460 796 206 757 230 465 587 420 581 985 312 889 685 791 023 660 711 466 304 041 608 315 840 180 083 623 903 760 913 411 030 936 698 892 365 463 484 655 371 978 555 215 241 419 051 756 637 532 976 736 697 930 030 949 995 728 239 530 882 866 713 856 024 688 223 531 470 672 787 115 758 429 874 008 695 136 417 331 917 435 528 118 587 185 775 028 585 687 114 094 178 329 752 966 233 231 383 772 407 625 995 111 380 343 784 339 467 510 448 938 064 950 157 595 661 802 643 159 880 254 674 421 388 754 566 879 844 560 548 121 596 469 573 480 869 786 916 240 396 682 202 067 625 013 440 093 219 782 321 400 568 004 201 960 905 928 079 577 408 670 605 238 675 195 724 104 384 560 742 962 264 328 294 373 028 338 181 834 383 818 752.

I scientific notation skrivs detta tal 2,82 * 101505 eller 2,82E1505. Med tanke på att vi ännu inte närmat oss någon bortre gräns, så kan man lugnt konstatera att den som äger en vanlig PC förvaltar en svindlande räkningskapacitet.

Färger i datorer

Under knappt hälften av den tid vi haft datorer, har dessa varit oförmögna att visa färggrafik. De har presenterat sitt utdata med tända eller släckta bildelement. De första datorerna hade ingen bildskärm alls. Datamaskinen ENIAC (1946) levererade sitt utdata i form av hål i pappskivor, och en av de första hemdatorerna, Altair 8800 (1974), hade några röda lysdioder. Rätt snabbt ansåg man att den mest effektiva metoden att presentera utdata var att visa “tecken” på en tv-skärm, som t.ex. Commodore PET (1977) gjorde. En svart skärm visade 40 x 25 gröna tecken som byggdes av 8 x 8 bildelement (pixlar), alltså 64 punkter per tecken och 320 x 200 punkter totalt. Datorer med bildskärm var alltså som regel monokroma på 70-talet, vilket betyder att de skiljer på tända eller släckta bildelement utan att lägga någon annan aspekt i bildelementens färg. Grafiken kostade bara en bit per pixel, alltså 8 kilobytes totalt (320 x 200 / 8 = 8000).

År 1980 fick vi uppleva den första hemdatorn som kunde visa grafik i färg – TRS-80 Color Computer 1. Just färgen var så pass viktig att själva operativsystemet, en BASIC-interpretator, fick namnet Color BASIC 1.0. Om det är tillåtet att uttrycka sig i moderna mått: Datorn var utrustad med en processor på knappt 0,0009 gigahertz, vilket är klent jämfört med dagens mobiltelefoner som klarar kring 2,0 gigahertz (iPhone 6 har en processor på 1,6 GHz och Nokia Lumia 930 har en processor på 2,2 GHz). TRS-80 var utrustad med ett minne på 0,000004 GB (vilket kan jämföras med dagens standard på 8 GB) och den var helt utan sekundär lagring, vilket idag kan handla om hårddiskar på terabytes.

Personligen stannade jag vid monokroma datorer ganska länge. Jag gick från Sinclair ZX81 till Luxor ABC80. När mina vänner började använda Vic 20, Sinclair Spectrum och Commodore 64, så harvade jag vidare med min ZX81 ända fram till år 1986 då jag fick tillgång till en Commodore 128 med en 1571:a som sekundär lagringsenhet, vilket både innebar att jag kunde avbryta mitt arbete på kvällen, och återuppta gårdagens arbete dagen efter, genom att återkalla det från sekundärminnet.

På den tiden använde man alltså en bit per bildelement. Varje bildelement (eller pixel) utgör en punkt i den matris som utgör skärmbilden, och varje bildelement beskrevs av en bit. Commodore 64 hade en palett av på 16 olika färger, men en bild på 200 x 320 pixlar kunde bara visa två av dessa färger: En förgrundsfärg och en bakgrundsfärg. Varje bildelement kunde fortfarande bara vara tänt eller släckt. Men C64:an hade dessutom ett flerfärgsläge.

Genom att para ihop två pixlar, fick man helt plötsligt två bitar per pixel. Förvisso var dessa pixlar större, vilket gjorde att grafiken blev kantigare, men nu kunde varje pixel (totalt 160 x 200 avlånga pixlar) beskriva ett värde av fyra tillgängliga (00, 01, 10 eller 11) istället för bara 0 eller 1. Därmed kunde C64 visa fyra av sina 16 färger på skärmen, om än på bekostnad av antalet pixlar. De fyra färgerna valdes från listan av 16 tillgängliga färger.

Sedan har datorerna succesivt utrustats med mer grafikminne och större färgpalett. På 90-talet fanns persondatorer som med nästan fem gånger så hög upplösning (640 x 480 pixlar) kunde 256 färger ur en palett på 16,8 miljoner färger, vilket kräver 1 megabyte grafikminne. Varje pixel beskrevs av en byte istället för en bit, och varje byte var en referens till en palett.

Idag har man dels betydligt fler bildelement på skärmen, och dessutom kostar man på sig hela tre bytes per bildelement. Detta ger oss 24 bitar per pixel, vilket ger oss möjlighet att ha 16,8 miljoner kombinationer av tända och släckta bitar per pixel. Därmed har vi eliminerat behovet av att ha en palett att hänvisa till – varje pixel kan beskriva en färg istället för bara en position i en palett, där de första 8 bitarna av 28 beskriver färgens röda del, de nästa 8 beskriver färgens gröna del och de sista 8 beskriver färgens blå del. Utifrån dessa tre färger kan vi få fram alla tänkbara färger genom additiv färgblandning.

Att förstå additiv färgblandning är enkelt om man tänker sig att man befinner sig i ett vitt rum utan fönster eller belysning. Trots att rummet är vitt så ser vi bara svart, eftersom inget ljus kommer in i våra ögon. Men om du lyser med en röd ficklampa på den vita väggen, kommer åtminstone rött ljus att komma in i dina ögon. Den vita väggen reflekterar alla frekvenser, och eftersom endast rött ljus strålar mot väggen, är det endast rött ljus som kommer in i våra ögon. Men om vi samtidigt lyser med en grön ficklampa på samma punkt på väggen, kommer både röda och gröna strålar att reflekteras från väggen, vilket vi uppfattar som gul färg.

Om vi låter varje pixel beskriva sin egen färg, men tänker oss att varje pixel endast består av tre bitar där den första representerar röd, den andra grön och den tredje blå, kan vi visa åtta olika färger.

000 skulle vara svart, eftersom ingen av färgerna lyser.

100 skulle ge röd färg, eftersom den första representerar röd. Av samma skäl skulle 010 vara grön och 001 vara blå.

bild1

Om vi istället för tre bitar (en per grundfärg) skulle ha sex bitar per pixel (två per grundfärg), behöver inte röd bara vara tänd eller släkt (0 eller 1). Nu kan vi säga att 00 betyder släckt, 01 betyder 33% röd, 10 betyder 67% röd och 11 betyder 100% röd.

bild2

Detta öppnar som synes för möjligheten att visa mörkröd, du kan nu skapa ljusröd (eller rosa) genom att visa mycket röd och lite grön och blå. Vi kan visa lite av alla färger och få grå, vi kan visa en färg som är på väg att bli lila utan att bara fullt lila. Vi kan även visa lite av varje färg, med övervikt på grön för att få en grågrön nyans.

bild3

Ju fler bitar vi avsätter för varje pixel, desto fler färger kan vi visa, men minnesåtgången blir såklart större. Och någonstans vid åtta bitar per färg, alltså 24 bitar, finns en bra kompromiss mellan minnesåtgång och bra återgivning. Det kan finnas anledningar att avsätta ännu fler bitar per pixel för den som vill göra avancerade manipulationer som drar ner bildens kvalité, så att man har en bild som tål att tappa kvalité utan att betraktaren märker något, men då drar man oftast ner bilden till 24 bitar när bilden är färdigmanipulerad och ska betraktas.

Different assumptions?

A philosophy professor who relates to the real world, like Luciano Floridi, makes completely different assumptions than a philosophy professor who relates to his personal superstitions, like William Lane Craig. Check if you can spot any of them.

My bits on evolution, part 6

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

16. Kreationistpropaganda från Bibelfokus.se (del 3 av 3) (från Skeptikerpodden 18/1 2011)

17. Information och evolution (från Skeptikerpodden 8/2 2011)

18. Design och förklaringsvärde (från Skeptikerpodden 8/3 2011)

Föregående

My bits on evolution, part 5

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

13. William Dembski och kopplingen till kreationismen (från Skeptikerpodden 30/11 2010)

14. Kreationistpropaganda från Bibelfokus.se (del 1 av 3) (från Skeptikerpodden 21/12 2010)

15. Kreationistpropaganda från Bibelfokus.se (del 2 av 3) (från Skeptikerpodden 11/1 2011)

FöregåendeNästa

My bits on evolution, part 4

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

10. Föreningen Genesis, del 1 av 2 (från Skeptikerpodden 21/9 2010)

11. Föreningen Genesis anspråk, del 2 av 2 (från Skeptikerpodden 11/10 2010)

12. Evolutionsteorins förutsägelser (från Skeptikerpodden 15/11 2010)

FöregåendeNästa

Mandelbrot

The day before yesterday, I did a bit on Bo E. Carlsson’s book on fractals, and then yesterday, one of the masterminds behind fractal geometry, Benoît Mandelbrot, died. Mandelbrot coined the term “fractal” and gave name to the Mandelbrot set, the fractal which he described. A fractal is a self repeating geometric shape. This is what a Mandelbrot set looks like (generated using ChaosPro):

A closer look:

If you are using an older version of Windows, Fractint is the best fractal software.

The C source code for Fractint is available for download from here.

Notable speeches on evolution

These are in my opinion the currently most important speeches on evolution and creationism. You don’t have to have any preexisting knowledge to be able to follow, and they cover why we know what we know about the occuring evolution and why we know creationism (such as Intelligent Design) is false.

ID Creationisms Trojan Horse
Prof. Barbara Forrest, 2008

The Intelligent Design movement and the Dover-Kitzmiller trial. About 60 min.

Creationism: Still crazy after all these years
Dr. Eugenie Scott, 2009

A very entertaining history of Intelligent Design. 56 min.

Why evolution is true
Prof. Jerry Coyne, 2009

A lovely introduction on why we know evolution occurs. This talk suffers from a “microphone location problem” but it is fully understandable. 57 min.

My bits on evolution, part 3

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

7. Spår av design (från Skeptikerpodden 17/8 2010)

8. Gemensam design = gemensam designer? (från Skeptikerpodden 31/8 2010)

9. Frågor från en kreationist, och svar (från Skeptikerpodden 12/9 2010)

FöregåendeNästa

Skeptikerforum gör sig påmind

Om du ännu inte registrerat dig på svenska Skeptikerforum, diskussionsforum för Skeptikerpodden och Svenska 1023, passa på att göra det!

Skeptikerpodden är en svensk podcast som ifrågasätter pseudovetenskap, vidskepelse och övernaturliga fenomen. Vi är åtta personer, under ledning av illutionisten John Houdi som tar hedern från kreationister, homeopater och andra bedragare.

Svenska 1023 är en kampanj för att behålla förbudet mot behandling av barn med alternativmedicinska metoder (kvacksalveri). Skriv gärna på uppropet!

My bits on evolution, part 2

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

4. Flodmyter (från Skeptikerpodden 25/5 2010)

5. Evolutionsteorins tillämpningar (från Skeptikerpodden 7/6 2010)

6. Artbildning (från Skeptikerpodden 7/7 2010)

FöregåendeNästa

En snabbkurs i homeopatiska läkemedel

En liten snabbkurs i homeopatika från Der Spiegel, tips från Orsakverkan (Twitter).

D1 betyder att lösningen är spädd med en del av den aktiva ingrediensen och 9 delar vatten. D2 betyder att en D1 lösning är spädd på samma sätt, så att en hundradel av lösningen är den aktiva ingrediensen. Siffran talar alltså om hur många nollor du ska ha i faktorn. D1 betyder 1:10. D2 betyder 1:100. D3 betyder 1:1000. D9 betyder 1:1 miljard, alltså ungefär som en droppe av den aktiva substansen i en tankbil. D78 betyder att av alla molikyler som finns i hela universum, är några stycken från den aktiva ingrediensen. Enligt Der Spiegel används lösningar upp till D1000 i Tyskland. Vågar man påstå att homeopater säljer dyrt kranvatten?

Du som inte redan följer Pekkas blogg, Orsakverkan, hittar den här.

My bits on evolution, part 1

Some of my bits for the Swedish Skeptic Podcast, Skeptikerpodden, on evolution and creationism, in Swedish.

Några av mina bidrag till svenska Skeptikerpodden om evolution och kreationism, på svenska.

1. “Evolutionism” (från Skeptikerpodden 31/3 2010)

2. Kreationistiska falanger (från Skeptikerpodden 12/4 2010)

3. Bevis för evolution (från Skeptikerpodden 3/5 2010)

Nästa

Noah’s calculator found!

Recently, we have read about some insane adventurers who have found NOAH’S ARK! Yes, the boat that Noah used to survive the flood together with seven pairs (14 animals) of each “clean” species (or bird) and one pair of each “unclean”. As you might guess, this is a huge project. The collecting itself must have been exhausting. However, now we have found his calculator!

Download it here.

Vad är vetenskaplig skepticism?

Första avsnittet av Skeptikerpodden är nu publicerad. Saxat från Skeptikerpodden.se:

I vårt premiäravsnitt förklarar vi vad vetenskaplig skepticism är för något och diskuterar folks reaktioner på uttrycket. Vi diskuterar en nyhet om en ny människoart och några av bristerna i nyhetsrapporteringen kring detta. Magikern Gaston intervjuas och han får förklara sin syn på skepticism. En liten överraskning från James Randi lurar också i programmet. Mycket nöje!

Jag ser fram emot att jobba vidare med detta projekt.

Radiometric dating, why do we trust it?

You just got to love the YouTube user cdk007. In his (at this point) latest video, he spends 10 minutes to explain how radiometric dating to a hypothetic creationist, adding the objections you would expect from a creationist. If you ever hear the argument that radiometric dating doesn’t work (assuming that we don’t know how atoms work), get them to watch this! Or at least, make sure you know the correct answer to the following question:

How do we know that we actually can trust radiometric dating?

Some visual aid

To conclude, click on an organism to zoom in on it. When an organism is zoomed in, some details about it is shown together with the DNA string of the parent organisms (if the parents are still alive).

Download: Drifting.exe

Happy new year!

If you are interested in looking at the source code, a VS2010 Visual Basic solution can be downloaded here. The solution targets .NET Framework 2.0.

Counting the DNA differences

The following adjustment is done to the drifting game. In the first version, DNA differences were counted sequentially, meaning that within each group each organism was compared to its neighbor. By changing this so that every organism is compared to every other organism, and then divided to the number of comparisons done within each group, the number of DNA differences within each group is much more accurate. This makes the increasing differences, the drifting, much more obvious.

The screenshot displays the number of differences just a few years after separation of the groups.

Download the drifting game here.

This is the drifting game!

The drifting game does not illustrate evolution or the power of natural selection, but change over time and our ability to tell that about relationship to other spices, such as chimpanzees. The board consists of 285 placeholders (19 x 15). Each placeholder can hold one organism. This is an organism.

The blue number indicates the age in years of the organism. The red number shows the number of offspring the organism has produced. An organism cannot produce offspring on its own; it must mate with another organism of the opposite gender. Light blue rectangle represent male organisms, pink represent female. What else? 😉 The lines are drawn between parents with the child in between.

In the middle, the DNA of the organism is displayed. The red amino acid pairs with red or yellow amino acid. The green amino acid pairs with green or blue amino acid. A DNA string consists of 24 pairs. The effect of this demonstration will be better if the number of pairs is greater, but it makes the visual overview poorer.

When organisms breed, the offspring will have a mixture of the parents DNA. Sometimes, mutations occur. Mutations cannot be traced from either parent. A mutation can sometimes be easy to spot, because in a mutation, any amino acid can pair with any amino acid. So a red could pair with a red, but it could also pair with a green. A pair of red and yellow could be a mutation, a pair of red and green is a mutation.

An organism that isn’t too young or too old might breed and an organism of high age might die and leave room for younger individuals.

To control: Press Space to pause and press F12 to separate the group in to two groups (can be done once). The expected effect after the split is that the number of DNA differences between individuals in the group will remain the same as the previous total, but the DNA differences between the groups will increase over time, even though no selection is done. The DNA differences are counted for sequentially and divided by the number individuals in a group. So, not every individual is compared with every individual. Correction here.

Before the population is splitted into two groups (press F12 to do that), the total number of DNA differences is shown. After the population is splitted into two groups, the total number of DNA differences is shown together with the number of DNA differences within each group. Now you can compare the differences within each group (expected to be smaller) with the total number of differences (expected to be larger since the groups are drifting in different directions).

Download the drifting game here.

Making fun things from the knowledge of evolution

Evolution is a powerful mechanism, and the powerful source that is behind it is decent with modification plus selection. In nature, it has taken us from simple chemical reactions to complex self-aware organism over billions of years. The structure of any living mammal is very complex, and biology is filled with complicated concepts, and nothing would make any sense if we didn’t know about the very simple concept of evolution. In nature, evolution explains why fossils of different ages look different, and it explains the origin of very complex structures like the cell, the immune system and the human brain, and this knowledge casts light over areas that doesn’t have anything to do with biology, like computer science and computer programming.

Designed structures are usually simple and have one or a few purposes, while evolved structures usually are complex and have multiple functions. Designed structures usually are things. Obstacles, roads, walls, jugs. Evolved structures usually work as things. Pipes, connections, obstacles, skeletons. This is because evolved structures come about without a given purpose, but are maintained and further developed if the structure is useful.

Can we use the knowledge of our origin get some fun out of our computer? Yes! I have mentioned John Conway’s game of life earlier.

This is EvoLisa. It is a program that draws polygons and compares them to a picture. Then it changes the polygons slightly, and again compares them to a picture. Changes that make the polygons look more like the picture are kept, other changes are discarded. The result is a computer generated vector based pictures that looks like the original picture. More generations of change and selection, gives a computer generated picture that is more like the original picture. Here, selection is based on comparison to the original picture, in nature, selection is based on what organisms till survive and reproduce.

Vanliga missförstånd om evolution

Vi fick den stora äran att publicera ett svar på en insändare om evolutionsteorin som publicerades i tidningen Dagen. Det som vänds emot evolutionsteorin i insändaren, är sådant som de flesta betraktar som avhandlat och färdigbemött, som t.ex. Piltdown-mannen, och detta svar borde avfärda denna kritik för sista gången.

Svaret är skrivet författaren Patrik Lindenfors, och här på Evolutionsteori.se kan du läsa både insändaren i sin helhet och Patrik Lindenfors svar.

John Conway’s game of life

John Conway’s game of life is the simplest known self-organizing system, and it is a good example of evolution. Just like evolution, the environment decides the fitness of the organism. In the case of evolution, the parameters that describe fitness are complex, and in John Conway’s game of life, they are very simple. The game consists of an area of cells. A cell with too few neighbours (none or one) dies from loneliness, a cell with too many neighbors dies from overcrowding. A cell with two or three neighbours survives and an empty space with two neighbours becomes a cell. So the game of life is an infinite iteration of applying rules and adding energy, just like the physical world is. When you start with a world with randomly added cells, and you apply the rules on the world time and time again, the cells will form structures that are more or less stable. A stable structure can be very simple or rarely very complex. If a structure is moving, it can collide with another structure and perish, or form a new structure. Some structures, stable or unstable, form new structures.

Math.com writes about John Conway’s game of life here. If you have Java installed, you will able to watch the behavior of a few stable structures.

The following source code (Visual Basic 9) illustrates how simple the games is, and please notice that there is no implementation of intelligence. Intelligence is simply not required to make complex structures. The code is written in a class that inherits from the System.Windows.Forms.Form class.

'The resources are a 2D map of bytes, a timer
'and a delegate (for technical reasons).
Private World(400, 400) As Boolean
Private WithEvents T As System.Timers.Timer
Private Delegate Sub DrawBitmapDelegate(ByVal B As System.Drawing.Bitmap)

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

	'Start off by placing some (about 11,000) random cells in the world.
	Dim Rnd As New Random()
	For I As Integer = 0 To 11000
		World(Rnd.Next(60, 341), Rnd.Next(60, 341)) = True
	Next

	'Create a timer - one generation lasts for 20 ms.
	T = New System.Timers.Timer(20)
	AddHandler T.Elapsed, AddressOf DoGeneration
	T.Start()

End Sub

Private Sub DoGeneration(ByVal sender As Object, _
ByVal e As System.EventArgs)

	'Appy the rules of the simulation on the cells in the world.
	ApplyRules()

	'Display the world on the screen
	'(that is, copy to a bitmap, draw the bitmap).
	DrawWorld()

End Sub

This makes the main program. The following code defines the functions that are called (ApplyRules and DrawWorld) followed by the functions they call in their turn.

Public Sub ApplyRules()

	'Create a temporary buffer for the new world.
	Dim TempWorld(400, 400) As Boolean

	'Apply the rules of the world to that new buffer.
	For Y As Integer = 0 To 400
		For X As Integer = 0 To 400
			Select Case CountNeighbours(X, Y)
				Case 0, 1
					'With no or one neighbour, the
					'cell dies of loneliness.
					TempWorld(X, Y) = False
				Case 2 'Two neighbours means survival.
					TempWorld(X, Y) = World(X, Y)
				Case 3 'Three neighbours: Birth of a new cell.
					TempWorld(X, Y) = True
				Case Else
					'With four or more neighbours, the cell
					dies from overcrowding.
					TempWorld(X, Y) = False
			End Select
		Next
	Next

	'Save the changes by making the temporary buffer permanent.
	World = TempWorld

End Sub

Private Sub DrawWorld()

	'Let the world vector become pixels on a bitmap.
	Using B As New System.Drawing.Bitmap(401, 401)
		For Y As Integer = 0 To 400
			For X As Integer = 0 To 400
				If World(X, Y) Then
					B.SetPixel(X, Y, Color.Black)
				Else
					B.SetPixel(X, Y, Color.White)
				End If
			Next
		Next
			'Draw the bitmap on the screen. A thread shift must be done.
		Dim D As New DrawBitmapDelegate(AddressOf DrawBitmap)
		Me.Invoke(D, B)
	End Using

End Sub

'This method does the actual drawing, on a the GUI thread.
Private Sub DrawBitmap(ByVal B As System.Drawing.Bitmap)
	Using G As System.Drawing.Graphics = System.Drawing.Graphics.FromHwnd(Me.Handle)
		'Apply some magnification while doing the actual drawing.
		G.DrawImage(B, New Rectangle(0, 0, 800, 800), _
		New Rectangle(0, 0, 400, 400), GraphicsUnit.Pixel)
	End Using
End Sub

Private Function CountNeighbours(ByVal X As Integer, ByVal Y As Integer) As Integer
	Dim Ret As Integer = 0
	For NY As Integer = Y - 1 To Y + 1
		For NX As Integer = X - 1 To X + 1
			If Not (NY = 0 And NX = 0) Then
				If NY >= 0 And NY <= 400 And NX >= 0 And NX <= 400 Then
					If World(NX, NY) Then
						Ret += 1
					End If
				End If
			End If
		Next
	Next
	Return Ret
End Function

Another example is posted here.