50,545
社区成员
发帖
与我相关
我的任务
分享
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;
}
}
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;
}
}