0

First I would like to say that I am aware of different topics on true Randomness with seeds and how new Random() is created depending on Environment.TickCount. Despite all that I couldn't figure out what my problem is. I'm trying to create a population of 100 graphs for use in Graph Coloring Genetic Algorithm. Every single population consists of set number of edges and set number of nodes. Every node has an index number and a random initial color. That initial color is what I want to random. The colors are ints between 1 and 10. But every single population looks the same, same nodes got same colors. I probably might have missed something simple but I just cannot figure it out. Any help would be appreciated.

CreatePopulation.cs

class CreatePopulation
{

    private static Solution CreateRandomSolution(Graph graph, int colorsCount)
    {
        Solution solution = new Solution(graph, colorsCount);
        for (int node = 0; node < graph.Nodes.Count; node++)
        {
            solution.assignColor(node, Program.RandomNumber(1, 10));
        }

        return solution;
    }

    public static List<Solution> CreateRandomPopulation(Graph graph, int populationSize)
    {
        List<Solution> list = new List<Solution>();
        for (int i = 0; i < populationSize; i++)
        {
            list.Add(CreateRandomSolution(graph, 10));
        }
            return list;
    }

}

Solution.cs holding future implementation of fitness methods and other methods needed for algorithm

  class Solution
{
    private int colorsCount;
    private List<Vertex> edges;
    private List<Node> nodes;

    private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
    {
        this.colorsCount = colorsCount;
        this.edges = edges;
        this.nodes = nodes;
    }

    public Solution(Graph graph, int colorsCount)
    {
        edges = graph.Vertices;
        this.colorsCount = colorsCount;
        this.nodes = graph.Nodes;
    }

    public void assignColor(int index, int color)
    {
        nodes[index].color = color;
    }

}

Program.cs with main function

 class Program
{
    public static readonly Random Random = new Random();

    private static double MutationRate = 0.05;

    private static double CrossoverRate = 0.7;

    private static int Colors = 10;

    private static int GenerationCount = 100;

    private static int PopulationSize = 100;

    private static readonly object syncLock = new object();

    public static int RandomNumber(int min, int max)
    {
        lock (syncLock)
        {
            return Random.Next(min, max);
        }
    }

    static void Main(string[] args)
    {
        var graph = new Graph(@"C:\Users\Pawel\Desktop\lab1\GraphColoring-branch\bin\Debug\geom20.col");
        var initPopulation = CreatePopulation.CreateRandomPopulation(graph, PopulationSize);
        Console.ReadLine();
    }


}

Node.cs

namespace Graph
{
    class Node
    {
        public int number { get; set; }
        public int color { get; set; }

        public Node(int number)
        {
            this.number = number;
        }
        public Node() { }
    }
}

Update Changed the way I create a new List in Solution.cs but would like to know if it can be done in a nicer way.

 public Solution(Graph graph, int colorsCount)
    {
        this.edges = graph.Vertices;
        this.colorsCount = colorsCount;
        this.nodes = new List<Node>(graph.Nodes.Count);
        for (int i = 0; i < graph.Nodes.Count; i++)
        {
            this.nodes.Add(new Node{color = graph.Nodes[i].color, number = graph.Nodes[i].number});
        }
    }
Galaxiset
  • 69
  • 7
  • 1
    do not add inaccurate tags to your question. – user1666620 Mar 08 '16 at 16:51
  • is the problem that your `RandomNumber()` method returns the same integer value every time? – user1666620 Mar 08 '16 at 16:56
  • @user1666620 In loop through all nodes in single Graph it has different values, but all Graphs(have 100 of them in population) are the same. I want colors of nodes to be different between graphs – Galaxiset Mar 08 '16 at 16:59
  • when you set breeakpoints and debug through your code, does the `color` argument passed to your `assignColor` method change every time you call it? – user1666620 Mar 08 '16 at 17:01
  • You are only using 10 colors, are you sure it is not just the way you are visualizing it that it looks the same? Also, `public static readonly Random Random` really should be `private`, you should not be exposing a non-thread safe way to accesss `Random` statically, your current `RandomNumber` method is the correct way to do it. – Scott Chamberlain Mar 08 '16 at 17:04
  • I am sure the random value is different every iteration through a loop and I doubt that I could receive all nodes in all graphs to be equal to same nodes in other graphs everytime. And thanks, I changed it to private, didn't see that it was public. – Galaxiset Mar 08 '16 at 17:07

1 Answers1

2

The problem is every single one of your Solution objects are working from the same instance of List<Vertex> and List<Node>. So Random is working correctly, the real problem is you are overwriting the values for the previous solutions when generate the next solution.


The only constructor I see you use is

Solution solution = new Solution(graph, colorsCount);

In there you do

public Solution(Graph graph, int colorsCount)
{
    edges = graph.Vertices;
    this.colorsCount = colorsCount;
    this.nodes = graph.Nodes;
}

This is just copying the reference of graph.Vertices and graph.Nodes, if any Solution modifies one of the items in the collections all Solutions get modified.

To fix this you need to make a deep copy of those two lists. You did not show what a Vertex or Node was, however if they are classes just doing

public Solution(Graph graph, int colorsCount)
{
    edges = graph.Vertices.ToList();
    this.colorsCount = colorsCount;
    this.nodes = graph.Nodes.ToList();
}

will not be enough because that will only create a shallow copy of the list, your call to nodes[index].color = color; will still modify the nodes in all of the other graphs because although the lists are now separate references the elements in the list are still shared across Solution objects. You need something similar to

class Solution
{
    private int colorsCount;
    private List<Vertex> edges;
    private List<Node> nodes;

    private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
    {
        this.colorsCount = colorsCount;
        this.edges = edges;
        this.nodes = nodes.Select(old => old.Clone()).ToList();
    }

    public Solution(Graph graph, int colorsCount)
    {
        edges = graph.Vertices;
        this.colorsCount = colorsCount;
        this.nodes = graph.Nodes.Select(old => old.Clone()).ToList();
    }

    public void assignColor(int index, int color)
    {
        nodes[index].color = color;
    }

}


class Node
{
    public int number { get; set; }
    public int color { get; set; }

    public Node(int number)
    {
        this.number = number;
    }
    public Node() { }

    public Node Clone()
    {
        var newNode = new Node();
        newNode.number = this.number;
        newNode.color = this.color;
        return newNode;
    }
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Thank you for your answer, I will try to implement it and let you know if it worked asap. I think it might be just that. – Galaxiset Mar 08 '16 at 17:37
  • Would you like to look at my update? Do you think this is enough to fix this issue. It seemed to have worked but would like to hear from you what you think about it. – Galaxiset Mar 08 '16 at 18:47
  • One way you could improve it is wrap all that logic in to a `Clone()` method. I will update my answer with a example. – Scott Chamberlain Mar 08 '16 at 20:12