using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace RFS { class pointF { private const double horizontal_circumference_of_world = 1000.0; public double myX, myY; public double x // Accessor methods for this point's coordinates. { get { return myX; } set { myX = value; } // % horizontal_circumference_of_world; } } public double y { get { return myY; } set { myY = value; } } public double xDiff(pointF other) { double diff = Math.Abs(x - other.x); if (diff > horizontal_circumference_of_world / 2) return horizontal_circumference_of_world - diff; else return diff; } public double yDiff(pointF other) { double diff = Math.Abs(y - other.y); return diff; } } // Square is the piece to be nested. class Square : ICloneable { public double s = 100.0; // side length private pointF location = new pointF(); // x,y coordinates of the center of this square public int num_copies = 0; private int fontsize = 10; protected double my_niche_count; // niche_count is the denominator in the RFS shared fitness calc. // Measures the total amount overlap between this square and all // others in the population. public double x // Accessor methods for this square's coordinates. { get { return location.x; } set { location.x = value; } } public double y { get { return location.y; } set { location.y = value; } } public double niche_count // Accessor methods for this shape's niche_count. { get { return my_niche_count; } set { my_niche_count = value; } } public double fitness // Accessor methods for this shape's RFS shared fitness. { get { return 1.0 / niche_count; } } public void move(double newX, double newY) // Changes the location of this shape { x = newX; y = newY; } public void randomize(Random rFountain) // Move ourselves to random location within 800 by 600 area. { x = rFountain.NextDouble() * 200 + 50; char randomChar = (char)rFountain.Next(0, 2); y = rFountain.NextDouble() * 200 + 50; } public Boolean equals(Square other) { return (x == other.x && y == other.y); } public void paint(Graphics g) { g.DrawRectangle(new Pen(Color.Green, 1), (int)(x - s/2), (int)(y - s/2), (int) s, (int) s); if (num_copies >= 0) g.DrawString("" + num_copies, new Font("Arial", fontsize, FontStyle.Regular), Brushes.Blue, (float)(x - fontsize / 2.0), (float)(y - fontsize / 2.0)); } public double area_of() { return s*s; } public double area_of_overlap(Square other) { if (other is Square) { if (equals(other)) return area_of(); else { if (location.xDiff(other.location) >= s || location.yDiff(other.location) >= s) return 0.0; else return (s - location.xDiff(other.location)) * (s - location.yDiff(other.location)); } } else { Console.WriteLine("Oh-oh! Non-circle!"); return 0.0; } } public Object Clone() { Square copyOfMe = new Square(); copyOfMe.move(x, y); copyOfMe.niche_count = niche_count; copyOfMe.s = s; return copyOfMe; } } // Circle is the piece to be nested. class Circle : ICloneable { public double r = 50.0; // radius private pointF location = new pointF(); // x,y coordinates of the center of this circle public int num_copies = 0; private int fontsize = 10; protected double my_niche_count; // niche_count is the denominator in the RFS shared fitness calc. // Measures the total amount overlap between this circle and all // others in the population. public double x // Accessor methods for this circle's coordinates. { get { return location.x; } set { location.x = value; } } public double y { get { return location.y; } set { location.y = value; } } public double niche_count // Accessor methods for this shape's niche_count. { get { return my_niche_count; } set { my_niche_count = value; } } public double fitness // Accessor methods for this shape's RFS shared fitness. { get { return 1.0 / niche_count; } } public void move(double newX, double newY) // Changes the location of this shape { x = newX; y = newY; } public void randomize(Random rFountain) // Move ourselves to random location within 800 by 600 area. { x = rFountain.NextDouble() * 200 + 50; char randomChar = (char)rFountain.Next(0, 2); y = rFountain.NextDouble() * 200 + 50; } public Boolean equals(Circle other) { return (x == other.x && y == other.y); } public void paint(Graphics g) { g.DrawEllipse(new Pen(Color.Green, 1), (int) (x - r), (int)(y - r), (int) (2*r), (int) (2*r)); if (num_copies >= 0) g.DrawString("" + num_copies, new Font("Arial", fontsize, FontStyle.Regular), Brushes.Blue, (float)(x - fontsize / 2.0), (float)(y - fontsize / 2.0)); } public double area_of() { return Math.PI * r * r; } public double area_of_overlap(Circle other) { double distance_squared; double chord_area; double h; if (other is Circle) { if (equals(other)) return area_of(); else { distance_squared = Math.Pow(x - other.x, 2.0) + Math.Pow(y - other.y, 2.0); if (distance_squared >= 4 * r * r) return 0.0; else { h = (2.0 * r - Math.Sqrt(distance_squared)) / 2.0; chord_area = (r * r * Math.Acos((r - h) / r)) - (r - h) * Math.Sqrt(2 * r * h - h * h); Console.WriteLine("Chord area: "+chord_area); return 2 * chord_area; } } } else { Console.WriteLine("Oh-oh! Non-circle!"); return 0.0; } } public Object Clone() { Circle copyOfMe = new Circle(); copyOfMe.move(x, y); copyOfMe.niche_count = niche_count; copyOfMe.r = r; return copyOfMe; } } class Population { private Random rFountain; private int popsize; private Circle[] members; private double summed_fitnesses; public Population(int new_popsize) { popsize = new_popsize; members = new Circle[popsize]; rFountain = new Random(); } public void initialize() { for (int i = 0; i < popsize; i++) members[i] = new Circle(); } // This method sets up the initial situation with three species, and pop split evenly // among them. Species s1 and s2 form an exact cover, while species s3 is "dominated' // by the first two, and SHOULD die out under RFS... public void init_two_against_one() { for (int i = 0; i < popsize / 3; i++) // species s1 { members[i] = new Circle(); members[i].move(0, 0); } for (int i = popsize / 3; i < popsize * 2 / 3; i++) //species s2 { members[i] = new Circle(); members[i].move(100, 0); } for (int i = popsize * 2 / 3; i < popsize; i++) //species s3 { members[i] = new Circle(); members[i].move(50, 0); } } // This method sets up the initial situation with three species, and pop split evenly // among them. Species s1 and s2 form an exact cover, while species s3 is "dominated' // by the first two, and SHOULD die out under RFS... public void init_two_against_two() { for (int i = 0; i < popsize/4; i++) // species a { members[i] = new Circle(); members[i].move(50, 50); } for (int i = popsize/4; i < 2*popsize/4; i++) //species b { members[i] = new Circle(); members[i].move(150, 50); } for (int i = 2*popsize/4; i < 3*popsize/4; i++) //species c { members[i] = new Circle(); members[i].move(50, 150); } for (int i = 3*popsize/4; i < popsize; i++) //species d { members[i] = new Circle(); members[i].move(150, 150); } } public void randomize() // Create random initial population { for (int i = 0; i < popsize; i++) members[i].randomize(rFountain); } public void evaluate_fitness() // Evaluate RFS shared fitness of everyone in pop. { summed_fitnesses = 0; for (int i = 0; i < popsize; i++) { members[i].niche_count = members[i].area_of(); members[i].num_copies = 0; } for (int i = 0; i < popsize; i++) { for (int j = i + 1; j < popsize; j++) { double temp = members[i].area_of_overlap(members[j]); members[i].niche_count += temp; members[j].niche_count += temp; if (temp == members[i].area_of()) { members[i].num_copies++; members[j].num_copies++; } } summed_fitnesses += members[i].fitness; } } public Circle select_Roulette() // Implements Roulette Wheel Selection to select // one individual from current population. Assumes { // all pop has been evaluated. double ball = rFountain.NextDouble() * summed_fitnesses; double slot = members[0].fitness; int i = 0; while (ball > slot) slot += members[++i].fitness; return (Circle) members[i].Clone(); // HW7, FIX THIS!!!!! } public void create_next_generation() // Returns a new population by { // by applying RWS to this pop. Population next_gen = new Population(popsize); for (int i = 0; i < popsize; i++) next_gen.members[i] = select_Roulette(); for (int i = 0; i < popsize; i++) members[i] = next_gen.members[i]; } public void print_coordinates() // Print locations of all Shapes in this pop. { for (int i = 0; i < popsize; i++) Console.WriteLine("(" + members[i].x + "," + members[i].y + "}" + " niche_count: " + members[i].niche_count); } public void paint(Graphics g, int thresholdIN) { if (this != null) for (int i = 0; i < popsize; i++) if (members[i].num_copies >= thresholdIN) members[i].paint(g); } public Population evolve(int num_gens) { // pop.randomize(); for (int g = 0; g < num_gens; g++) // generation loop { evaluate_fitness(); print_coordinates(); Console.WriteLine("---------------------" + g + "----------------------------"); create_next_generation(); } evaluate_fitness(); print_coordinates(); return this; } } // TestRFS implements the patented RFS algorithm (Resource-defined Fitness Sharing) public partial class RFSform : Form { private Population currentPop; private Button new_run = new Button(); private Button incr_threshold = new Button(); private Button decr_threshold = new Button(); private int substrate_width = 800; private int substrate_height = 600; private int threshold = 0; public RFSform() { Text = "CS 326 Winter 2007 FINAL PROJECT: RFS with Various Shapes"; Size = new Size(substrate_width+100, substrate_height+100); new_run.Text = "evolve 10 gens"; new_run.Location = new Point(substrate_width + 10, 20); Controls.Add(new_run); new_run.Click += new EventHandler(NewTrial); incr_threshold.Text = "Increase"; incr_threshold.Location = new Point(substrate_width + 10, 60); Controls.Add(incr_threshold); incr_threshold.Click += new EventHandler(IncrThreshold); decr_threshold.Text = "Decrease"; decr_threshold.Location = new Point(substrate_width + 10, 80); Controls.Add(decr_threshold); decr_threshold.Click += new EventHandler(DecrThreshold); currentPop = new Population(100); currentPop.initialize(); // Can try other initial pops, here. currentPop.randomize(); } protected void NewTrial(Object sender, EventArgs e) { currentPop.evolve(10); Refresh(); } protected void IncrThreshold(Object sender, EventArgs e) { threshold++; Refresh(); } protected void DecrThreshold(Object sender, EventArgs e) { if(threshold>0) threshold--; Refresh(); } protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.DrawString("Species Count Threshold: "+threshold, new Font("Arial", 8, FontStyle.Regular), Brushes.Black, substrate_width - 14, 48); Pen blue = new Pen(Color.Blue, 3); if(currentPop != null) currentPop.paint(g,threshold); base.OnPaint(e); } } }