/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package br.usp.poli.takiyama.acfove;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashSet;
import java.util.Set;
import org.junit.Ignore;
import org.junit.Test;
import br.usp.poli.takiyama.common.Constraint;
import br.usp.poli.takiyama.common.InequalityConstraint;
import br.usp.poli.takiyama.common.Marginal;
import br.usp.poli.takiyama.prv.Constant;
import br.usp.poli.takiyama.prv.LogicalVariable;
import br.usp.poli.takiyama.prv.Prv;
import br.usp.poli.takiyama.prv.RandomVariableSet;
import br.usp.poli.takiyama.utils.Example;
/**
* Tests comparing execution time for VE x C-FOVE x AC-FOVE. The following
* networks are used:
* <li> Sick Death
* <li> Competing Workshops
* <li> Water Sprinkler
* <li> Big Jackpot
* <p>
* In each test, the number of individuals in the population is varied to
* check the performance of each algorithm. A pre-defined query is used in
* each network.
* </p>
*/
public class ACFOVEPerformanceTest {
/**
* Path for output files. The name of each file must be concatenated with
* this variable.
*/
private String OUT_PATH = "/Users/ftakiyama/Dropbox/Mestrado/Disserta��o/img/";
/**
* Encoding of output files
*/
private final String ENCODING = "UTF-8";
/**
* Extension of output files with data
*/
private final String EXTENSION = ".dat";
/**
* The number of times each test is run to get a mean time.
*/
private final int CYCLES = 10;
/**
* Timeout for performance tests (in milliseconds)
*/
// @Rule
// public Timeout globalTimeout = new Timeout(100000);
private abstract class Problem {
private Example network;
private RandomVariableSet query;
private Marginal input;
private String name;
private Problem() { };
private String name() {
return name;
}
abstract void setNetwork(int size);
private ACFOVE propositionalizeAll() {
input = network.getMarginal(query);
return new VariableElimination(input);
}
private ACFOVE removeAggregation() {
input = network.getMarginal(query);
return new CFOVE(input);
}
private ACFOVE network() {
input = network.getMarginal(query);
return new ACFOVE(input);
}
}
private class SickDeath extends Problem {
private SickDeath() {
super.name = "Sick Death";
}
@Override
void setNetwork(int size) {
super.network = Example.sickDeathNetwork(size);
Prv someDeath = super.network.prv("someDeath ( )");
super.query = RandomVariableSet.getInstance(someDeath, new HashSet<Constraint>(0));
}
}
private class BigJackpot extends Problem {
private BigJackpot() {
super.name = "Big Jackpot";
}
@Override
void setNetwork(int size) {
super.network = Example.bigJackpotNetwork(size);
Prv jackpotWon = super.network.prv("jackpot_won ( )");
super.query = RandomVariableSet.getInstance(jackpotWon, new HashSet<Constraint>(0));
}
}
private class CompetingWorkshopsWithFixedNumberOfWorkshops extends Problem {
private int workshops;
public CompetingWorkshopsWithFixedNumberOfWorkshops(int workshops) {
this.workshops = workshops;
super.name = "Competing Workshops With Fixed Number of Workshops";
}
@Override
void setNetwork(int size) {
super.network = Example.competingWorkshopsNetwork(workshops, size);
Prv success = super.network.prv("success ( )");
super.query = RandomVariableSet.getInstance(success, new HashSet<Constraint>(0));
}
}
private class CompetingWorkshopsWithFixedNumberOfPeople extends Problem {
private int people;
public CompetingWorkshopsWithFixedNumberOfPeople(int people) {
this.people = people;
super.name = "Competing Workshops With Fixed Number of People";
}
@Override
void setNetwork(int size) {
super.network = Example.competingWorkshopsNetwork(size, people);
Prv success = super.network.prv("success ( )");
super.query = RandomVariableSet.getInstance(success, new HashSet<Constraint>(0));
}
}
private class WaterSprinkler extends Problem {
private WaterSprinkler() {
super.name = "Water Sprinkler";
}
@Override
void setNetwork(int size) {
super.network = Example.waterSprinklerNetWork(size);
Prv wetGrass = super.network.prv("wet_grass ( Lot )");
Set<Constraint> constraints = new HashSet<Constraint>();
LogicalVariable lot = super.network.lv("Lot");
for (int i = 1; i < size; i++) {
Constant loti = lot.population().individualAt(i);
constraints.add(InequalityConstraint.getInstance(lot, loti));
}
super.query = RandomVariableSet.getInstance(wetGrass, constraints);
}
}
private class PerformanceTest {
private final int limit;
private final String fileName;
private final Experiment experiment;
private final String title;
private final String step = "Testing with %d individuals...";
private final String end = "Done.";
public PerformanceTest(Experiment experiment, int limit, String fileName) {
this.experiment = experiment;
this.limit = limit;
this.fileName = fileName;
this.title = experiment.problem.name() + " - " + experiment.name();
}
public void run() throws IOException {
log(title);
Writer out = new OutputStreamWriter(new FileOutputStream(fileName), ENCODING);
for (int domainSize = 1; domainSize <= limit; domainSize = increment(domainSize)) {
log(step, domainSize);
double duration = experiment.getMeanExecutionTimeFor(domainSize);
out.write(dataPoint(domainSize, duration));
}
out.close();
log(end);
}
private int increment(int domainSize) {
int increment = (int) Math.pow(10.0, (int) Math.log10(domainSize));
return domainSize + increment;
}
private void log(String message, Object ... args) {
System.out.format(message + "\n", args);
}
// Returns a string with the data point to be written in output file
private String dataPoint(int x, double y) {
return x + " " + y + "\n";
}
}
private abstract class Experiment {
private final Problem problem;
private final int cycles;
private final String name;
public Experiment(Problem problem, int cycles, String name) {
this.problem = problem;
this.cycles = cycles;
this.name = name;
}
private String name() {
return name;
}
// returns the mean execution time in milliseconds
private double getMeanExecutionTimeFor(int domainSize) {
long sum = 0;
long duration = 0;
for (int i = 0; i < cycles; i++) {
// ACFOVE is mutable, so I need to create a new instance in each iteration
problem.setNetwork(domainSize);
ACFOVE acfove = formatProblem();
duration = getDurationInNanoseconds(acfove);
sum = sum + duration;
}
double mean = sum / cycles / 1e6;
return mean;
}
// returns the execution time to run the specified algorithm
private long getDurationInNanoseconds(ACFOVE algorithm) {
long startTime = System.nanoTime();
algorithm.run();
long endTime = System.nanoTime();
return (endTime - startTime);
}
abstract ACFOVE formatProblem();
}
private class VeTest extends Experiment {
public VeTest(Problem problem, int cycles) {
super(problem, cycles, "VE");
}
@Override
public ACFOVE formatProblem() {
return super.problem.propositionalizeAll();
}
}
private class CfoveTest extends Experiment {
public CfoveTest(Problem problem, int cycles) {
super(problem, cycles, "CFOVE");
}
@Override
public ACFOVE formatProblem() {
return super.problem.removeAggregation();
}
}
private class AcfoveTest extends Experiment {
public AcfoveTest(Problem problem, int cycles) {
super(problem, cycles, "ACFOVE");
}
@Override
public ACFOVE formatProblem() {
return super.problem.network();
}
}
private final String SICK_DEATH = OUT_PATH + "experiment_sick_death_network_";
@Test(timeout=550000)
@Ignore("Test already done")
public void SickDeathVe() throws IOException {
Experiment experiment = new VeTest(new SickDeath(), CYCLES);
int numberOfPoints = 10;
String fileName = SICK_DEATH + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=500000)
@Ignore("Test already done")
public void SickDeathCfove() throws IOException {
Experiment experiment = new CfoveTest(new SickDeath(), CYCLES);
int numberOfPoints = 500;
String fileName = SICK_DEATH + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=20000)
@Ignore("Test already done")
public void SickDeathAcfove() throws IOException {
Experiment experiment = new AcfoveTest(new SickDeath(), CYCLES);
int numberOfPoints = 10000;
String fileName = SICK_DEATH + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
private final String WATER_SPRINKLER = OUT_PATH + "experiment_water_sprinkler_network_";
@Test(timeout=30000)
@Ignore("Test already done")
public void WaterSprinklerVe() throws IOException {
Experiment experiment = new VeTest(new WaterSprinkler(), CYCLES);
int numberOfPoints = 10;
String fileName = WATER_SPRINKLER + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=70000)
@Ignore("Test already done")
public void WaterSprinklerCfove() throws IOException {
Experiment experiment = new CfoveTest(new WaterSprinkler(), CYCLES);
int numberOfPoints = 500;
String fileName = WATER_SPRINKLER + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=80000)
@Ignore("Test already done")
public void WaterSprinklerAcfove() throws IOException {
Experiment experiment = new AcfoveTest(new WaterSprinkler(), CYCLES);
int numberOfPoints = 500;
String fileName = WATER_SPRINKLER + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
private final String BIG_JACKPOT = OUT_PATH + "experiment_big_jackpot_network_";
@Test(timeout=1200000)
@Ignore("Test already done")
public void BigJackpotVe() throws IOException {
Experiment experiment = new VeTest(new BigJackpot(), CYCLES);
int numberOfPoints = 10;
String fileName = BIG_JACKPOT + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=5200000)
@Ignore("Test already done")
public void BigJackpotCfove() throws IOException {
Experiment experiment = new CfoveTest(new BigJackpot(), CYCLES);
int numberOfPoints = 1000;
String fileName = BIG_JACKPOT + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=20000)
@Ignore("Test already done")
public void BigJackpotAcfove() throws IOException {
Experiment experiment = new AcfoveTest(new BigJackpot(), CYCLES);
int numberOfPoints = 10000;
String fileName = BIG_JACKPOT + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
private final String COMPETING_WORKSHOPS_PEOPLE = OUT_PATH + "experiment_competing_workshops_network_people_";
@Test
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfPeopleVe() throws IOException {
Experiment experiment = new VeTest(new CompetingWorkshopsWithFixedNumberOfPeople(5), CYCLES);
int numberOfPoints = 10;
String fileName = COMPETING_WORKSHOPS_PEOPLE + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=15000000)
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfPeopleCfove() throws IOException {
Experiment experiment = new CfoveTest(new CompetingWorkshopsWithFixedNumberOfPeople(5), CYCLES);
int numberOfPoints = 500;
String fileName = COMPETING_WORKSHOPS_PEOPLE + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test(timeout=15000)
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfPeopleAcfove() throws IOException {
Experiment experiment = new AcfoveTest(new CompetingWorkshopsWithFixedNumberOfPeople(5), CYCLES);
int numberOfPoints = 10000;
String fileName = COMPETING_WORKSHOPS_PEOPLE + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
private final String COMPETING_WORKSHOPS_WORKSHOPS = OUT_PATH + "experiment_competing_workshops_network_workshops_";
@Test
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfWorkshopsVe() throws IOException {
Experiment experiment = new VeTest(new CompetingWorkshopsWithFixedNumberOfWorkshops(3), CYCLES);
int numberOfPoints = 10;
String fileName = COMPETING_WORKSHOPS_WORKSHOPS + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfWorkshopsCfove() throws IOException {
Experiment experiment = new CfoveTest(new CompetingWorkshopsWithFixedNumberOfWorkshops(3), CYCLES);
int numberOfPoints = 1000;
String fileName = COMPETING_WORKSHOPS_WORKSHOPS + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
@Test
@Ignore("Test already done")
public void CompetingWorkshopsWithFixedNumberOfWorkshopsAcfove() throws IOException {
Experiment experiment = new AcfoveTest(new CompetingWorkshopsWithFixedNumberOfWorkshops(3), CYCLES);
int numberOfPoints = 1000;
String fileName = COMPETING_WORKSHOPS_WORKSHOPS + experiment.name().toLowerCase() + EXTENSION;
new PerformanceTest(experiment, numberOfPoints, fileName).run();
}
}