Commit 28bf25f2 authored by Dumoulin Nicolas's avatar Dumoulin Nicolas
Browse files

first version

parent 11546340
No related merge requests found
Showing with 711 additions and 0 deletions
+711 -0
pom.xml 0 → 100644
<?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
/*
* 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]);
}
}
}
/*
* 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();
}
}
}
/*
* 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);
}
/*
* 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;
}
}
/*
* 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);
}
}
/*
* 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;
}
}
/*
* 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);
}
/*
* 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();
}
}
/*
* 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));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment