summaryrefslogtreecommitdiff
path: root/autoutils/functiongenerator.go
diff options
context:
space:
mode:
Diffstat (limited to 'autoutils/functiongenerator.go')
-rw-r--r--autoutils/functiongenerator.go264
1 files changed, 132 insertions, 132 deletions
diff --git a/autoutils/functiongenerator.go b/autoutils/functiongenerator.go
index 7acb680..20ab0e0 100644
--- a/autoutils/functiongenerator.go
+++ b/autoutils/functiongenerator.go
@@ -20,27 +20,27 @@ along with AutoArt. If not, see <https://www.gnu.org/licenses/>.
package autoutils
import (
- "math"
- "math/rand"
- "fmt"
+ "fmt"
+ "math"
+ "math/rand"
)
// Operators
const (
- CONST = iota
- ADD
- SUB
- MUL
- DIV
+ CONST = iota
+ ADD
+ SUB
+ MUL
+ DIV
MIN
MAX
- SQRT
- SIN
- COS
- TAN
+ SQRT
+ SIN
+ COS
+ TAN
LOG
EXP
- OPERATOR_COUNT
+ OPERATOR_COUNT
)
const FIRST_BINARY = ADD
const FIRST_UNARY = SQRT
@@ -49,147 +49,147 @@ const UNARY_COUNT = OPERATOR_COUNT - FIRST_UNARY
const FIRST_VAR = OPERATOR_COUNT
type Operator struct {
- op int // Operator number. If operator is a variable, v, it is equal to FIRST_VAR + v
- constant float64 // Constant (if op = CONST)
+ op int // Operator number. If operator is a variable, v, it is equal to FIRST_VAR + v
+ constant float64 // Constant (if op = CONST)
}
type Function struct {
- nvars int
- operators []Operator
+ nvars int
+ operators []Operator
}
// Generate a random function f with the given length (i.e. len(f.operators))
// and the given number of variables
func (f *Function) Generate(nvars int, length int) {
- f.nvars = nvars
- f.operators = make([]Operator, length)
- nsOnStack := 0
- i := 0
- for nsOnStack + i < length {
- var operator Operator
- var optype int
- if nsOnStack == 0 {
- // Pick a random variable
- optype = 0
- } else if nsOnStack == 1 {
- // Pick a constant/variable/unary operator
- optype = rand.Intn(3)
- } else {
- // Pick a constant/variable/unary/binary operator
- optype = rand.Intn(4)
- }
- switch optype {
- case 0:
- // variable
- operator.op = FIRST_VAR + rand.Intn(nvars)
- nsOnStack++
- case 1:
- // Constant
- operator.op = CONST
- operator.constant = rand.Float64()
- nsOnStack++
- case 2:
- // unary
- operator.op = rand.Intn(UNARY_COUNT) + FIRST_UNARY
- case 3:
- // binary
- operator.op = rand.Intn(BINARY_COUNT) + FIRST_BINARY
- nsOnStack--
- }
- f.operators[i] = operator
- i++
- }
-
- if nsOnStack + i == length {
- // Add a unary operator
- f.operators[i].op = rand.Intn(UNARY_COUNT) + FIRST_UNARY
- i++
- }
-
- // Keep adding binary operators until nsOnStack == 1
- for nsOnStack > 1 {
- f.operators[i].op = rand.Intn(BINARY_COUNT) + FIRST_BINARY
- nsOnStack--
- i++
- }
+ f.nvars = nvars
+ f.operators = make([]Operator, length)
+ nsOnStack := 0
+ i := 0
+ for nsOnStack+i < length {
+ var operator Operator
+ var optype int
+ if nsOnStack == 0 {
+ // Pick a random variable
+ optype = 0
+ } else if nsOnStack == 1 {
+ // Pick a constant/variable/unary operator
+ optype = rand.Intn(3)
+ } else {
+ // Pick a constant/variable/unary/binary operator
+ optype = rand.Intn(4)
+ }
+ switch optype {
+ case 0:
+ // variable
+ operator.op = FIRST_VAR + rand.Intn(nvars)
+ nsOnStack++
+ case 1:
+ // Constant
+ operator.op = CONST
+ operator.constant = rand.Float64()
+ nsOnStack++
+ case 2:
+ // unary
+ operator.op = rand.Intn(UNARY_COUNT) + FIRST_UNARY
+ case 3:
+ // binary
+ operator.op = rand.Intn(BINARY_COUNT) + FIRST_BINARY
+ nsOnStack--
+ }
+ f.operators[i] = operator
+ i++
+ }
+
+ if nsOnStack+i == length {
+ // Add a unary operator
+ f.operators[i].op = rand.Intn(UNARY_COUNT) + FIRST_UNARY
+ i++
+ }
+
+ // Keep adding binary operators until nsOnStack == 1
+ for nsOnStack > 1 {
+ f.operators[i].op = rand.Intn(BINARY_COUNT) + FIRST_BINARY
+ nsOnStack--
+ i++
+ }
}
func (f *Function) Evaluate(vars []float64) float64 {
- var stack []float64
- for _, op := range f.operators {
- l := len(stack)
- switch (op.op) {
- case CONST:
- stack = append(stack, op.constant)
- case ADD:
- stack[l-2] += stack[l-1]
- stack = stack[:l-1]
- case SUB:
- stack[l-2] -= stack[l-1]
- stack = stack[:l-1]
- case MUL:
- stack[l-2] *= stack[l-1]
- stack = stack[:l-1]
- case DIV:
- if stack[l-1] == 0 { // Check for division by 0
- stack[l-1] = 0.01
- }
- stack[l-2] /= stack[l-1]
- stack = stack[:l-1]
+ var stack []float64
+ for _, op := range f.operators {
+ l := len(stack)
+ switch op.op {
+ case CONST:
+ stack = append(stack, op.constant)
+ case ADD:
+ stack[l-2] += stack[l-1]
+ stack = stack[:l-1]
+ case SUB:
+ stack[l-2] -= stack[l-1]
+ stack = stack[:l-1]
+ case MUL:
+ stack[l-2] *= stack[l-1]
+ stack = stack[:l-1]
+ case DIV:
+ if stack[l-1] == 0 { // Check for division by 0
+ stack[l-1] = 0.01
+ }
+ stack[l-2] /= stack[l-1]
+ stack = stack[:l-1]
case MIN:
stack[l-2] = math.Min(stack[l-2], stack[l-1])
stack = stack[:l-1]
case MAX:
stack[l-2] = math.Max(stack[l-2], stack[l-1])
stack = stack[:l-1]
- case SQRT:
- stack[l-1] = math.Sqrt(math.Abs(stack[l-1]))
- case SIN:
- stack[l-1] = math.Sin(stack[l-1])
- case COS:
- stack[l-1] = math.Cos(stack[l-1])
- case TAN:
- stack[l-1] = math.Tan(stack[l-1])
+ case SQRT:
+ stack[l-1] = math.Sqrt(math.Abs(stack[l-1]))
+ case SIN:
+ stack[l-1] = math.Sin(stack[l-1])
+ case COS:
+ stack[l-1] = math.Cos(stack[l-1])
+ case TAN:
+ stack[l-1] = math.Tan(stack[l-1])
case LOG:
stack[l-1] = math.Log(math.Abs(stack[l-1]))
case EXP:
stack[l-1] = math.Exp(stack[l-1])
- default:
- stack = append(stack, vars[op.op - FIRST_VAR])
- }
- }
- return stack[0]
+ default:
+ stack = append(stack, vars[op.op-FIRST_VAR])
+ }
+ }
+ return stack[0]
}
func (f *Function) String() string {
- var str string
- for _, op := range f.operators {
- switch (op.op) {
- case CONST:
- str += fmt.Sprintf("%v",op.constant)
- case ADD:
- str += "+"
- case SUB:
- str += "-"
- case MUL:
- str += "*"
- case DIV:
- str += "/"
- case SQRT:
- str += "sqrt"
- case SIN:
- str += "sin"
- case COS:
- str += "cos"
- case TAN:
- str += "tan"
- default:
- str += fmt.Sprintf("v%v", op.op - FIRST_VAR)
- }
- str += " "
- }
- return str
+ var str string
+ for _, op := range f.operators {
+ switch op.op {
+ case CONST:
+ str += fmt.Sprintf("%v", op.constant)
+ case ADD:
+ str += "+"
+ case SUB:
+ str += "-"
+ case MUL:
+ str += "*"
+ case DIV:
+ str += "/"
+ case SQRT:
+ str += "sqrt"
+ case SIN:
+ str += "sin"
+ case COS:
+ str += "cos"
+ case TAN:
+ str += "tan"
+ default:
+ str += fmt.Sprintf("v%v", op.op-FIRST_VAR)
+ }
+ str += " "
+ }
+ return str
}
const mutationRate = 0.01
@@ -202,14 +202,14 @@ func (f *Function) Mutate() {
}
}
-func (f *Function) Breed(f1* Function, f2 *Function) {
+func (f *Function) Breed(f1 *Function, f2 *Function) {
// f(x) = (f1(x) + f2(x)) / 2
- f.operators = make([]Operator, len(f1.operators) + len(f2.operators) + 3)
+ f.operators = make([]Operator, len(f1.operators)+len(f2.operators)+3)
for i, o := range f1.operators {
f.operators[i] = o
}
for i, o := range f2.operators {
- f.operators[i + len(f1.operators)] = o
+ f.operators[i+len(f1.operators)] = o
}
i := len(f1.operators) + len(f2.operators)
f.operators[i].op = ADD