熟悉java的给看看 遗传算法实现组卷 迭代不下去

aixuanuser 2015-05-18 10:01:34
package kkk.ga.com.function;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

import kkk.ga.com.entity.*;
public class MainFunction {
//知识点分布所占的权重
public static final double kpCoverage=0.5;
//难度系数所占的权重
public static final double difficulty=0.5;
/**
* 产生初始种群
* @param count 个体数量
* @param paper 期望种群
* @param problemList 题库
* @return
*/
public static List<Unit> CSZQ(int count,Paper paper,List<Problem> problemList){
List<Unit> unitList=new ArrayList<Unit>();
//获得各种题型的题数
int[] eachTypeCount=paper.getEachTypeCount();
Unit unit;
Random rand=new Random();
//为各套试卷加入试题
for(int i=0;i<count;i++){
unit=new Unit();
unit.setId(i+1);
unit.setAdaptationDegree(0.0);
//总分限制
while(paper.getTotalScore()!=unit.getSumScore()){
unit.getProblemList().clear();
List<Problem> li=new ArrayList<Problem>();
//控制题型
for(int j=0;j<eachTypeCount.length;j++){
List<Problem> oneTypeProblem=new ArrayList<Problem>();;
for(Problem p:problemList){
//选择该题型的题且试题满族试卷要求
if((p.getType()==(j+1))&&isContain(paper,p)){
oneTypeProblem.add(p);
}
}
Problem temp=new Problem();

//选择不重复的题目
for(int k=0;k<eachTypeCount[j];k++){
int index=rand.nextInt(oneTypeProblem.size()-k);
unit.getProblemList().add(oneTypeProblem.get(index));
li.add(oneTypeProblem.get(index));
unit.setSumScore(oneTypeProblem.get(index).getScore());
temp=oneTypeProblem.get(oneTypeProblem.size()-1-k);
oneTypeProblem.set(oneTypeProblem.size()-1-k,oneTypeProblem.get(index));
oneTypeProblem.set(index, temp);

}
unit.setDifficuty(li);
unit.setProblemCount(li.size());
}
}

unitList.add(unit);
}
//计算知识点覆盖率和适应度
unitList=getKPCoverage(unitList,paper);
unitList=getAdaptationDegree(unitList, paper, kpCoverage, difficulty);
return unitList;
}
/**
* 计算知识点覆盖率
* @param unitList
* @param paper
* @return
*/
public static List<Unit> getKPCoverage(List<Unit> unitList,Paper paper){
List<Integer> kp;
for(int i=0;i<unitList.size();i++){
kp=new ArrayList<Integer>();
for(int j=0;j<unitList.get(i).getProblemList().size();j++){
kp.addAll(unitList.get(i).getProblemList().get(j).getPoints());
}
//期望试卷知识点与整个个体知识点的交集
Set<Integer> set=new HashSet<Integer>(kp);
kp=new ArrayList<Integer>(set);
kp.retainAll(paper.getPoints());

unitList.get(i).setKpCoverage(kp.size()*1.00/paper.getPoints().size());
}
return unitList;
}
/**
* 计算种群适应度
* @param unitList
* @param paper
* @param kpCoverage
* @param difficulty
* @return
*/
public static List<Unit> getAdaptationDegree(List<Unit> unitList,Paper paper,double kpCoverage,double difficulty){
unitList=getKPCoverage(unitList, paper);
for(int i=0;i<unitList.size();i++){
unitList.get(i).setAdaptationDegree(1-(1-unitList.get(i).getKpCoverage())*kpCoverage-Math.abs(unitList.get(i).getDifficuty()-paper.getDifficulty())*difficulty);
}
return unitList;
}
/**
* 选择算子
* @param unitList
* @param count
* @return
*/
public static List<Unit> select(List<Unit> unitList,int count){
List<Unit> selectUnitList=new ArrayList<Unit>();
//种群个体适应度的和
double allAdaptationDegree=0.0;
for(int i=0;i<unitList.size();i++){
allAdaptationDegree+=unitList.get(i).getAdaptationDegree();
}
Random rand=new Random();
while(selectUnitList.size()!=count){
double degree=0.0;
double randDegree=(rand.nextInt(99)+1)*0.01*allAdaptationDegree;
//选择符合要求的个体
for(int j=0;j<unitList.size();j++){
degree+=unitList.get(j).getAdaptationDegree();
if(degree>=randDegree){
//不重复选择
if(!selectUnitList.contains(unitList.get(j))){
selectUnitList.add(unitList.get(j));
}
break;
}
}
}
return selectUnitList;

}
/**
* 交叉算子
* @param unitList
* @param count
* @param papere
* @return
*/
public static List<Unit> cross(List<Unit> unitList,int count,Paper paper){
List<Unit> crossedUnitList=new ArrayList<Unit>();
Random rand=new Random();
while(crossedUnitList.size()!=count){
//随机选择两个个体
int indexone=rand.nextInt(unitList.size());
int indextow=rand.nextInt(unitList.size());
Unit unitone;
Unit unittow;
if(indexone!=indextow){
unitone=unitList.get(indexone);
unittow=unitList.get(indextow);
//选择交叉位置
int crossPosition=rand.nextInt(51-2);
//保证交叉题目的分数和相同
double scoreone=unitone.getProblemList().get(crossPosition).getScore()+unitone.getProblemList().get(crossPosition+1).getScore();
double scoretow=unittow.getProblemList().get(crossPosition).getScore()+unittow.getProblemList().get(crossPosition+1).getScore();
if(scoreone==scoretow){
//两个新个体
Unit unitNewOne=new Unit();
unitNewOne.getProblemList().addAll(unitone.getProblemList());
Unit unitNewTow=new Unit();
unitNewTow.getProblemList().addAll(unittow.getProblemList());
//交换交叉位置后两道题
for(int i=crossPosition;i<crossPosition+2;i++){
unitNewOne.getProblemList().add(i,new Problem(unittow.getProblemList().get(i)));
unitNewTow.getProblemList().add(i,new Problem(unitone.getProblemList().get(i)));
}
unitNewOne.setId(crossedUnitList.size());
unitNewTow.setId(unitNewOne.getId()+1);
//添加到新种群
if(crossedUnitList.size()<count){
crossedUnitList.add(unitNewOne);
}if(crossedUnitList.size()<count){
crossedUnitList.add(unitNewTow);
}
}
}

}
crossedUnitList=getKPCoverage(crossedUnitList, paper);
crossedUnitList=getAdaptationDegree(crossedUnitList, paper, kpCoverage, difficulty);
return crossedUnitList;
}
/**
* 变异算子
* @param unitList
* @param problemList
* @param paper
* @return
*/
public static List<Unit> change(List<Unit> unitList,List<Problem> problemList,Paper paper){
Random rand=new Random();
int index=0;
for(int i=0;i<unitList.size();i++){
//随机选择一道题
index=rand.nextInt(unitList.get(i).getProblemList().size());
Problem temp=unitList.get(i).getProblemList().get(index);
Problem problem=new Problem();
//得到这道题的知识点
for(int j=0;j<temp.getPoints().size();j++){
if(paper.getPoints().contains(temp.getPoints().get(j))){
problem.getPoints().add(temp.getPoints().get(j));
}
}
//从数据库中选择包含此题知识点的同种类型同分数不同题号试题
List<Problem> smallDB=new ArrayList<Problem>();
for(Problem p:problemList){
if(isContain(paper,problem)&&(p.getScore()==temp.getScore())&&(p.getType()==temp.getType())&&(p.getId()!=temp.getId())){
smallDB.add(p);
}
}
//从符合要求的试题中随机选择一个
if(smallDB.size()>0){
int indexo=rand.nextInt(smallDB.size());
System.out.println(smallDB.size());
unitList.get(i).getProblemList().set(index, smallDB.get(indexo));
}
}
unitList=getKPCoverage(unitList, paper);
unitList=getAdaptationDegree(unitList, paper, kpCoverage, difficulty);
return unitList;
}
/**
* 题目知识点是否符合试卷要求
* @param paper
* @param problem
* @return
* @return
*/
private static boolean isContain(Paper paper,Problem problem){
for(int i=0;i<problem.getPoints().size();i++){
if(paper.getPoints().contains(problem.getPoints().get(i))){
return true;
}
}
return false;
}
}
...全文
360 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wangguoguo123 2016-04-21
  • 打赏
  • 举报
