java实现遗传算法组卷功能

      遗传算法中通过模仿生物界生物遗传方式,实现的算法,本次组卷生成案例主要使用到了其中一部分概念:染色体编码传递、初始化种群、杂交、变异、进化、最优适应者。

   个人理解上可能有些地方比较欠缺,望大家指正!!

1. 染色体编码传递

       采用实数编码作为替代,将试题id作为基因,试卷和染色体建立映射关系,由于题库仅仅含有选择题,

则没有题型分类一说,则当组套10道题的试卷,组卷结果:

       (2,33,22,11,44,35,6,4,445,29)【注:如果有题型一说,则可以分类[1,2,44 | 3,33| 12 ,44 ]】

for (SubjectInfo subjectInfo : subjectInfoList) {

         list.add(subjectInfo.getSubjectId());

      }

2. 初始化种群

对应方法:GeneticUtil.init();

初始化试卷时不采取完全随机的方式.通过分析不难发现,组卷主要有题型、数量、总分和难度这四个约束条件,在初始化种群的时候,我们可以根据组卷规则随机产生指定数量的题型。

其中:

组卷规则:(注:可自行定义规则)

设置种群大小,由于题库量太大,适当取出一部分题型,优化检索速度。

//种群大小(当种群量大于40倍我们取的题量时,我们可以将题量缩小至20倍)
		public static int INIT_SIZE=40;
		//取得种群量
	public static int GET_SIZE=20;


// 改造种群大小
		if(list.size()>INIT_SIZE*subjectSum)
		{
			for(int i=0;i

3. 杂交

       对应方法:GeneticUtil. hybrid ();

       正常逻辑杂交需要有双亲,但是由于我们是基于题库为种群,所以双亲指定为取出的种群。当杂交时出现重复,我们可以在大种群下取出新的数据

//两点交叉(start,end)
		// 上一代start至end的基因会遗传到下一代
		for (int i = start; i < end; i++) {
			list.set(i, subjectIds.get(i));
		}
		// 子代继承未继承的父代基因
		// 查重
		for (int j = 0; j < start; j++) {
			if(!list.contains(subjectIds.get(j)))
			{
				list.set(j, subjectIds.get(j));
			}
			else{
				//重复了就获取新基因
				Integer newIds=getNewId(list,subjectIds);
				list.set(j, newIds);
			}
		}
		for(int i=end;i

4. 变异

 

方法:GeneticUtil .variation();

设置一定的概率使基因变异:

基因变异的出现增加了种群的多样性.在本系统中,每个个体的每个基因都有变异的机会,如果随机概率小于变异概率,那么基因就可以突变.突变基因的原则为:与原题的同题型、同分数且同知识点的试题.有研究表明,对于变异概率的选择,在0.1-0.001之间最佳,本例中选取了0.085作为变异概率

//变异概率:85%
	public static  int variationRate=85;
for (int i = 0; i < subjectIds.size(); i++) {
			if (Math.random() * 100 > variationRate) {
				
				//且不能获取此变异题目
				Integer variationId=(int) (Math.random() * subjectIds.size());
				while(i==variationId)
				{
					variationId=(int) (Math.random() * subjectIds.size());
				}
				subjectIds.set(i, subjectIds.get(variationId));
//				System.out.println("发生变异!得到新基因:"+variationId);
			}
		}

 

5. 择优,进化

方法:preferential()

 

系统缺乏缺乏精细数据来触发进化规则,目前采用10%淘汰规则,淘汰个体。

for (int i = 0; i < selectSize - 1; i++) {
			for (int j = i + 1; j < selectSize; j++) {
				tmp = list.get(i);
				list.set(i, list.get(j));
				list.set(j, tmp);
			}
		}
			for (int i = 0; i < (selectSize - 1) / 10; i++) // 淘汰10%
			{
				list.set(selectSize - 1 - i, list.get(i));
			}

6. 最优适应者

方法:getExcellent()

根据一代代遗传,取出在每次遗传产生的后代,最终适应下来的个体存活,根据存活个体数量,取出存活前N题,组成最优试卷。

List finalResult=new ArrayList<>();
//		System.out.println("获取最终代基因");
		int i=0;//统计次数
		TreeMap tm=new TreeMap<>();
		for(int x = 0;x < newList.size();x++) {//循环遍历数组
			Integer obj=newList.get(x);
				if(!tm.containsKey(obj)) {//是否在tm中
					tm.put(obj, 1);//不在tm中则初始化其value值为1
				} else {//在tm中
					int count = tm.get(obj)+1;//其出现次数增加1
				    tm.put(obj,count);//在tm中则其value值为count
			    }
		}
		List> list = new ArrayList>(tm.entrySet());//将map转换为list便于进行排序
		//构造一个排序比较器
		Collections.sort (list,new Comparator>() {//使用Collections.sort()方法对这个list进行排序
			public int compare(Entry o1,Entry o2) {
				//实现降序排序
				int z = o2.getValue()-o1.getValue();
                return z;
			}
		});
		for(Map.Entry mapping:list) {//遍历list
			if(i++

 

通过调用build()方法,执行遗传算法组卷。

// 生成
	public static List build(List subjects, int subjectSum, int subjectEasy) {
		if(subjects.size() subjectIds = (List) init(subjects,subjectSum);
		// 2.适应度:试题数量、难度
		int count = 0;
		int easy = 0;
		List newList = new ArrayList();
		while (count < subjectSum && easy <=subjectEasy) {
//			System.out.println("第"+(count+1)+"代");
			// 3.杂交
			newList = hybrid(subjectIds);
			// 4.变异
			newList = variation(newList);
			// 5.择优
			newList = preferential(newList);
			count++;
			subjectIds=newList;
			
		}
		//6.在最后一代获取最优基因
		return getExcellent(subjectSum,newList);
	}

 

你可能感兴趣的:(JAVA,算法)