Java 根据比例和人口规模添加对象

Java adding objects according to ratios and population sizes

我的项目是一个简单的基于代理的模拟,模拟疾病的传播。模拟由agents和map组成,属于agents的classes有:CivilMedicAnimal。目前我正在尝试根据人口规模填充地图:noMedicsnoCivilsnoAnimals 以及 healthyillimmune 应该加起来等于人类和动物总人口的代理人。 确定代理人健康状况的方式很简单——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);
}

然而,每当我尝试实现模拟的其余参数时,问题就会出现:noHealthynoImmunenoIll。我似乎无法找到一个循环或条件来满足我的需求,即“公平地” 用给定的 createAgents() 方法中的所有代理填充地图。创建代理需要 6 个参数:noHealthynoImmunenoIllnoAnimalsnoCivilnoMedics。 我已经尝试了一些东西,但到目前为止正确编译和 运行s 的方法如下:我正在创建一个从 currNoImmunenoImmune 的循环 运行s ] 来自参数,每当满足条件 sumForImmune < halfNoAnimals && currNoImmune <= noImmune 时,它就会将动物添加到模拟中并增加 sumForImmunecurrNoImmune 一次。对平民 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++;
    }
}

然后有两个循环,运行 直到 noIllnoHealthy,这就是到目前为止创建代理的方式。它的工作原理并不完全像我希望的那样。作为参数传递给 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 长的健康状态数组,并用相应的 noHealthynoIllnoImmune-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]
    }   
}