回复
请问这个功能现在实现了吗?
engourdi 2015-05-18
  • 打赏
  • 举报
回复
迭代不下去的原因是? 是不是交叉算子的概率或者基因变异的概率不大导致的不收敛?
aixuanuser 2015-05-18
  • 打赏
  • 举报
回复
测试类:
package kkk.ga.com.function;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import kkk.ga.com.entity.*;
/**
 * 
 * 测试类
 *
 */
public class Test {
	public static void main(String[] args) {
		//模拟数据库
		DB db=new DB();
		//试卷试题
		Paper paper=new Paper();
		paper.setId(1);
		//试卷设置总分
		paper.setTotalScore(100);
		paper.setDifficulty(0.72);
		//试卷设置知识点
		List<Integer> points=new ArrayList<Integer>();
		for(int i=1;i<=81;i+=2){
			points.add(i);
		}
		//试卷设置题型的个数
		int[] eachTypeCount=new int[]{20,5,10,10,6};
		paper.setPoints(points);
		paper.setEachTypeCount(eachTypeCount);
		int count=0;
		//试卷期望值
		double expand=0.94;
		//迭代次数
		int runCount=50;
		//产生初始群体
		List<Unit> unitList=MainFunction.CSZQ(20, paper, db.getProblemDB());
		System.out.println("------------遗传算符组卷系统--------------");
		System.out.println("初始种群:");
		showUnit(unitList.get(count));
		System.out.println("------------迭代开始--------------------");
		while(!isEnd(unitList,expand)){
			System.out.println("在第"+(++count)+"代未得到结果");
			if(count>=runCount){
				System.out.println("计算"+runCount+"代仍未得到结果,请重新设置条件");
				break;
			}
			unitList=MainFunction.select(unitList,10);
			unitList=MainFunction.cross(unitList, 20, paper);
			if(isEnd(unitList,expand)){
				break;
			}
			unitList=MainFunction.change(unitList, db.getProblemDB(), paper);
		}
		if(count<runCount){
			System.out.println("在第"+(++count)+"代得到结果");
			System.out.println("期望试卷难度"+paper.getDifficulty());
			showResult(unitList,expand);
		}
	}
	/**
	 * 是否到达目标
	 * @param unitList
	 * @param endcondition
	 * @return
	 */
	public static boolean isEnd(List<Unit> unitList,double endcondition){
		if(unitList.size()>0){
			for(int i=0;i<unitList.size();i++){
				if(unitList.get(i).getAdaptationDegree()>=endcondition){
					return true;
				}
			}
		}
		return false;
	}
	/**
	 * 显示结果
	 * @param unitList
	 * @param expand
	 */
	public static void showResult(List<Unit> unitList,double expand){
		Collections.sort(unitList,new Unit());
		for(Unit unit:unitList){
			if(unit.getAdaptationDegree()>=expand){
				System.out.println("第"+unit.getId()+"套");
				System.out.println("题目数量              知识点分布                           难度系数                              适应度");
				System.out.println(unit.getProblemCount()+"         "+unit.getKpCoverage()+"           "+unit.getDifficuty()+"          "+unit.getAdaptationDegree());
			}
		}
	}
	/**
	 * 显示种群个体题目编号
	 * @param u
	 */
	public static void showUnit(Unit u){
		System.out.println("编号                       知识点分布                           难度系数");
		System.out.println(u.getId()+"          "+u.getKpCoverage()+"          "+u.getDifficuty(u.getProblemList()));
		for(int i=0;i<u.getProblemList().size();i++){
			System.out.print(u.getProblemList().get(i).getId()+"  ");
		}
		System.out.println();
	}
}
试卷实体
package kkk.ga.com.entity;

