
/*
 * Chromosome.class
 * Part of package project
 * 
 * Author: Philip Bradley
 * 
 */

package project;

import java.util.Random;
import java.io.*;

public class Chromosome implements Serializable {
/*
 * Class Chromosome consists of a string (in this case array) of symbols. 
 * Each Chromosome has associated with it, a cost. The cost can only be
 * calulated within the context of the adjacancy matrix representing the
 * graph to be partitioned. The variable AdjacancyMatrix is made static 
 * for efficiency reasons (it is not modified by any of the methods of
 * Chromosome)
 *
 * The static variable hasAdjacancyMatrix is also an efficiency. When
 * the first instance of Chromosome is created, the AdjacancyMatrix
 * variable is defined to be the adjacancy matrix of the graph. This
 * definition is flagged by the boolean hasAdjacancyMatrix.
 */

        public int[] DATA;
        public int COST;
        private static Random numberGen;
        private static boolean hasAdjacancyMatrix = false;
        private static int[][] AdjacancyMatrix;

        public Chromosome(int chromosomeSize, int k, GeometricGraph g) {

                if (!hasAdjacancyMatrix) {
                        AdjacancyMatrix = g.getAdjacancyMatrix();
                        hasAdjacancyMatrix = true;
                }

                DATA = new int[chromosomeSize];
                numberGen = new Random();
                int partitionSize = (int)chromosomeSize/k;
                int splitSize = 0;
                int index = 0;
                COST = 0;

                // Initialise to 0
                for (int i=0; i<chromosomeSize; i++) {
                        DATA[i] = 0;
                }

                // Initialise elements of chromosome
                // Start at 1 because all vertices are in partition 0 by default
                for (int partition=1; partition<k; partition++) {
                        splitSize = 0;
                        while (splitSize < partitionSize) {
                                index = Math.abs(numberGen.nextInt() % chromosomeSize);
                                if (DATA[index] == 0) {
                                        DATA[index] = partition;
                                        splitSize++;
                                }
                        }
                }
 
                if (k != 1) {
                        // Calculate cutsize of partition
                        int edge_ij =0;
                        for (int i=0; i<chromosomeSize; i++) {
                                for (int j=i; j<chromosomeSize; j++) {
                                        edge_ij = AdjacancyMatrix[i][j];
                                        if (edge_ij != 0) {
                                                if (DATA[i] != DATA[j]) {
                                                        COST += 1;
                                                }
                                        }
                                }
                        }
                }
        
        }
 
        public void writeToFile(String filename) {

                try {
                        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filename));
                        os.writeObject(this);
                        os.close();
                } catch (Exception e) {
                        System.err.println("Error writing object: " + e.getMessage());
                }
        }

        public static Chromosome readFromFile(String filename) {
                Chromosome c = (Chromosome)null;
                try {
                        ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
                        c = (Chromosome)in.readObject();
                } catch (Exception e) {
                        System.err.println("Error reading object: " + e.getMessage());
                }
                return(c);
        }

        public String toString() {
                int index = DATA.length;
                String chromosomeAsString = new String("");
 
                while (index-- > 0)
                        chromosomeAsString = DATA[index] + chromosomeAsString;
                return(chromosomeAsString);
        }
}


