All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.uam.eps.ir.relison.diffusion.simulation.Simulation Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2020 Information Retrieval Group at Universidad Autónoma
 * de Madrid, http://ir.ii.uam.es
 * 
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package es.uam.eps.ir.relison.diffusion.simulation;

import es.uam.eps.ir.relison.diffusion.data.Data;
import es.uam.eps.ir.relison.diffusion.data.PropagatedInformation;
import es.uam.eps.ir.relison.diffusion.update.UpdateMechanism;
import es.uam.eps.ir.relison.utils.datatypes.Tuple2oo;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Class that stores the evolution of a simulation over time. It just stores the
 * pieces that are read by the different users in the network.
 *
 * @author Javier Sanz-Cruzado ([email protected])
 * @author Pablo Castells ([email protected])
 *
 * @param  type of the users.
 * @param  type of the information pieces.
 * @param 

type of the parameter values. */ public class Simulation { /** * Total number of iterations in the simulation. */ private int numIterations; /** * List of iterations. */ private final List> iterations; /** * Data. */ private final Data data; /** * Initial iteration number. */ private final int initialNumber; /** * Constructor. * @param data the real data. * @param initialNumber initial iteration number. */ public Simulation(Data data, int initialNumber) { this.data = data; this.numIterations = 0; this.iterations = new ArrayList<>(); this.initialNumber = initialNumber; } /** * Constructor. * @param data the real data */ public Simulation(Data data) { this(data, 0); } /** * Adds an iteration. The iteration must have the correct iteration number (initial + number of iterations). * @param iteration the iteration to add. * @return true if the iteration is correctly added, false if it is not. */ public boolean addIteration(Iteration iteration) { if(iteration != null && iteration.getIterationNumber() == (this.numIterations + this.initialNumber)) { this.numIterations++; this.iterations.add(iteration); return true; } return false; } /** * Gets an individual iteration in the simulation. * @param number the number of the iteration. * @return the iteration if it exists, null if it does not. */ public Iteration getIteration(int number) { if(number >= this.initialNumber && number < (this.numIterations + this.initialNumber)) { return this.iterations.get(number - this.initialNumber); } return null; } /** * Obtains the current number of iterations in the simulation. * @return the current number of iterations in the simulation. */ public int getNumIterations() { return this.numIterations; } /** * Obtains the data for the simulation. * @return the data for the simulation. */ public Data getData() { return this.data; } /** * Number of the first iteration. * @return the number of the first iteration. */ public int getInitialNumber() { return this.initialNumber; } /** * Finds a final state of the simulation. * @param upd update mechanism. * @return the final state of the simulation. */ public SimulationState getFinalState(UpdateMechanism upd) { SimulationState state = new SimulationState<>(); state.initialize(this.data); Map> propagated = new HashMap<>(); Map,Long>>> discarded = new HashMap<>(); Map,Long>>> received = new HashMap<>(); for(int i = 0; i < this.numIterations; ++i) { Iteration iteration = this.getIteration(i); this.updatePropagated(iteration, propagated, discarded, received); this.updateDiscarded(iteration, propagated, discarded, received); this.updateReceived(iteration, propagated, discarded, received, upd); } // Establish the state. state.getAllUsers().forEach(st -> { U u = st.getUserId(); int uidx = this.data.getUserIndex().object2idx(u); // Indicate the values for propagated information if(propagated.containsKey(u)) { propagated.get(u).keySet().forEach(info -> { int iidx = this.data.getInformationPiecesIndex().object2idx(info); st.addPropagatedInformation(new PropagatedInformation(iidx, propagated.get(u).get(info), uidx)); st.deleteOwnInformation(iidx); }); } // Indicate the values for discarded information if(discarded.containsKey(u)) { discarded.get(u).keySet().forEach(info -> { int iidx = this.data.getInformationPiecesIndex().object2idx(info); Set creators = discarded.get(u).get(info).v1().stream().map(v -> this.data.getUserIndex().object2idx(v)) .collect(Collectors.toCollection(HashSet::new)); long timestamp = discarded.get(u).get(info).v2(); PropagatedInformation propInfo = new PropagatedInformation(iidx, timestamp, creators); st.addDiscardedInformation(propInfo); st.addAllInformation(propInfo); }); } // Indicate the values for received information if(received.containsKey(u)) { received.get(u).keySet().forEach(info -> { int iidx = this.data.getInformationPiecesIndex().object2idx(info); Set creators = received.get(u).get(info).v1().stream().map(v -> this.data.getUserIndex().object2idx(v)) .collect(Collectors.toCollection(HashSet::new)); long timestamp = received.get(u).get(info).v2(); PropagatedInformation propInfo = new PropagatedInformation(iidx, timestamp, creators); st.addReceivedInformation(propInfo); st.addAllInformation(propInfo); }); } }); return state; } /** * Updates the values for propagated pieces of information. * @param iteration the current iteration. * @param propagated the set of propagated pieces. * @param discarded the set of discarded pieces. * @param received the set of received pieces. */ private void updatePropagated(Iteration iteration, Map> propagated, Map, Long>>> discarded, Map, Long>>> received) { long iter = iteration.getIterationNumber(); // Update information concerning propagated pieces of information. iteration.getPropagatingUsers().forEach(u -> { if(!propagated.containsKey(u)) { propagated.put(u, new HashMap<>()); } iteration.getPropagatedInformation(u).forEach(info -> { if(received.containsKey(u) && received.get(u).containsKey(info)) { received.get(u).remove(info); } propagated.get(u).put(info, iter); }); }); } /** * Updates the values for discarded pieces of information. * @param iteration the current iteration. * @param propagated the set of propagated pieces. * @param discarded the set of discarded pieces. * @param received the set of received pieces. */ private void updateDiscarded(Iteration iteration, Map> propagated, Map, Long>>> discarded, Map, Long>>> received) { // Update information concerning discarded pieces of information. iteration.getDiscardingUsers().forEach(u -> { if(!discarded.containsKey(u)) { discarded.put(u, new HashMap<>()); } iteration.getDiscardedInformation(u).forEach(info -> { if(received.containsKey(u) && received.get(u).containsKey(info)) { Set creators = received.get(u).get(info).v1(); long time = received.get(u).get(info).v2(); discarded.get(u).put(info, new Tuple2oo<>(creators, time)); received.get(u).remove(info); } }); }); } /** * Updates the values for received pieces of information. * @param iteration the current iteration. * @param propagated the set of propagated pieces. * @param discarded the set of discarded pieces. * @param received the set of received pieces. * @param upd the update mechanism. */ private void updateReceived(Iteration iteration, Map> propagated, Map, Long>>> discarded, Map, Long>>> received, UpdateMechanism upd) { long iter = iteration.getIterationNumber(); // Update information concerning newly received pieces of information. iteration.getReceivingUsers().forEach(u -> { if(!received.containsKey(u)) { received.put(u, new HashMap<>()); } iteration.getSeenInformation(u).forEach(t -> { I info = t.v1(); Set creators = t.v2(); received.get(u).put(info, new Tuple2oo<>(creators, iter)); }); }); // Update information concerning old pieces of information received again. iteration.getReReceivingUsers().forEach(u -> { if(!received.containsKey(u)) { received.put(u, new HashMap<>()); } iteration.getReReceivedInformation(u).forEach(t -> { I info = t.v1(); long numIter = iter; int iidx = this.data.getInformationPiecesIndex().object2idx(info); Set setCreatorsB = t.v2().stream().map(v -> this.data.getUserIndex().object2idx(v)) .collect(Collectors.toCollection(HashSet::new)); // If the information was previously discarded... if(discarded.get(u) != null && discarded.get(u).containsKey(info)) { Set setCreatorsA = discarded.get(u).get(info).v1() .stream().map(v -> this.data.getUserIndex().object2idx(v)) .collect(Collectors.toCollection(HashSet::new)); PropagatedInformation propA = new PropagatedInformation(iidx, received.get(u).get(info).v2(), setCreatorsA); PropagatedInformation propB = new PropagatedInformation(iidx, numIter, setCreatorsB); PropagatedInformation def = upd.updateDiscarded(propA, propB); setCreatorsB = def.getCreators(); numIter = def.getTimestamp(); } // If the information was previously received... if(received.get(u) != null && received.get(u).containsKey(info)) { Set setCreatorsA = received.get(u).get(info).v1() .stream().map(v -> this.data.getUserIndex().object2idx(v)) .collect(Collectors.toCollection(HashSet::new)); PropagatedInformation propA = new PropagatedInformation(iidx, received.get(u).get(info).v2(), setCreatorsA); PropagatedInformation propB = new PropagatedInformation(iidx, numIter, setCreatorsB); PropagatedInformation def = upd.updateSeen(propA, propB); setCreatorsB = def.getCreators(); numIter = def.getTimestamp(); } Set creators = setCreatorsB.stream().map(vidx -> this.data.getUserIndex().idx2object(vidx)) .collect(Collectors.toCollection(HashSet::new)); received.get(u).put(info, new Tuple2oo<>(creators, numIter)); }); }); } }