import java.util.List;
/**
 * 试卷实体
 *
 */
public class Paper {
	private int id;//试卷编号
	private double difficulty;//难度系数
	private int totalScore;//总分
	private List<Integer> points;//知识点
	private int[] eachTypeCount;//各种题型题数
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public double getDifficulty() {
		return difficulty;
	}
	public void setDifficulty(double difficulty) {
		this.difficulty = difficulty;
	}
	public int getTotalScore() {
		return totalScore;
	}
	public void setTotalScore(int totalScore) {
		this.totalScore = totalScore;
	}
	public List<Integer> getPoints() {
		return points;
	}
	public void setPoints(List<Integer> points) {
		this.points = points;
	}
	public int[] getEachTypeCount() {
		return eachTypeCount;
	}
	public void setEachTypeCount(int[] eachTypeCount) {
		this.eachTypeCount = eachTypeCount;
	}
	
}
试题库
package kkk.ga.com.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
 * 试题库
 *
 */
public class DB {
	//题库
	private List<Problem> problemDB;
	public DB(){
		problemDB=new ArrayList<Problem>();
		Problem model;
		Random rand=new Random();
		List<Integer> points;
		for(int i=1;i<=5000;i++){
			model=new Problem();
			model.setId(i);
			//难度设置
			model.setDifficulty((rand.nextInt(71)+30)*0.01);
			//单选题1分
			if(i<1001){
				model.setScore(1);
				model.setType(1);
			}
			//多选题2分
			if(i>1000&&i<2001){
				model.setScore(2);
				model.setType(2);
			}
			//判断题2分
			if(i>2000&&i<3001){
				model.setType(3);
				model.setScore(2);
			}
			//填空题2分
			if(i>3000&&i<4001){
				model.setType(4);
//				model.setScore(rand.nextInt(4)+1);
				model.setScore(2);
			}
			//问答题5分
			if(i>4000&&i<50001){
				model.setType(5);
//				double diff=model.getDifficulty();
//				int score;
//				if(diff>0.3){
//					score=(int)diff*10;
//				}else{
//					score=3;
//				}
//				model.setScore(score);
				model.setScore(5);
			}
			points=new ArrayList<Integer>();
			int count=rand.nextInt(4)+1;
			for(int j=0;j<count;j++){
				points.add(rand.nextInt(99)+1);
			}
			model.setPoints(points);
			problemDB.add(model);
		}
	}

