0

我正在使用遗传算法进行最后一年的项目,为我的大学设计一组时间表。

我遇到了 1 个阻止我前进的错误。我收到以下错误。

 Exception in thread "main" java.lang.NullPointerException
at LunchTimeFree.calculateViolations(LunchTimeFree.java:36)
at FitnessFunction.calculateFitnesScore(FitnessFunction.java:34)
at Main.main(Main.java:19)

但这对我来说没有任何意义:在那一行是这行代码:

    int time = c.genes[i].time;

它将变量时间设置为我染色体中某个基因的时间值。我已经调试它并在打印我的时间变量和 c.genes[i].time 变量后插入了一个 println 语句,它们都被初始化为变量,即 time = 1 或 2 等。

我不明白问题是什么。请问有人可以帮我吗?!

public class LunchTimeFree extends constraintInterface {

    Chromosome c;

    public LunchTimeFree(Chromosome chromo){
        c = chromo;
    }

    @Override
    public double calculateViolations() {     
    double violations=0;    

    int i = 0; 
    int y = c.getLength();

    while(i <= y-1 )
    {
        int time = c.genes[i].time;

        if (time >= 16 && time <= 25)   {                           
            violations = violations + 1;        
                            } 
                i++;
    }      

    return violations*this.weight;

    }
}

public class ChromosomeFactory
{

Chromosome c;

 public ChromosomeFactory(int l)
 {

 c = new Chromosome(l);

 DummyDatabase da = new DummyDatabase();

 int numOfLectures = da.GetNumLectures();

  int i=0;

  while(i<=numOfLectures-1)
   {

   int lecture = da.getLecture(i);   

   int r = da.Rooms[(int)(Math.random() * da.Rooms.length)];
   int t = da.TimeSlots[(int)(Math.random() * da.TimeSlots.length)]; 

   Gene g = new Gene(lecture,lecture,r,t);

    c.genes[i] = g;
           System.out.println(""+this.c.genes[i].teacher+","+this.c.genes[i].lecture+","+this.c.genes[i].room+","+this.c.genes[i].time+"");
    i++;
    }
   }  
   }

 public class FitnessFunction 
{
Chromosome c;

public FitnessFunction(Chromosome newChromo)  {
    c = newChromo;
}

public double calculateFitnesScore() {

    LunchTimeFree ltf = new LunchTimeFree(c);

    ltf.setWeight(0.01);

    double violationScore =ltf.calculateViolations();

    double score = (1/(1 + violationScore));

    return score;

  } 

 public class Chromosome 
 {

Gene[] genes;



public Chromosome(int l)
{
genes = new Gene[l]; 

}

public int getLength()
{
return genes.length;
}



}

public class Gene 
{
public int teacher;
public int lecture;
public int room;
public int time;


public Gene(int t,int l, int r, int time)
{

this.teacher=t;    
this.lecture=l;
this.room=r;
this.time=time;

}



}

public class DummyDatabase implements DatabaseAccessor
{

 int[] Lecturers = { 1,2,3,4,5,6,7,8,9 };
  int[] Lectures = { 1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18,19} ;

  int[] TimeSlots =      {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};

    int[] Rooms = {1,2,3,4,5,6,7,8,9,10};





@Override
public int GetRoom(int entry) {

    return this.Rooms[entry];
}

@Override
public int GetNumLectures() {
    return this.Lectures.length;
}

@Override
public int getTeacher(int entry) {
    return this.Lecturers[entry];
}

@Override
public int getLecture(int entry) {
    return this.Lectures[entry];
}

@Override
public int getNumRooms() {
    return this.Rooms.length;
}

}

4

2 回答 2

2

c您的值中的一个或一个为c.genes[i]空。

您正在尝试执行操作或请求为空的属性。所以你得到一个NullPointerException. 如果您使用的是 Eclipse 或您选择的其他 IDE,您可以对其进行调试并查看什么为 null 或发布相关代码以便我们猜测。也许你的循环i有缺陷。

于 2012-11-10T21:22:03.130 回答
0

首先:拆分

int time = c.genes[i].time;

进入

final Gene[] allGenes = c.genes;
final Gene aGene = allGenes[i];
final int time = aGene.time;

应该准确地向您显示堆栈跟踪中哪些引用为空。这可能有助于缩小错误的位置。

除此之外,这可能是一个很长的电话,但您发布的代码中的所有其他内容看起来都不错:

在您的 Chromosome 类中是否返回数组getLength的长度?genes还是阵列中设定基因的数量?如果基因数组未完全填充并getLength指示填充数组槽的(不正确)数量,则 while 循环可能会过冲并命中数组中的空值。请注意,您使用 int 变量l作为 ChromosomeFactory 中 Chromosome 的构造函数参数,但将基因数组填充到numOfLectures. 如果l用于设置 Chromosome 中基因阵列的大小lnumOfLectures不同,您可能会遇到问题。差异将用数组中的空值填充。

int y = c.getLength();
while(i <= y-1 )
{
    int time = c.genes[i].time;
    if (time >= 16 && time <= 25)   {                           
        violations = violations + 1;        
    } 
    i++;
}

还可以考虑用 for 循环替换它

for (int i = 0; i < c.getLength(); i++) {
   int time = c.genes[i].time;
   if (time >= 16 && time <= 25) {                           
      violations++;   
   }
}

For 循环应该是首选,因为它们最小化循环变量的范围,处理循环变量的增加并且更容易掌握。还可以考虑使用 Collection 类之一而不是数组。并强烈考虑使用 getter/setter 将所有实例变量更改为私有可见性。

如果这不是您必须向我们展示更多代码的原因,例如 Chromoson 类以及您的基因阵列的结构。

于 2012-11-10T23:02:47.653 回答