#region License Information
/* HeuristicLab
* Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using HeuristicLab.Core;
using HeuristicLab.GP.Interfaces;
using System.Text;
using HeuristicLab.Random;
namespace HeuristicLab.GP {
public partial class FunctionLibraryEditor : EditorBase {
private ChooseItemDialog chooseFunctionDialog;
public FunctionLibrary FunctionLibrary {
get { return (FunctionLibrary)Item; }
set { base.Item = value; }
}
public FunctionLibraryEditor()
: base() {
InitializeComponent();
}
public FunctionLibraryEditor(FunctionLibrary library)
: this() {
FunctionLibrary = library;
}
protected override void AddItemEvents() {
base.AddItemEvents();
base.Item.Changed += (sender, args) => UpdateControls();
}
protected override void UpdateControls() {
base.UpdateControls();
mutationListView.Items.Clear();
initListView.Items.Clear();
functionsListView.Clear();
foreach (IFunction fun in FunctionLibrary.Functions) {
functionsListView.Items.Add(CreateListViewItem(fun));
if (fun.Manipulator != null) {
mutationListView.Items.Add(CreateListViewItem(fun));
}
if (fun.Initializer != null) {
initListView.Items.Add(CreateListViewItem(fun));
}
}
}
private void mutationListView_SelectedIndexChanged(object sender, EventArgs e) {
if (mutationListView.SelectedItems.Count > 0 && mutationListView.SelectedItems[0].Tag != null) {
IOperator manipulator = ((IFunction)mutationListView.SelectedItems[0].Tag).Manipulator;
mutationVariableView.Enabled = true;
mutationVariableView.Variable = new Variable("Manipulator", manipulator);
} else {
mutationVariableView.Enabled = false;
}
}
private void initListView_SelectedIndexChanged(object sender, EventArgs e) {
if (initListView.SelectedItems.Count > 0 && initListView.SelectedItems[0].Tag != null) {
IOperator initializer = ((IFunction)initListView.SelectedItems[0].Tag).Initializer;
initVariableView.Enabled = true;
initVariableView.Variable = new Variable("Initializer", initializer);
} else {
initVariableView.Enabled = false;
}
}
private void addButton_Click(object sender, EventArgs e) {
if (chooseFunctionDialog == null) chooseFunctionDialog = new ChooseItemDialog(typeof(IFunction));
if (chooseFunctionDialog.ShowDialog(this) == DialogResult.OK) {
FunctionLibrary.AddFunction((IFunction)chooseFunctionDialog.Item);
}
}
private void removeButton_Click(object sender, EventArgs e) {
// delete from the end of the list
List removeIndices = functionsListView.SelectedIndices.OfType().OrderBy(x => 1.0 / x).ToList();
try {
Cursor = Cursors.WaitCursor;
foreach (int selectedIndex in removeIndices) {
FunctionLibrary.RemoveFunction((IFunction)functionsListView.Items[selectedIndex].Tag);
}
}
finally {
Cursor = Cursors.Default;
}
}
private void functionsListView_SelectedIndexChanged(object sender, EventArgs e) {
if (functionsListView.SelectedIndices.Count > 0) {
removeButton.Enabled = true;
} else {
removeButton.Enabled = false;
}
}
private ListViewItem CreateListViewItem(IFunction function) {
ListViewItem item = new ListViewItem();
item.Name = function.Name;
item.Text = function.Name;
item.Tag = function;
return item;
}
private void functionsListView_ItemDrag(object sender, ItemDragEventArgs e) {
ListViewItem item = (ListViewItem)e.Item;
IFunction fun = (IFunction)item.Tag;
DataObject data = new DataObject();
data.SetData("IFunction", fun);
data.SetData("DragSource", functionsListView);
DoDragDrop(data, DragDropEffects.Link);
}
private void functionsListView_KeyUp(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Delete && functionsListView.SelectedItems.Count > 0) {
List removedFunctions = new List(from x in functionsListView.SelectedItems.OfType()
select (IFunction)x.Tag);
try {
Cursor = Cursors.WaitCursor;
foreach (var fun in removedFunctions) {
FunctionLibrary.RemoveFunction(fun);
}
}
finally {
Cursor = Cursors.Default;
}
}
}
#region fun lib test
private string TestFunctionLibrary() {
int n = 1000;
try {
IFunctionTree[] randomTrees = CreateRandomTrees(n, 1, 100);
StringBuilder builder = new StringBuilder();
builder.AppendLine("Function symbol frequencies:");
builder.AppendLine(CalculateFunctionFrequencies(randomTrees));
builder.AppendLine("-----------------------------------------");
builder.AppendLine("Terminal symbol frequencies:");
builder.AppendLine(CalculateTerminalFrequencies(randomTrees));
builder.AppendLine("-----------------------------------------");
builder.AppendLine("Function arity frequencies:");
builder.AppendLine(CalculateFunctionArityFrequencies(randomTrees));
builder.AppendLine("-----------------------------------------");
builder.AppendLine("Tree size frequencies:");
builder.AppendLine(CalculateTreeSizeFrequencies(randomTrees));
builder.AppendLine("-----------------------------------------");
builder.AppendLine("Tree height frequencies:");
builder.AppendLine(CalculateTreeHeightFrequencies(randomTrees));
return builder.ToString();
}
catch (ArgumentException ex) {
return "Could not create random trees:" + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace;
}
}
private string CalculateFunctionFrequencies(IFunctionTree[] randomTrees) {
Dictionary occurances = new Dictionary();
double n = 0.0;
for (int i = 0; i < randomTrees.Length; i++) {
foreach (var node in FunctionTreeIterator.IteratePrefix(randomTrees[i])) {
if (node.SubTrees.Count > 0) {
if (!occurances.ContainsKey(node.Function))
occurances[node.Function] = 0;
occurances[node.Function]++;
n++;
}
}
}
StringBuilder strBuilder = new StringBuilder();
foreach (var function in occurances.Keys) {
strBuilder.Append(Environment.NewLine);
strBuilder.Append(function.Name); strBuilder.Append(": ");
strBuilder.AppendFormat("{0:#0.00%}", occurances[function] / n);
}
return strBuilder.ToString();
}
public string CalculateTreeSizeFrequencies(IFunctionTree[] randomTrees) {
int[] histogram = new int[105 / 5];
for (int i = 0; i < randomTrees.Length; i++) {
histogram[randomTrees[i].GetSize() / 5]++;
}
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < histogram.Length; i++) {
strBuilder.Append(Environment.NewLine);
strBuilder.Append("< "); strBuilder.Append((i + 1) * 5);
strBuilder.Append(": "); strBuilder.AppendFormat("{0:#0.00%}", histogram[i] / (double)randomTrees.Length);
}
return strBuilder.ToString();
}
public string CalculateTreeHeightFrequencies(IFunctionTree[] randomTrees) {
int[] histogram = new int[100];
for (int i = 0; i < randomTrees.Length; i++) {
histogram[randomTrees[i].GetHeight()]++;
}
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < histogram.Length; i++) {
strBuilder.Append(Environment.NewLine);
strBuilder.Append("< "); strBuilder.Append((i + 1));
strBuilder.Append(": "); strBuilder.AppendFormat("{0:#0.00%}", histogram[i] / (double)randomTrees.Length);
}
return strBuilder.ToString();
}
public string CalculateFunctionArityFrequencies(IFunctionTree[] randomTrees) {
Dictionary occurances = new Dictionary();
double n = 0.0;
for (int i = 0; i < randomTrees.Length; i++) {
foreach (var node in FunctionTreeIterator.IteratePrefix(randomTrees[i])) {
if (!occurances.ContainsKey(node.SubTrees.Count))
occurances[node.SubTrees.Count] = 0;
occurances[node.SubTrees.Count]++;
n++;
}
}
StringBuilder strBuilder = new StringBuilder();
foreach (var arity in occurances.Keys) {
strBuilder.Append(Environment.NewLine);
strBuilder.Append(arity); strBuilder.Append(": ");
strBuilder.AppendFormat("{0:#0.00%}", occurances[arity] / n);
}
return strBuilder.ToString();
}
public string CalculateTerminalFrequencies(IFunctionTree[] randomTrees) {
Dictionary occurances = new Dictionary();
double n = 0.0;
for (int i = 0; i < randomTrees.Length; i++) {
foreach (var node in FunctionTreeIterator.IteratePrefix(randomTrees[i])) {
if (node.SubTrees.Count == 0) {
if (!occurances.ContainsKey(node.Function))
occurances[node.Function] = 0;
occurances[node.Function]++;
n++;
}
}
}
StringBuilder strBuilder = new StringBuilder();
foreach (var function in occurances.Keys) {
strBuilder.Append(Environment.NewLine);
strBuilder.Append(function.Name); strBuilder.Append(": ");
strBuilder.AppendFormat("{0:#0.00%}", occurances[function] / n);
}
return strBuilder.ToString();
}
private IFunctionTree[] CreateRandomTrees(int popSize, int minSize, int maxSize) {
int maxHeight = 10;
int maxTries = 100;
IFunctionTree[] randomTrees = new IFunctionTree[popSize];
MersenneTwister twister = new MersenneTwister();
for (int i = 0; i < randomTrees.Length; i++) {
int treeSize = twister.Next(minSize, maxSize);
IFunctionTree root = null;
int tries = 0;
TreeGardener gardener = new TreeGardener(twister, FunctionLibrary);
do {
try {
root = gardener.PTC2(treeSize, maxSize);
}
catch (ArgumentException) {
// try a different size
treeSize = twister.Next(minSize, maxSize);
tries = 0;
}
if (tries++ >= maxTries) {
// try a different size
treeSize = twister.Next(minSize, maxSize);
tries = 0;
}
} while (root == null || root.GetSize() > maxSize || root.GetHeight() > maxHeight);
randomTrees[i] = root;
}
return randomTrees;
}
private void testButton_Click(object sender, EventArgs e) {
try {
Cursor = Cursors.WaitCursor;
outputTextBox.Text = TestFunctionLibrary();
}
finally {
Cursor = Cursors.Default;
}
}
#endregion
private void functionsListView_MouseUp(object sender, MouseEventArgs e) {
if (functionsListView.SelectedItems.Count > 0) {
IFunction selectedFun = (IFunction)functionsListView.SelectedItems[0].Tag;
Control funView = (Control)selectedFun.CreateView();
funView.Dock = DockStyle.Fill;
functionDetailsPanel.Controls.Clear();
functionDetailsPanel.Controls.Add(funView);
}
}
}
}