Listing 1 Demo program and global functions to solve knapsack problem

#include <stdlib.h>
#include <stdio.h>
#include "pop.h"

static enum Bool {FALSE, TRUE};

// MAXWEIGHT defines the constraint of the knapsack
// example and ItemDesc is simply the coding scheme.

static const int MAXWEIGHT = 17;
static const struct
{
   int    Weight;
   int    Value;
} ItemDesc[] = {
   {3,  4}, {3,  4}, {3,  4}, {3,  4}, {3,  4},
   {4,  5}, {4,  5}, {4,  5}, {4,  5},
   {7, 10}, {7, 10}, {8, 11}, {8, 11}, {9, 13}};

void CalcWeightAndValue(CGAChromosome *Chromosome,
                    int& Weight, int& Value);
Bool FoundSolution(CGAPopulation& Pop);
void PrintPop(CGAPopulation& Pop);

// Main creates the population of chromosomes and
// continues creating new generations until a solution
// is found.

int main(void)
{
   const float  MaxMutationRate = 0.2;
   const int    PopulationSize  = 30;

   CGAPopulation Pop(PopulationSize, sizeof(ItemDesc) /
                  sizeof(ItemDesc[0]),
                  MaxMutationRate);

   while (!FoundSolution(Pop)) {
      Pop.CreateNextGeneration();
      PrintPop(Pop);
   }
   return EXIT_SUCCESS;
}

// Print information and statistics about population.

void PrintPop(
   CGAPopulation& Pop)
{
   float TotalFitness = 0;

   printf("Idx Fit Val Wt Chromosome\n");
   for (size_t ChromIdx = 0;
       ChromIdx < Pop.GetPopulationSize();
       ChromIdx++) {

      int   Weight;
      int   Value;
      CGAChromosome *Chromosome =
         Pop.GetChromosome(ChromIdx);

      TotalFitness += Chromosome->GetFitness();
      CalcWeightAndValue(Chromosome, Weight, Value);
      printf("%3u %4.0f %3d %3d ",
            ChromIdx, Chromosome->GetFitness(),
            Value, Weight);
      for (size_t BitIdx = 0;
          BitIdx < Chromosome->GetLength();
          BitIdx++) {
        printf("%1u", (*Chromosome)[BitIdx]);
      }
      printf("\n");
   }
   printf(
   "Gen, Best, Avg, Worst: %4d, %6.2f, %6.2f, %6.2f\n",
    Pop.GetGeneration(), Pop.GetBestFitness(),
    TotalFitness / ChromIdx,
    Pop.GetChromosome(ChromIdx - 1)->GetFitness());
   getchar();
}

// Check if a solution has been found. By definition
// it must have a value of ANSWER (24) and not exceed
// MAXWEIGHT (17). Since the fittest chromosome could
// violate the weight constraint FoundSolution must
// search through the population of chromosomes.

Bool FoundSolution(
   CGAPopulation& Pop)
{
   const int  ANSWER = 24;
   int        Weight;
   int        Value;

   for (size_t ChromIdx = 0;
       ChromIdx < Pop.GetPopulationSize();
       ChromIdx++) {
     CalcWeightAndValue(Pop.GetChromosome(ChromIdx),
                     Weight, Value);
     if (Weight <= MAXWEIGHT && Value == ANSWER) {
        return TRUE;
     }
   }
   return FALSE;
}

// Calculate the fitness of each chromosome by adding
// its weight to its value then subtracting a PENALITY
// for the excess weight.

float CalcFitness(
   CGAChromosome *Chromosome)
{
   const float  PENALITY = 3.0;
   int          Weight;
   int          Value;

   CalcWeightAndValue(Chromosome, Weight, Value);
   if (Weight > MAXWEIGHT) {
      return Value - PENALITY * (Weight - MAXWEIGHT);
   } else {
      return Value;
   }
}

// Calculate the weight and value of the chromosome by
// accumulating the weight and value of each item
// whose bit in the chromosome is set true.

void CalcWeightAndValue(
   CGAChromosome *Chromosome,
   int& Weight,
   int& Value)
{
   Weight = 0;
   Value  = 0;
   for (size_t Idx = 0; Idx < Chromosome->GetLength();
       Idx++) {
     if ((*Chromosome)[Idx]) {
        Weight += ItemDesc[Idx].Weight;
        Value += ItemDesc[Idx].Value;
     }
   }
}
/* End of File */