class CheatingStudents {

    public static double runWithBernoulli(int numberOfStudents, int numberOfYesAnswers) {

        int numberOfSamples = 2000;
        UniformVertex probabilityOfCheating = new UniformVertex(0.0, 1.0);
        BooleanVertex studentCheated = new BernoulliVertex(new long[]{numberOfStudents}, probabilityOfCheating);
        BooleanVertex answerIsTrue = new BernoulliVertex(new long[]{numberOfStudents}, 0.5);
        BooleanVertex randomAnswer = new BernoulliVertex(new long[]{numberOfStudents}, 0.5);

        DoubleVertex answer = If.isTrue(answerIsTrue)
            .then(
                If.isTrue(studentCheated)
                    .then(1.0)
                    .orElse(0.0)
            ).orElse(
                If.isTrue(randomAnswer)
                    .then(1.0)
                    .orElse(0.0)
            );

        DoubleVertex answerTotal = new GaussianVertex(answer.sum(), 1);
        answerTotal.observe(numberOfYesAnswers);

        KeanuProbabilisticModel model = new KeanuProbabilisticModel(answerTotal.getConnectedGraph());

        NetworkSamplesGenerator samplesGenerator = Keanu.Sampling.MetropolisHastings.withDefaultConfig()
            .generatePosteriorSamples(model, singletonList(probabilityOfCheating));

        NetworkSamples networkSamples = samplesGenerator
            .dropCount(numberOfSamples / 2)
            .downSampleInterval(model.getLatentVariables().size())
            .generate(numberOfSamples);

        double approximateProbabilityOfCheating = networkSamples
            .getDoubleTensorSamples(probabilityOfCheating)
            .getAverages()
            .scalar();

        return approximateProbabilityOfCheating;
    }

}