	public List<Problem> getProblemDB() {
		return problemDB;
	}

	public void setProblemDB(List<Problem> problemDB) {
		this.problemDB = problemDB;
	}
}
问题实体
package kkk.ga.com.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
 * 试题库
 *
 */
public class DB {
	//题库
	private List<Problem> problemDB;
	public DB(){
		problemDB=new ArrayList<Problem>();
		Problem model;
		Random rand=new Random();
		List<Integer> points;
		for(int i=1;i<=5000;i++){
			model=new Problem();
			model.setId(i);
			//难度设置
			model.setDifficulty((rand.nextInt(71)+30)*0.01);
			//单选题1分
			if(i<1001){
				model.setScore(1);
				model.setType(1);
			}
			//多选题2分
			if(i>1000&&i<2001){
				model.setScore(2);
				model.setType(2);
			}
			//判断题2分
			if(i>2000&&i<3001){
				model.setType(3);
				model.setScore(2);
			}
			//填空题2分
			if(i>3000&&i<4001){
				model.setType(4);
//				model.setScore(rand.nextInt(4)+1);
				model.setScore(2);
			}
			//问答题5分
			if(i>4000&&i<50001){
				model.setType(5);
//				double diff=model.getDifficulty();
//				int score;
//				if(diff>0.3){
//					score=(int)diff*10;
//				}else{
//					score=3;
//				}
//				model.setScore(score);
				model.setScore(5);
			}
			points=new ArrayList<Integer>();
			int count=rand.nextInt(4)+1;
			for(int j=0;j<count;j++){
				points.add(rand.nextInt(99)+1);
			}
			model.setPoints(points);
			problemDB.add(model);
		}
	}

	public List<Problem> getProblemDB() {
		return problemDB;
	}

	public void setProblemDB(List<Problem> problemDB) {
		this.problemDB = problemDB;
	}
}
种群个体实体
package kkk.ga.com.entity;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
 * 种群个体实体类
 * 
 *
 */
public class Unit implements Comparator<Unit>{
	private int id;//试卷id
	private double adaptationDegree;//试卷适应度
	private List<Problem> problemList;//试卷题目
	private double kpCoverage;//知识点分布
	private int problemCount;//题目数量
	private int sumScore;//试卷总分
	private double difficuty;//难度系数
	public Unit(){
		id=0;
		adaptationDegree=0.0;
		kpCoverage=0.0;
		problemList=new ArrayList<Problem>();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public double getAdaptationDegree() {
		return adaptationDegree;
	}
	public void setAdaptationDegree(double adaptationDegree) {
		this.adaptationDegree = adaptationDegree;
	}
	public List<Problem> getProblemList() {
		return problemList;
	}
	public void setProblemList(List<Problem> problemList) {
		this.problemList = problemList;
	}
	public double getKpCoverage() {
		return kpCoverage;
	}
	public void setKpCoverage(double kpCoverage) {
		this.kpCoverage = kpCoverage;
	}
	public int getProblemCount(List<Problem> problemList) {
		return problemList.size();
	}
	public int getProblemCount() {
		return problemCount;
	}
	public void setProblemCount(int problkemCount) {
		this.problemCount = problkemCount;
	}
	public int getSumScore(List<Problem> problemList) {
		int sum=0;
		for(int i=0;i<problemList.size();i++){
			sum+=problemList.get(i).getScore();
		}
		return sum;
	}
	public int getSumScore() {
	   return sumScore;
	}
	public void setSumScore(int sumScore) {
		this.sumScore += sumScore;
	}
	public double getDifficuty(List<Problem> problemList) {
		double diff=0.0;
		for(int i=0;i<problemList.size();i++){
			diff+=problemList.get(i).getDifficulty()*problemList.get(i).getScore();
		}
		return diff/sumScore;
	}

public double getDifficuty() {
	return difficuty;
}
	public void setDifficuty(List<Problem> problemList) {
		double diff=0.0;
		for(int i=0;i<problemList.size();i++){
			diff+=problemList.get(i).getDifficulty()*problemList.get(i).getScore();
		}
		this.difficuty=diff/sumScore;
	}
	public int compare(Unit o1, Unit o2) {
		if(o1.getId()<o2.getId()){
			return 0;
		}
		return 1;
	}
	
}

50,545

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