diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..9511ae62e11f94ea13962d76c5ccf7b9601aba36 --- /dev/null +++ b/pom.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>fr.irstea</groupId> + <artifactId>associatione-model</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + <organization><name>Irstea</name></organization> + <dependencies> + <dependency> + <groupId>ca.umontreal</groupId> + <artifactId>ssj</artifactId> + <version>2.1.3</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + <version>1.0.13</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.1</version> + <type>jar</type> + </dependency> + </dependencies> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + <repositories> + <repository> + <id>fr.cemagref.lisc.maven2.releases</id> + <name>Lisc repository</name> + <url>http://trac.clermont.cemagref.fr/nexus/content/repositories/releases/</url> + </repository> + <repository> + <id>fr.cemagref.lisc.maven2.thirdparty</id> + <name>Lisc repository 2</name> + <url>http://trac.clermont.cemagref.fr/nexus/content/repositories/thirdparty/</url> + </repository> + </repositories> + +</project> \ No newline at end of file diff --git a/src/main/java/fr/irstea/associatione/model/Individual.java b/src/main/java/fr/irstea/associatione/model/Individual.java new file mode 100644 index 0000000000000000000000000000000000000000..e50417644b0af4e02c47b6f39bb84467e4463d6c --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/Individual.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +import java.util.Arrays; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class Individual { + + private final int id; + private final double[] individualsOpinions; + private final double[] subjectOpinions; + private final double[] influences; + + public Individual(int id, int popSize, int nbSubject) { + this.id = id; + individualsOpinions = new double[popSize]; + subjectOpinions = new double[popSize]; + influences = new double[popSize]; + Arrays.fill(individualsOpinions, 0); + Arrays.fill(subjectOpinions, 0); + Arrays.fill(influences, 0); + } + + public double getOpinionOnIndividual(int ind) { + return individualsOpinions[ind]; + } + + public double getOpinionOnSubject(int subject) { + return individualsOpinions[subject]; + } + + public void computeInfluences(Parameters parameters) { + for (int fromInd = 0; fromInd < individualsOpinions.length; fromInd++) { + influences[fromInd] = 1 / (1 + Math.exp(-(individualsOpinions[fromInd] - individualsOpinions[id]) / parameters.getSigma())); + } + } + + public void changeOpinion(Parameters parameters, Individual fromInd) { + double distort = parameters.getDistorsion().compute(this, fromInd); + individualsOpinions[id] += influences[fromInd.id] * parameters.getRho() * (fromInd.individualsOpinions[id] - individualsOpinions[id] + distort); + } + + public void argumentationImpact(Parameters parameters, Individual fromInd) { + for (int k = 0; k < parameters.getNbSubject(); k++) { + subjectOpinions[k] += influences[fromInd.id] * parameters.getRho() * (subjectOpinions[fromInd.id] - subjectOpinions[id]); + } + } + +} diff --git a/src/main/java/fr/irstea/associatione/model/Model.java b/src/main/java/fr/irstea/associatione/model/Model.java new file mode 100644 index 0000000000000000000000000000000000000000..0588e6d637c9309c6ac5923d2da01d931dee394a --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/Model.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +import fr.irstea.associatione.model.distorsion.DistorsionFromOpinions; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.StringUtils; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class Model { + + private final Parameters parameters; + private final Random random; + private final Individual[] individuals; + private final List<Individual[]> couples; + private int timestep; + + public Model(Parameters parameters) throws ProcessingException { + this.parameters = parameters; + this.random = new Random(); + random.resetNextSubstream(parameters.getSeedIndex()); + this.individuals = new Individual[parameters.getPopSize()]; + Arrays.setAll(individuals, i -> new Individual(i, parameters.getPopSize(), parameters.getNbSubject())); + couples = new ArrayList<>(); + for (int i = 0; i < individuals.length; i++) { + for (int j = 0; j < i; j++) { + couples.add(new Individual[]{individuals[i], individuals[j]}); + } + } + timestep = 0; + } + + public Parameters getParameters() { + return parameters; + } + + public int getTimestep() { + return timestep; + } + + public void iter() { + List<Individual[]> couplesShuffled = new ArrayList<>(couples); + random.shuffle(couplesShuffled); + for (Individual[] couple : couplesShuffled) { + iterMeeting(couple[0], couple[1]); + } + timestep++; + } + + private void iterMeeting(Individual ind1, Individual ind2) { + ind1.changeOpinion(parameters, ind2); + ind2.changeOpinion(parameters, ind1); + ind1.computeInfluences(parameters); + ind2.computeInfluences(parameters); + ind1.argumentationImpact(parameters, ind2); + ind2.argumentationImpact(parameters, ind1); + } + + public double[] getCredibility() { + double[] data = new double[individuals.length * (individuals.length - 1)]; + int index = 0; + for (int i = 0; i < individuals.length; i++) { + Individual ind = individuals[i]; + for (int j = 0; j < individuals.length; j++) { + if (i != j) { + data[index] = ind.getOpinionOnIndividual(j); + index++; + } + } + } + return data; + } + + public double[] getOpinionsMeanOnSubjects() { + double[] data = new double[individuals.length]; + for (int i = 0; i < individuals.length; i++) { + Individual individual = individuals[i]; + data[i] = 0; + for (int k = 0; k < parameters.getNbSubject(); k++) { + data[i] += individual.getOpinionOnSubject(k); + } + data[i] = data[i] / parameters.getNbSubject(); + } + return data; + } + + public static void main(String[] args) throws ProcessingException, IllegalArgumentException, IllegalAccessException { + + Parameters parameters = new Parameters(0, 50, 1, new DistorsionFromOpinions(), 1, 0.3); + Model model = new Model(parameters); + parameters.init(model); + for (int i = 0; i < 5; i++) { + System.out.println("Iteration " + i); + model.iter(); + } + } +} diff --git a/src/main/java/fr/irstea/associatione/model/Parameter.java b/src/main/java/fr/irstea/associatione/model/Parameter.java new file mode 100644 index 0000000000000000000000000000000000000000..2ab178e045006b23e3265f398360b4941f653bdf --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/Parameter.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public interface Parameter { + public void init(Model model); +} diff --git a/src/main/java/fr/irstea/associatione/model/Parameters.java b/src/main/java/fr/irstea/associatione/model/Parameters.java new file mode 100644 index 0000000000000000000000000000000000000000..bdd9fc27a3e07fb2a2d029f3d0c842034e2bf2f9 --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/Parameters.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +import fr.irstea.associatione.model.distorsion.Distorsion; +import java.lang.reflect.Field; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class Parameters { + + private int seedIndex; + private int popSize; + private int nbSubject; + private Distorsion distorsion; + private double rho; + private double sigma; + + public Parameters(int seedIndex, int popSize, int nbSubject, Distorsion distorsion, double rho, double sigma) { + this.seedIndex = seedIndex; + this.popSize = popSize; + this.nbSubject = nbSubject; + this.distorsion = distorsion; + this.rho = rho; + this.sigma = sigma; + } + + public void init(Model model) throws IllegalArgumentException, IllegalAccessException { + for (Field field : Parameters.class.getDeclaredFields()) { + if (Parameter.class.isAssignableFrom(field.get(this).getClass())) { + ((Parameter)field.get(this)).init(model); + } + } + } + + public int getSeedIndex() { + return seedIndex; + } + + public int getPopSize() { + return popSize; + } + + public int getNbSubject() { + return nbSubject; + } + + public Distorsion getDistorsion() { + return distorsion; + } + + public double getRho() { + return rho; + } + + public double getSigma() { + return sigma; + } + + + +} diff --git a/src/main/java/fr/irstea/associatione/model/ProcessingException.java b/src/main/java/fr/irstea/associatione/model/ProcessingException.java new file mode 100644 index 0000000000000000000000000000000000000000..28c25418707eb076a292e191da907095c8ef3571 --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/ProcessingException.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class ProcessingException extends Exception { + + public ProcessingException(Throwable cause) { + super(cause); + } + + public ProcessingException(String message, Throwable cause) { + super(message, cause); + } + + public ProcessingException(String message) { + super(message); + } + +} diff --git a/src/main/java/fr/irstea/associatione/model/Random.java b/src/main/java/fr/irstea/associatione/model/Random.java new file mode 100644 index 0000000000000000000000000000000000000000..ad6080a0dde08e8def02f586db4f97938b08ce11 --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/Random.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2010 Cemagref + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import umontreal.iro.lecuyer.rng.MRG32k3a; +import umontreal.iro.lecuyer.rng.RandomPermutation; + +/** + * @author Nicolas Dumoulin <nicolas.dumoulin@cemagref.fr> + * @author sylvie.huet + */ +public class Random { + + private MRG32k3a randomStream; + + /** + * This method returns an integer picked out following a Uniform law between + * i and i1. The values i and i1 are included (can be picked out) + */ + public int nextInt(int i, int i1) { + return randomStream.nextInt(i, i1); + } + + /** + * This method return a random order for a sequence of leng numbers. + */ + public int[] randomList(int leng) { + int[] vec = new int[leng]; + for (int i = 0; i < leng; i++) { + vec[i] = i; + } + RandomPermutation.shuffle(vec, randomStream); + return vec; + } + + public String getSeedToString() { + StringBuilder buff = new StringBuilder(); + for (long val : randomStream.getState()) { + buff.append(val); + buff.append(" "); + } + return buff.toString(); + // this code make troubles in exception stacktrace formatting (don't know why…) + //return Arrays.toString(randomStream.getState()); + } + + /** + * This method should only be called by the simulation starter. The initial + * status for the RNG is initialized by the simulator at startup. + * + * @param seed + */ + public void setSeed(long[] seed) throws ProcessingException { + if (randomStream != null) { + throw new ProcessingException("Trying to reinit the seed of the RNG although it is already initialized!"); + } + randomStream = new MRG32k3a(); + randomStream.setSeed(seed); + } + + /** + * This method should only be called by the simulation starter. + * Reinitializes the stream to the beginning of its next substream (see SSJ + * documentation) + * + * @param count nb of substreams to shift. Give 0 if you want the default + * one. + */ + public void resetNextSubstream(int count) throws ProcessingException { + if (randomStream != null) { + throw new ProcessingException("Trying to reinit the seed of the RNG although it is already initialized!"); + } + randomStream = new MRG32k3a(); + randomStream.setSeed(new long[]{12345, 12345, 12345, 12345, 12345, 12345}); + for (int i = 0; i < count; i++) { + randomStream.resetNextSubstream(); + } + } + + /** + * Randomly permutes list. This method permutes the whole list. + * + * @param list the list to process + */ + public void shuffle(List list) { + RandomPermutation.shuffle(list, randomStream); + } + + /** + * Picks randomly some elements from a list. + * + * @param <E> + * @param list + * @param nb the number of elements to pick out + * @return null, if nb <= 0 + */ + public <E> List<E> pickElements(List<E> list, int nb) { + if (nb <= 0) { + return null; + } + List<E> result = new ArrayList<E>(nb); + List<E> copy = new ArrayList<E>(list); + for (int i = 0; i < nb; i++) { + int index = nextInt(0, copy.size() - 1); + result.add(copy.remove(index)); + } + return result; + } + + /** + * Build an array of indexes for randomly picking elements in a matrix. + * + * @param elements + * @return an array of two-dimensional indexes + */ + public List<int[]> buildRandomMatrixIndexes(int size) { + List<int[]> indexes = new ArrayList<int[]>(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + indexes.add(new int[]{i, j}); + } + } + shuffle(indexes); + return indexes; + } + +} diff --git a/src/main/java/fr/irstea/associatione/model/distorsion/Distorsion.java b/src/main/java/fr/irstea/associatione/model/distorsion/Distorsion.java new file mode 100644 index 0000000000000000000000000000000000000000..bab5f9af3aba155bc1ae64eda8115116149667c3 --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/distorsion/Distorsion.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model.distorsion; + +import fr.irstea.associatione.model.Individual; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public interface Distorsion { + public double compute(Individual from, Individual to); +} diff --git a/src/main/java/fr/irstea/associatione/model/distorsion/DistorsionFromOpinions.java b/src/main/java/fr/irstea/associatione/model/distorsion/DistorsionFromOpinions.java new file mode 100644 index 0000000000000000000000000000000000000000..e7b9bf12005359b7c78debc5d99477ae8d7a08dd --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/distorsion/DistorsionFromOpinions.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model.distorsion; + +import fr.irstea.associatione.model.Individual; +import fr.irstea.associatione.model.Model; +import fr.irstea.associatione.model.Parameter; +import fr.irstea.associatione.model.Parameters; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class DistorsionFromOpinions implements Distorsion, Parameter { + + private Parameters parameters; + + @Override + public void init(Model model) { + this.parameters = model.getParameters(); + } + + @Override + public double compute(Individual from, Individual to) { + double sum = 0; + for (int k = 0; k < parameters.getNbSubject(); k++) { + sum += Math.abs(from.getOpinionOnSubject(k) - to.getOpinionOnSubject(k)); + } + return sum / parameters.getNbSubject(); + } + +} diff --git a/src/main/java/fr/irstea/associatione/model/gui/GUI.java b/src/main/java/fr/irstea/associatione/model/gui/GUI.java new file mode 100644 index 0000000000000000000000000000000000000000..aa8554040c122d8a852e1d5956e26f3f4f436d8f --- /dev/null +++ b/src/main/java/fr/irstea/associatione/model/gui/GUI.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 Irstea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package fr.irstea.associatione.model.gui; + +import fr.irstea.associatione.model.Model; +import fr.irstea.associatione.model.Parameters; +import fr.irstea.associatione.model.ProcessingException; +import fr.irstea.associatione.model.distorsion.DistorsionFromOpinions; +import java.awt.GridLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.StandardXYBarPainter; +import org.jfree.chart.renderer.xy.XYBarRenderer; +import org.jfree.data.statistics.HistogramDataset; +import org.jfree.data.statistics.HistogramType; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +/** + * + * @author Nicolas Dumoulin <nicolas.dumoulin@irstea.fr> + */ +public class GUI { + + private final JFrame frame; + private final JPanel chartsPanel; + private Model model; + private ChartPanel credibilityChartPanel; + private final XYSeriesCollection opinionsMeanOnSubjects; + + public GUI() { + frame = new JFrame("test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.chartsPanel = new JPanel(new GridLayout(0, 2)); + frame.setContentPane(chartsPanel); + opinionsMeanOnSubjects = new XYSeriesCollection(); + } + + public void initCharts() { + for (int i = 0; i < model.getParameters().getPopSize(); i++) { + opinionsMeanOnSubjects.addSeries(new XYSeries(i)); + } + chartsPanel.removeAll(); + credibilityChartPanel = new ChartPanel(createHistogram(model.getCredibility())); + chartsPanel.add(credibilityChartPanel); + chartsPanel.add(new ChartPanel(ChartFactory.createXYLineChart("Opinions means on subjects", "timesteps", "opinions", opinionsMeanOnSubjects, PlotOrientation.VERTICAL, true, true, false))); + } + + public void init(Parameters parameters) throws ProcessingException, IllegalArgumentException, IllegalAccessException { + model = new Model(parameters); + parameters.init(model); + initCharts(); + frame.pack(); + frame.setVisible(true); + for (int i = 0; i < 500; i++) { + model.iter(); + updatePlots(model.getTimestep()); + } + } + + public void test() { + double[] data = new double[]{0.3, 0.3, 0.5, 0.6, 0.65}; + JFrame f = new JFrame("test"); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.setContentPane(new ChartPanel(createHistogram(data))); + f.pack(); + f.setVisible(true); + } + + public void updatePlots(int timestep) { + credibilityChartPanel.setChart(createHistogram(model.getCredibility())); + for (int i = 0; i < model.getParameters().getPopSize(); i++) { + double[] data = model.getOpinionsMeanOnSubjects(); + opinionsMeanOnSubjects.getSeries(i).add(timestep, data[i]); + } + } + + public static JFreeChart createHistogram(double[] data) { + HistogramDataset dataset = new HistogramDataset(); + dataset.setType(HistogramType.SCALE_AREA_TO_1); + dataset.addSeries("Histogram", data, 30); + String plotTitle = "Histogram"; + String xaxis = "number"; + String yaxis = "value"; + PlotOrientation orientation = PlotOrientation.VERTICAL; + boolean show = false; + boolean toolTips = false; + boolean urls = false; + JFreeChart chart = ChartFactory.createHistogram(plotTitle, xaxis, yaxis, + dataset, orientation, show, toolTips, urls); + XYPlot plot = (XYPlot) chart.getPlot(); + XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer(); + renderer.setBarPainter(new StandardXYBarPainter()); + renderer.setShadowVisible(false); + return chart; + } + + public static void main(String[] args) throws Exception { + GUI gui = new GUI(); + gui.init(new Parameters(0, 50, 1, new DistorsionFromOpinions(), 1, 0.3)); + + } +}