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).
+
+
+
+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:
+
+
+
+## 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