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

es.uam.eps.ir.relison.diffusion.propagation.PullPushStrategyRecommenderPropagationMechanism 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.propagation;

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.simulation.SimulationEdgeTypes;
import es.uam.eps.ir.relison.diffusion.simulation.UserState;
import es.uam.eps.ir.relison.graph.edges.EdgeOrientation;

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

/**
 * Propagation mechanism for the so-called rumour spreading propagation mechanism. Following this strategy, each user
 * selects a user each iteration: he catches the information from such user, and shares with him the information he has.
 * It is a combination of the pull and push propagation mechanisms. A certain amount of time has to pass before a
 * neighbor is selected again.
 *
 * With a given probability, it selects a neighbor using recommended links. Otherwise, it recommends any link.
 *
 * 

* Reference: A. Demers, D. Greene, C. Hauser, W. Irish, J. Larson. Epidemic algorithms for replicated database maintenance. ACM PODC 1987, pp. 1-12 (1987) *

* * @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 parameters. * */ public class PullPushStrategyRecommenderPropagationMechanism implements PropagationMechanism { /** * Number of iterations to wait until a profile can be revisited. */ private final int waitTime; /** * Edge direction of the neighbors to ask for information. */ private final EdgeOrientation orientation; /** * For each user, the list of users that user will propagate the information to. */ private final Map> propagationList; /** * The list of users in the last iterations. */ private final Map> lastIterations; /** * Probability of selecting a recommended link for propagation. */ private final double recProb; /** * Random number generator. */ private final Random rng; /** * Constructor. * @param waitTime number of iterations to wait until a profile can be revisited. * @param recProb probability of selecting a recommended link for propagation. */ public PullPushStrategyRecommenderPropagationMechanism(int waitTime, double recProb) { this(waitTime, EdgeOrientation.IN, recProb); } /** * Constructor. * @param waitTime number of iterations to wait until a profile can be revisited. * @param orientation selection of the visits available for contact. * @param recProb probability of selecting a recommended link for propagation. */ public PullPushStrategyRecommenderPropagationMechanism(int waitTime, EdgeOrientation orientation, double recProb) { this.waitTime = waitTime; this.orientation = orientation; this.lastIterations = new HashMap<>(); this.propagationList = new HashMap<>(); this.recProb = recProb; this.rng = new Random(); } @Override public Stream getUsersToPropagate(PropagatedInformation information, UserState originUser, Data data) { if(propagationList.containsKey(originUser.getUserId())) return propagationList.get(originUser.getUserId()).stream(); return Stream.empty(); } @Override public void resetSelections(Data data) { propagationList.clear(); // For each user in the network: data.getAllUsers().forEach((u)-> { // We first obtain the list of neighbors obtained through recommendation (and the rest of them). List recNeighs = new ArrayList<>(); List nonRecNeighs = new ArrayList<>(); data.getGraph().getNeighbourhood(u, orientation).forEach(v -> { if(orientation.equals(EdgeOrientation.IN)) { if(data.getGraph().getEdgeType(v, u) == SimulationEdgeTypes.RECOMMEND) { recNeighs.add(v); } else { nonRecNeighs.add(v); } } else if(orientation.equals(EdgeOrientation.OUT)) { if(data.getGraph().getEdgeType(u,v) == SimulationEdgeTypes.RECOMMEND) { recNeighs.add(v); } else { nonRecNeighs.add(v); } } else { if(data.getGraph().containsEdge(u, v) && data.getGraph().getEdgeType(u,v) == SimulationEdgeTypes.RECOMMEND) { recNeighs.add(v); } else if(data.getGraph().containsEdge(v,u) && data.getGraph().getEdgeType(v,u) == SimulationEdgeTypes.RECOMMEND) { recNeighs.add(v); } else { nonRecNeighs.add(v); } } }); // We check whether the last iterations contains a key: if(!this.lastIterations.containsKey(u)) { this.lastIterations.put(u, new ArrayList<>()); } // Then, we obtain the visited users in the last cases: List alreadyVisited = this.lastIterations.get(u); U neigh; recNeighs.removeAll(alreadyVisited); nonRecNeighs.removeAll(alreadyVisited); // To ensure that we can choose a neighbor, if there is no eligible neighbors among the // recommended ones, we choose from the rest. if(recNeighs.isEmpty()) { recNeighs.addAll(nonRecNeighs); } // The same applies to the rest (in the opposite direction. if(nonRecNeighs.isEmpty()) { nonRecNeighs.addAll(recNeighs); } double nextDouble = rng.nextDouble(); if(nextDouble < this.recProb) { if(!recNeighs.isEmpty()) { int index = rng.nextInt(recNeighs.size()); neigh = recNeighs.get(index); } else { neigh = null; } } else { if(!nonRecNeighs.isEmpty()) { int index = rng.nextInt(nonRecNeighs.size()); neigh = nonRecNeighs.get(index); } else { neigh = null; } } if(neigh != null) { if(!propagationList.containsKey(neigh)) propagationList.put(neigh, new ArrayList<>()); if(!propagationList.get(neigh).contains(u)) propagationList.get(neigh).add(u); if(!propagationList.containsKey(u)) propagationList.put(u, new ArrayList<>()); if(!propagationList.get(u).contains(neigh)) propagationList.get(u).add(neigh); alreadyVisited.add(neigh); } else { alreadyVisited.add(null); } // Prune the list if(alreadyVisited.size() > this.waitTime) { alreadyVisited.remove(0); } }); } @Override public boolean dependsOnInformationPiece() { return false; } }