diff --git a/.gitignore b/.gitignore index a78a332..b5e991a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *~ *.swp -.vagrant/ \ No newline at end of file +.vagrant/ +_build/ \ No newline at end of file diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..f2c2014 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,55 @@ +# Shamelessly stolen from https://gist.github.com/sudarkoff/3956724 + +BUILD_DIR := _build + +# pandoc is a handy tool for converting between numerous text formats: +# http://johnmacfarlane.net/pandoc/installing.html +PANDOC := pandoc + +# pandoc options +# Liberation fonts: http://en.wikipedia.org/wiki/Liberation_fonts +PANDOC_PDF_OPTS := --toc --chapters --base-header-level=1 --number-sections --variable mainfont="Liberation Serif" --variable sansfont="Liberation Sans" --variable monofont="Liberation Mono" --variable fontsize=12pt --variable documentclass=book + +MARKDOWN := $(wildcard *.md) +PDF := $(patsubst %.md,$(BUILD_DIR)/pdf/%.pdf,$(MARKDOWN)) +DOCX := $(patsubst %.md,$(BUILD_DIR)/docx/%.docx,$(MARKDOWN)) +HTML := $(patsubst %.md,$(BUILD_DIR)/html/%.html,$(MARKDOWN)) + +.PHONY: all checkdirs pdf doc html clean + +all: checkdirs pdf docx html + +checkdirs: $(BUILD_DIR) + +pdf: checkdirs pdfdir $(PDF) + +docx: checkdirs docxdir $(DOCX) + +html: checkdirs htmldir $(HTML) + +$(BUILD_DIR): + @mkdir -p $@ + +pdfdir: + @mkdir -p $(BUILD_DIR)/pdf + +docxdir: + @mkdir -p $(BUILD_DIR)/docx + +htmldir: + @mkdir -p $(BUILD_DIR)/html + +# generate PDF +$(BUILD_DIR)/pdf/%.pdf: %.md + $(PANDOC) $(PANDOC_PDF_OPTS) --self-contained -o $@ $< + +# generate Microsoft Word documents (.docx) +$(BUILD_DIR)/docx/%.docx: %.md + $(PANDOC) --self-contained -o $@ $< + +# generate HTML files +$(BUILD_DIR)/html/%.html: %.md + $(PANDOC) --self-contained -o $@ $< + +clean: + @rm -rf $(BUILD_DIR) diff --git a/doc/bitwise_computation_tutorial.md b/doc/bitwise_computation_tutorial.md new file mode 100644 index 0000000..8e2ed1a --- /dev/null +++ b/doc/bitwise_computation_tutorial.md @@ -0,0 +1,86 @@ +# Bitwise Computation Tutorial: Circuits and Goals + +## Introduction + +The CGP Julia package implements digital logic-gate circuit evolution +in Julia using bitwise computation. This tutorial introduces the +underlying concepts. + +## Logic Gates + +Logic gates are the building blocks of logic circuits. We start with 4 +basic logic gates, namely NOT (`~`), AND (`&`), OR (`|`), and XOR +(`$`). + +The semantics of a logic gate is described by its truth table. Here is +the truth table of the NOT gate: + +A | NOT(A) +--|------- +F | T +T | F + +In other words, if the input A is `T` (true), then the output is `F` +(false), and vice versa. Consistent with programming notation, we will +use `1` for true and `0` for false. And we will use the Julia symbols +shown above to denote the operation of the logic gate. Here is the +truth table using this notation: + +`A` | `~A` +------|----- +0 | 1 +1 | 0 + +And here are the truth tables of all of the above gates in one table: + +`A` | `B` | `~A` | `A & B` | A | B | `A $ B` +------|-------|--------|---------|----------|-------- +0 | 0 | 1 | 0 | 0 | 0 +1 | 0 | 0 | 0 | 1 | 1 +0 | 1 | 1 | 0 | 1 | 1 +1 | 1 | 0 | 1 | 1 | 0 + +Next, we will transpose the table which makes columns into rows and +rows into columns. Rows of the transposed truth table will correspond +to what is stored in a computer word. + +Expression | | | | +------------------------|---|---|---|-- +`A` | 0 | 1 | 0 | 1 +`B` | 0 | 0 | 1 | 1 +`~A` | 1 | 0 | 1 | 0 +`A & B` | 0 | 0 | 0 | 1 +A | B | 0 | 1 | 1 | 1 +`A $ B` | 0 | 1 | 1 | 0 + +## Circuits + +Next we will look at the half-adder and full-adder circuits. These +circuits are described on +[Wikipedia](http://en.wikipedia.org/wiki/Adder_%28electronics%29). Here +is the logic diagram of the half adder (taken from the linked page). + +![Half Adder](img/half-adder.png) + +The truth table for this circuit in our transposed notation is: + +Expression | | | | +-----------|---|---|---|-- +`A` | 0 | 1 | 0 | 1 +`B` | 0 | 0 | 1 | 1 +`C` | 0 | 0 | 0 | 1 +`S` | 0 | 1 | 1 | 0 + +Note that the C row is the same as the `A & B` row above since output +C is just the output of an AND gate, and the S row is the same as the +`A $ B` row above since output S is just the ouput of an XOR gate. + +The logic diagram for the full adder is: + +![Full Adder](img/full-adder.png) + +## Hexadecimal and Octal Notation + +## Goals + +## Chromosomes diff --git a/doc/img/full-adder.png b/doc/img/full-adder.png new file mode 100644 index 0000000..4c4fc38 Binary files /dev/null and b/doc/img/full-adder.png differ diff --git a/doc/img/half-adder.png b/doc/img/half-adder.png new file mode 100644 index 0000000..3bc78c4 Binary files /dev/null and b/doc/img/half-adder.png differ diff --git a/src/CGP.jl b/src/CGP.jl index 80cb3d2..ef5aa8c 100644 --- a/src/CGP.jl +++ b/src/CGP.jl @@ -9,5 +9,6 @@ include("Execute.jl") include("Mutation.jl") include("Goal.jl") include("Fitness.jl") +include("Utilities.jl") end diff --git a/src/Execute.jl b/src/Execute.jl index e13fbea..e5735e6 100644 --- a/src/Execute.jl +++ b/src/Execute.jl @@ -1,4 +1,4 @@ -export execute_chromosome, output_mask +export execute_chromosome function evaluate_node(c::Chromosome, node::InputNode, context::Vector{BitString}) node.active = true @@ -46,16 +46,3 @@ function execute_chromosome(c::Chromosome) return BitString[x & mask for x = result] end - -# TODO: This function appears in a couple places, factor it into a utility file. -# bitstring mask for one output of the packed representation -function output_mask(num_inputs) - one = convert(BitString, 0x1) - mask = one - for i in 1:(2^num_inputs-1) - mask <<= 1 - mask |= one - end - return mask -end - diff --git a/src/Goal.jl b/src/Goal.jl index 29e176c..40cc192 100644 --- a/src/Goal.jl +++ b/src/Goal.jl @@ -128,18 +128,6 @@ function convert{N}(::Type{InterleavedPackedGoal}, g::Goal{N}) return convert(InterleavedPackedGoal, convert(BasicPackedGoal, g)) end -# Utility function which returns bitstring mask for one output of the -# packed representation. -function output_mask(num_inputs) - one = convert(BitString, 0x1) - mask = one - for i in 1:(2 ^ num_inputs - 1) - mask <<= 1 - mask |= one - end - return mask -end - # Compose two goals g, and h. The number of outputs from h must be # equal to the number of inputs to g. function compose(g::InterleavedPackedGoal, h::InterleavedPackedGoal) diff --git a/src/Utilities.jl b/src/Utilities.jl new file mode 100644 index 0000000..c238008 --- /dev/null +++ b/src/Utilities.jl @@ -0,0 +1,29 @@ +# Utility function which returns bitstring mask for one output of the +# packed representation. +# Examples: output_mask(2) returns 0b1111 = 0XF +# and output_mask(3) returns 0b11111111 = 0XFF +function output_mask(num_inputs) + mask = convert(BitString, 0x1) + for i in 0:(num_inputs-1) + mask |= (mask << 2^i) + end + return mask +end + +# Returns an array of BitStrings which are the standard inputs to a chromosome +# when it is executed. +# num_inputs is the number of inputs of the chromosome. +function std_input_context(num_inputs) + if 2^num_inputs > 8*sizeof(BitString) + error("number of inputs is too large for size of BitString in std_input_context") + end + std_in = Array(BitString,num_inputs) + std_in[1] = 0b10 + for i in 2:num_inputs + std_in[i] = output_mask(i-1) << 2^(i-1) + for j in 1:(i-1) + std_in[j] $= std_in[j] << 2^(i-1) + end + end + return std_in +end