Java 根据比例和人口规模添加对象
Java adding objects according to ratios and population sizes
我的项目是一个简单的基于代理的模拟,模拟疾病的传播。模拟由agents和map组成,属于agents的classes有:Civil
、Medic
和Animal
。目前我正在尝试根据人口规模填充地图:noMedics
、noCivils
、noAnimals
以及 healthy
、ill
和 immune
应该加起来等于人类和动物总人口的代理人。
确定代理人健康状况的方式很简单——random.nextInt(3)
、0
健康、1
生病和 2
免疫。我通常使用其中一种代理 class 填充地图的方式如下:
for (int i = 0; i < noAnimals; i++) {
IAgent animal = new Animal(map, rnd.nextInt(3), 2, 3);
agentList.add(animal);
}
然而,每当我尝试实现模拟的其余参数时,问题就会出现:noHealthy
、noImmune
、noIll
。我似乎无法找到一个循环或条件来满足我的需求,即“公平地” 用给定的 createAgents() 方法中的所有代理填充地图。创建代理需要 6 个参数:noHealthy
、noImmune
、noIll
、noAnimals
、noCivil
、noMedics
。
我已经尝试了一些东西,但到目前为止正确编译和 运行s 的方法如下:我正在创建一个从 currNoImmune
到 noImmune
的循环 运行s ] 来自参数,每当满足条件 sumForImmune < halfNoAnimals && currNoImmune <= noImmune
时,它就会将动物添加到模拟中并增加 sumForImmune
和 currNoImmune
一次。对平民 sumForImmune >= halfNoAnimals && currNoImmune <= noImmune
进行反向检查,增加相同的变量并将平民添加到模拟中。这是我描述的方法的代码:
while (sumForImmune <= noImmune) {
if (sumForImmune < halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Animal(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
if (sumForImmune >= halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Civil(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
}
然后有两个循环,运行 直到 noIll
和 noHealthy
,这就是到目前为止创建代理的方式。它的工作原理并不完全像我希望的那样。作为参数传递给 createAgents()
的数字不会反映在所有可能输入的地图上。我意识到这项任务超出了我的能力范围,因为我花了很多时间试图弄清楚它,尽管如此我仍然很想了解它是如何完成的以及如何实现的。
我所说的公平的意思是尽可能接近50:50——每当用户输入不奇数的3免疫时, 1 个动物和 2 个民事代理人应该有 2 个免疫平民和 1 个免疫动物。同样的逻辑应该扩展到缺少的参数,即健康和生病的代理人。
编辑:
我上面写的乱七八糟的意思是我需要一个算法来根据 noHealthy:noIll:noImmune 确定的平民人口 (noCivils) 和动物人口 (noAnimals) 的比率来放置代理。考虑到医生已经免疫,所以 noImmune 应该减少模拟中存在的医生数量。
编辑2:
我稍微研究了一下数学,这就是我设法得到的结果,但是 1:1:1 比率仍然存在问题,因为它们没有给出给定人口规模的预期结果。还有一件事是这还没有考虑到医疗人员,只是为了不打乱比率并使逻辑更容易一些。
void createAgents(int noAnimals, int noCivil, noIll, noImmune, noHealthy) {
double sumTheRatio = noHealthy + noIll + noImmune;
double animalsPart = noAnimals / sumTheRatio;
double numHealthyAnimals = noHealthy * animalsPart;
double numIllAnimals = noIll * animalsPart;
double numImmuneAnimals = noImmune * animalsPart;
double civilPart = noCivil / sumTheRatio;
double numHealthyCivil = noHealthy * civilPart;
double numIllCivil = noIll * civilPart;
double numImmuneCivil = noImmune * civilPart;
//The only issue is when ratios of agent health states are 1:1:1
//- for example for ratios like 18:18:18 and 26 civilians 28 animals will
// give 27 agents for both animals and civilians (+/- 1 from expected numbers)
//- another example 7:7:7 and 1 civil and 20 animals will give 0 agents
// for civilians and 21 agents for animals (+/- 1 from expected numbers)
//- another example 14:14:14 and 38 civilians and 4 animals will give 39
// agents for civilians and 3 agents for animals (+/- 1 from expected numbers)
System.out.println("Rounded ratio number for animals:"
+ "\n healthy - " + Math.round(numHealthyAnimals)
+ " ill - " + Math.round(numIllAnimals)
+ " immune - " + Math.round(numImmuneAnimals));
System.out.println("Rounded ratio number for civilians:"
+ "\n healthy - " + Math.round(numHealthyCivil)
+ " ill - " + Math.round(numIllCivil)
+ " immune - " + Math.round(numImmuneCivil));
}
然后简单地迭代到:Math.round(numHealthyCivil)
、Math.round(numIllCivil)
、Math.round(numImmuneCivil)
并在每次迭代中添加相应的代理。
有没有办法调整这个算法,或者当比率为 1:1:1?
时,可能需要不同的函数来负责代理的创建
你说医生应该有免疫健康状态。因此,剩下的问题是为平民和动物分配健康、生病或免疫的健康状态,以便:
noCivils + noAnimals + noMedics = noHealthy + noIll + noImmune
一种方法是创建一个 noCivils + noAnimals
长的健康状态数组,并用相应的 noHealthy
、noIll
和 noImmune-noMedics
元素填充它输入 (0, 1, 2
)。然后,您随机打乱这个数组,并使用这些值依次为平民和动物分配健康状况。
这里有一些 Java 代码来说明:
static void createAgents(int noHealthy, int noImmune, int noIll,
int noAnimals, int noCivil, int noMedics)
{
for (int i=0; i<noMedics; i++) {
// create and add Medic, with health status Immune
}
int remImmune = noImmune - noMedics;
assert noCivil + noAnimals == noHealthy + noIll + remImmune;
int caAgents = noCivil + noAnimals;
Integer[] agentStatus = new Integer[caAgents];
Arrays.fill(agentStatus, 0, noHealthy, 0);
Arrays.fill(agentStatus, noHealthy, noHealthy+noIll, 1);
Arrays.fill(agentStatus, noHealthy+noIll, noHealthy+noIll+remImmune, 2);
Collections.shuffle(Arrays.asList(agentStatus));
int j = 0;
for (int i=0; i<noAnimals; i++, j++) {
// create and add Animal, with health status status[j]
}
for (int i=0; i<noCivil; i++, j++) {
// create and add Civilian, with health status status[j]
}
}
我的项目是一个简单的基于代理的模拟,模拟疾病的传播。模拟由agents和map组成,属于agents的classes有:Civil
、Medic
和Animal
。目前我正在尝试根据人口规模填充地图:noMedics
、noCivils
、noAnimals
以及 healthy
、ill
和 immune
应该加起来等于人类和动物总人口的代理人。
确定代理人健康状况的方式很简单——random.nextInt(3)
、0
健康、1
生病和 2
免疫。我通常使用其中一种代理 class 填充地图的方式如下:
for (int i = 0; i < noAnimals; i++) {
IAgent animal = new Animal(map, rnd.nextInt(3), 2, 3);
agentList.add(animal);
}
然而,每当我尝试实现模拟的其余参数时,问题就会出现:noHealthy
、noImmune
、noIll
。我似乎无法找到一个循环或条件来满足我的需求,即“公平地” 用给定的 createAgents() 方法中的所有代理填充地图。创建代理需要 6 个参数:noHealthy
、noImmune
、noIll
、noAnimals
、noCivil
、noMedics
。
我已经尝试了一些东西,但到目前为止正确编译和 运行s 的方法如下:我正在创建一个从 currNoImmune
到 noImmune
的循环 运行s ] 来自参数,每当满足条件 sumForImmune < halfNoAnimals && currNoImmune <= noImmune
时,它就会将动物添加到模拟中并增加 sumForImmune
和 currNoImmune
一次。对平民 sumForImmune >= halfNoAnimals && currNoImmune <= noImmune
进行反向检查,增加相同的变量并将平民添加到模拟中。这是我描述的方法的代码:
while (sumForImmune <= noImmune) {
if (sumForImmune < halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Animal(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
if (sumForImmune >= halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Civil(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
}
然后有两个循环,运行 直到 noIll
和 noHealthy
,这就是到目前为止创建代理的方式。它的工作原理并不完全像我希望的那样。作为参数传递给 createAgents()
的数字不会反映在所有可能输入的地图上。我意识到这项任务超出了我的能力范围,因为我花了很多时间试图弄清楚它,尽管如此我仍然很想了解它是如何完成的以及如何实现的。
我所说的公平的意思是尽可能接近50:50——每当用户输入不奇数的3免疫时, 1 个动物和 2 个民事代理人应该有 2 个免疫平民和 1 个免疫动物。同样的逻辑应该扩展到缺少的参数,即健康和生病的代理人。
编辑: 我上面写的乱七八糟的意思是我需要一个算法来根据 noHealthy:noIll:noImmune 确定的平民人口 (noCivils) 和动物人口 (noAnimals) 的比率来放置代理。考虑到医生已经免疫,所以 noImmune 应该减少模拟中存在的医生数量。
编辑2: 我稍微研究了一下数学,这就是我设法得到的结果,但是 1:1:1 比率仍然存在问题,因为它们没有给出给定人口规模的预期结果。还有一件事是这还没有考虑到医疗人员,只是为了不打乱比率并使逻辑更容易一些。
void createAgents(int noAnimals, int noCivil, noIll, noImmune, noHealthy) {
double sumTheRatio = noHealthy + noIll + noImmune;
double animalsPart = noAnimals / sumTheRatio;
double numHealthyAnimals = noHealthy * animalsPart;
double numIllAnimals = noIll * animalsPart;
double numImmuneAnimals = noImmune * animalsPart;
double civilPart = noCivil / sumTheRatio;
double numHealthyCivil = noHealthy * civilPart;
double numIllCivil = noIll * civilPart;
double numImmuneCivil = noImmune * civilPart;
//The only issue is when ratios of agent health states are 1:1:1
//- for example for ratios like 18:18:18 and 26 civilians 28 animals will
// give 27 agents for both animals and civilians (+/- 1 from expected numbers)
//- another example 7:7:7 and 1 civil and 20 animals will give 0 agents
// for civilians and 21 agents for animals (+/- 1 from expected numbers)
//- another example 14:14:14 and 38 civilians and 4 animals will give 39
// agents for civilians and 3 agents for animals (+/- 1 from expected numbers)
System.out.println("Rounded ratio number for animals:"
+ "\n healthy - " + Math.round(numHealthyAnimals)
+ " ill - " + Math.round(numIllAnimals)
+ " immune - " + Math.round(numImmuneAnimals));
System.out.println("Rounded ratio number for civilians:"
+ "\n healthy - " + Math.round(numHealthyCivil)
+ " ill - " + Math.round(numIllCivil)
+ " immune - " + Math.round(numImmuneCivil));
}
然后简单地迭代到:Math.round(numHealthyCivil)
、Math.round(numIllCivil)
、Math.round(numImmuneCivil)
并在每次迭代中添加相应的代理。
有没有办法调整这个算法,或者当比率为 1:1:1?
你说医生应该有免疫健康状态。因此,剩下的问题是为平民和动物分配健康、生病或免疫的健康状态,以便:
noCivils + noAnimals + noMedics = noHealthy + noIll + noImmune
一种方法是创建一个 noCivils + noAnimals
长的健康状态数组,并用相应的 noHealthy
、noIll
和 noImmune-noMedics
元素填充它输入 (0, 1, 2
)。然后,您随机打乱这个数组,并使用这些值依次为平民和动物分配健康状况。
这里有一些 Java 代码来说明:
static void createAgents(int noHealthy, int noImmune, int noIll,
int noAnimals, int noCivil, int noMedics)
{
for (int i=0; i<noMedics; i++) {
// create and add Medic, with health status Immune
}
int remImmune = noImmune - noMedics;
assert noCivil + noAnimals == noHealthy + noIll + remImmune;
int caAgents = noCivil + noAnimals;
Integer[] agentStatus = new Integer[caAgents];
Arrays.fill(agentStatus, 0, noHealthy, 0);
Arrays.fill(agentStatus, noHealthy, noHealthy+noIll, 1);
Arrays.fill(agentStatus, noHealthy+noIll, noHealthy+noIll+remImmune, 2);
Collections.shuffle(Arrays.asList(agentStatus));
int j = 0;
for (int i=0; i<noAnimals; i++, j++) {
// create and add Animal, with health status status[j]
}
for (int i=0; i<noCivil; i++, j++) {
// create and add Civilian, with health status status[j]
}
}