![JAR search and dependency download from the Maven repository](/logo.png)
es.uam.eps.ir.relison.diffusion.data.Data 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.data;
import es.uam.eps.ir.relison.graph.Graph;
import es.uam.eps.ir.relison.index.Index;
import es.uam.eps.ir.relison.index.Relation;
import es.uam.eps.ir.relison.index.fast.FastWeightedPairwiseRelation;
import es.uam.eps.ir.relison.utils.datatypes.Tuple2ol;
import org.ranksys.core.util.tuples.Tuple2od;
import java.io.Serializable;
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* Class that contains the basic information for simulations.
*
* @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 user and information pieces features.
*/
public class Data
{
/**
* User index.
*/
private final Index users;
/**
* Information pieces index.
*/
private final Index informationPieces;
/**
* Additional information for the information pieces.
*/
private final Map> informationPieceData;
/**
* Feature indexes (stored by the name of the parameter).
*/
private final Map> features;
/**
* Relation between users and the propagated information (allows identifying both the
* information pieces created by a user, and the creator of the information piece.
*/
private final Relation userInformation;
/**
* The graph in which the simulation will run.
*/
private final Graph graph;
/**
* List of features related to each individual user.
*/
private final List userFeatureNames;
/**
* List of features related to each information piece
*/
private final List infoPiecesFeatureNames;
/**
* Relation between users and their features (allows identifying the users
* that share the same feature, as well as the features of the different users).
*/
private final Map> userFeatures;
/**
* Relation between users and their features (allows identifying the information pieces
* that share the same feature, as well as the features of the different information pieces).
*/
private final Map> infoPiecesFeatures;
/**
* Map containing the information pieces which have been really propagated by the user.
*/
private final Relation realPropagated;
/**
* Ordered set of timestamps when information pieces where published in real life.
*/
private TreeSet timestamps;
/**
* Relation between the timestamps and the pieces propagated by each user.
*/
private final HashMap>> propagatedByTS;
/**
* Relation between the timestamps and the pieces repropagated by each user.
*/
private final HashMap>> realPropagatedByTS;
/**
* Simplest constructor. There is no additional information for information pieces, nor features.
* @param graph the social network graph.
* @param users the user index.
* @param informationPieces information pieces index.
* @param userInformation relation between users and information pieces.
*/
public Data(Graph graph, Index users, Index informationPieces, Relation userInformation)
{
this(graph, users, informationPieces, new HashMap<>(), userInformation, new HashMap<>(), new ArrayList<>(), new HashMap<>(), new ArrayList<>(), new HashMap<>());
}
/**
* Constructor. There is no additional information for information pieces, nor features.
* @param graph the social network graph.
* @param users the user index.
* @param informationPieces information pieces index.
* @param informationData detailed information about the information pieces.
* @param userInformation relation between users and information pieces.
*/
public Data(Graph graph, Index users, Index informationPieces, Map> informationData, Relation userInformation)
{
this(graph, users, informationPieces, informationData, userInformation, new HashMap<>(), new ArrayList<>(), new HashMap<>(), new ArrayList<>(), new HashMap<>());
}
/**
* Constructor. Only user / information pieces features.
* @param graph the social network graph.
* @param users the user index.
* @param informationPieces information pieces index.
* @param informationData detailed information about the information pieces.
* @param userInformation relation between users and information pieces.
* @param features indexes for the different features.
* @param featureNames the names of the user/pieces features.
* @param featureRel relation between users/pieces and their features.
* @param userfeatures true if features are related to users, false if they are related to information pieces.
*/
public Data(Graph graph, Index users, Index informationPieces, Map> informationData, Relation userInformation, Map> features, List featureNames, Map> featureRel, boolean userfeatures)
{
this.users = users;
this.informationPieces = informationPieces;
this.informationPieceData = informationData;
this.features = features;
this.userInformation = userInformation;
this.graph = graph;
this.userFeatureNames = userfeatures ? featureNames : new ArrayList<>();
this.infoPiecesFeatureNames = userfeatures ? new ArrayList<>() : featureNames;
this.userFeatures = userfeatures ? featureRel : new HashMap<>();
this.infoPiecesFeatures = userfeatures ? new HashMap<>() : featureRel;
this.realPropagated = new FastWeightedPairwiseRelation<>();
this.propagatedByTS = new HashMap<>();
this.realPropagatedByTS = new HashMap<>();
IntStream.range(0, this.users.numObjects()).forEach(this.realPropagated::addFirstItem);
IntStream.range(0, this.informationPieces.numObjects()).forEach(this.realPropagated::addSecondItem);
IntStream.range(0, this.users.numObjects()).forEach(uidx ->
{
this.userInformation.getIdsSecond(uidx).forEach(iidx -> this.timestamps.add(this.informationPieceData.get(iidx.getIdx()).getTimestamp()));
this.realPropagated.getIdsSecond(uidx).forEach(iidx -> this.timestamps.add(iidx.getValue()));
});
this.timestamps.add(Long.MAX_VALUE);
this.timestamps.forEach(ts ->
{
propagatedByTS.put(ts, new HashMap<>());
realPropagatedByTS.put(ts, new HashMap<>());
});
buildTimestampPieces();
}
/**
* Builds the relationship between timestamps and pairs (user, piece).
*/
private void buildTimestampPieces()
{
this.getUserIndex().getAllObjects().forEach(u ->
{
this.getPieces(u).forEach(i ->
{
long ts = this.getTimestamp(i);
if(!propagatedByTS.get(ts).containsKey(u))
{
propagatedByTS.get(ts).put(u, new HashSet<>());
}
propagatedByTS.get(ts).get(u).add(i);
});
this.getRealPropagatedPiecesWithTimestamp(u).forEach(tuple ->
{
long ts = tuple.v2();
if(!realPropagatedByTS.get(ts).containsKey(u))
{
realPropagatedByTS.get(ts).put(u, new HashSet<>());
}
realPropagatedByTS.get(ts).get(u).add(tuple.v1());
});
});
}
/**
* Full constructor.
* @param graph the social network graph.
* @param users the user index.
* @param informationPieces information pieces index.
* @param informationData detailed information about the information pieces.
* @param userInformation relation between users and information pieces.
* @param features indexes for the different features.
* @param userFeatureNames the names of the user features.
* @param userFeatures relation between users and their features.
* @param infoPiecesFeatureNames the name for information pieces features.
* @param infoPiecesFeatures relation between information pieces and their features.
*/
public Data(Graph graph, Index users, Index informationPieces, Map> informationData, Relation userInformation, Map> features, List userFeatureNames, Map> userFeatures, List infoPiecesFeatureNames, Map> infoPiecesFeatures)
{
this(graph,users,informationPieces,informationData,userInformation,features,userFeatureNames,userFeatures,infoPiecesFeatureNames,infoPiecesFeatures, null);
}
/**
* Full constructor.
* @param graph the social network graph.
* @param users the user index.
* @param informationPieces information pieces index.
* @param informationData detailed information about the information pieces.
* @param userInformation relation between users and information pieces.
* @param features indexes for the different features.
* @param userFeatureNames the names of the user features.
* @param userFeatures relation between users and their features.
* @param infoPiecesFeatureNames the name for information pieces features.
* @param infoPiecesFeatures relation between information pieces and their features.
* @param realPropagated relation indicating which information pieces were repropagated in real scenario.
*/
public Data(Graph graph, Index users, Index informationPieces, Map> informationData, Relation userInformation, Map> features, List userFeatureNames, Map> userFeatures, List infoPiecesFeatureNames, Map> infoPiecesFeatures, Relation realPropagated)
{
this.users = users;
this.informationPieces = informationPieces;
this.informationPieceData = informationData;
this.features = features;
this.userInformation = userInformation;
this.graph = graph;
this.userFeatureNames = userFeatureNames;
this.infoPiecesFeatureNames = infoPiecesFeatureNames;
this.userFeatures = userFeatures;
this.infoPiecesFeatures = infoPiecesFeatures;
this.propagatedByTS = new HashMap<>();
this.realPropagatedByTS = new HashMap<>();
if(realPropagated == null)
{
this.realPropagated = new FastWeightedPairwiseRelation<>();
IntStream.range(0, this.users.numObjects()).forEach(this.realPropagated::addFirstItem);
IntStream.range(0, this.informationPieces.numObjects()).forEach(this.realPropagated::addSecondItem);
}
else
{
this.realPropagated = realPropagated;
}
this.timestamps = new TreeSet<>();
IntStream.range(0, this.users.numObjects()).forEach(uidx ->
{
this.userInformation.getIdsSecond(uidx).forEach(iidx -> this.timestamps.add(this.informationPieceData.get(iidx.getIdx()).getTimestamp()));
this.realPropagated.getIdsSecond(uidx).forEach(iidx -> this.timestamps.add(iidx.getValue()));
});
this.timestamps.add(Long.MAX_VALUE);
this.timestamps.forEach(ts ->
{
propagatedByTS.put(ts, new HashMap<>());
realPropagatedByTS.put(ts, new HashMap<>());
});
buildTimestampPieces();
}
/**
* Obtain all users.
* @return a stream containing all users.
*/
public Stream getAllUsers()
{
return this.users.getAllObjects();
}
/**
* Obtain the number of users in the simulation.
* @return the number of users.
*/
public int numUsers()
{
return this.users.numObjects();
}
/**
* Obtains a user index for creating relations.
* @return the user index.
*/
public Index getUserIndex()
{
return this.users;
}
/**
* Obtain all information pieces.
* @return a stream containing all information pieces.
*/
public Stream getAllInformationPieces()
{
return this.informationPieces.getAllObjects();
}
/**
* Obtains the number of information pieces.
* @return the number of information pieces.
*/
public int numInformationPieces()
{
return this.informationPieces.numObjects();
}
/**
* Obtains an index for the different information pieces.
* @return the information pieces index.
*/
public Index getInformationPiecesIndex()
{
return informationPieces;
}
/**
* Obtains the extended information of an information piece
* @param piece the information piece.
* @return the extended information if the piece exists, null if it does not.
*/
public Information getInformation(I piece)
{
int iidx = this.informationPieces.object2idx(piece);
if(this.informationPieceData.containsKey(iidx))
{
return this.informationPieceData.get(iidx);
}
return null;
}
/**
* Obtains the creators of a single information piece.
* @param piece the piece.
* @return a stream of creators, empty if there are none.
*/
public Stream getCreators(I piece)
{
int iidx = this.informationPieces.object2idx(piece);
if(iidx == -1)
{
return Stream.empty();
}
return this.userInformation.getIdsFirst(iidx).map(uidx -> this.users.idx2object(uidx.getIdx()));
}
/**
* Obtains the information pieces created by a user.
* @param user the user.
* @return a stream of information pieces, empty if there are none.
*/
public Stream getPieces(U user)
{
int uidx = this.users.object2idx(user);
if(uidx == -1)
{
return Stream.empty();
}
return this.userInformation.getIdsSecond(uidx).map(iidx -> this.informationPieces.idx2object(iidx.getIdx()));
}
/**
* Obtains the timestamp for an information piece.
* @param info the information piece.
* @return the timestamp in case it exists, -1 if it does not.
*/
public long getTimestamp(I info)
{
int iidx = this.informationPieces.object2idx(info);
if(iidx != -1)
{
return this.informationPieceData.get(iidx).getTimestamp();
}
return -1L;
}
/**
* Obtains the graph.
* @return the graph.
*/
public Graph getGraph()
{
return this.graph;
}
/**
* Obtains the features for a single user.
* @param user the user.
* @param param the parameter.
* @return a stream of pairs (parameter,value), empty if there are none.
*/
public Stream> getUserFeatures(U user, String param)
{
int uidx = this.users.object2idx(user);
if(this.userFeatures.containsKey(param) && uidx != -1)
{
return this.userFeatures.get(param).getIdsSecond(uidx).map(pidx -> new Tuple2od<>(this.features.get(param).idx2object(pidx.getIdx()), pidx.getValue()));
}
return Stream.empty();
}
/**
* Obtains the features for a single information piece.
* @param info the information piece.
* @param param the parameter.
* @return a stream of pairs (parameter,value), empty if there are none.
*/
public Stream> getInfoPiecesFeatures(I info, String param)
{
int iidx = this.informationPieces.object2idx(info);
if(this.infoPiecesFeatures.containsKey(param) && iidx != -1)
{
return this.infoPiecesFeatures.get(param).getIdsSecond(iidx).map(pidx -> new Tuple2od<>(this.features.get(param).idx2object(pidx.getIdx()), pidx.getValue()));
}
return Stream.empty();
}
/**
* Gets all possible values for a certain parameter.
* @param parameter the parameter name.
* @return a stream containing all the possible values if the parameter exists,
* an empty stream if it does not.
*/
public Stream getAllFeatureValues(String parameter)
{
if(this.doesFeatureExist(parameter))
{
return this.features.get(parameter).getAllObjects();
}
return Stream.empty();
}
/**
* Gets the number of possible values for a certain parameter.
* @param parameter the parameter name.
* @return the number of possible features if the parameter exists, 0 if it does not.
*/
public int numFeatureValues(String parameter)
{
if(this.doesFeatureExist(parameter))
{
return this.features.get(parameter).numObjects();
}
return 0;
}
/**
* Returns an index for a given parameter.
* @param param the parameter name.
* @return the index if it exists, null if it does not.
*/
public Index getFeatureIndex(String param)
{
if(this.features.containsKey(param))
return this.features.get(param);
return null;
}
/**
* Indicates if a user is contained in the data.
* @param u the user.
* @return true if the user is contained in the data, false if it is not.
*/
public boolean containsUser(U u)
{
return this.users.containsObject(u);
}
/**
* Indicates if data contains a certain information piece.
* @param i the information piece.
* @return true if the user is contained in the data, false if it is not.
*/
public boolean containsInformationPiece(I i)
{
return this.informationPieces.containsObject(i);
}
/**
* Checks if a feature is stored in the data.
* @param feature the feature name.
* @return true if the feature exists, false otherwise.
*/
public boolean doesFeatureExist(String feature)
{
return this.features.containsKey(feature);
}
/**
* Checks if a feature exists, and it is a user feature.
* @param feature the feature name.
* @return true if the feature exists, false otherwise.
*/
public boolean isUserFeature(String feature)
{
return this.features.containsKey(feature) && this.userFeatureNames.contains(feature);
}
/**
* Checks if a feature exists, and it is an information piece feature.
* @param feature the feature name.
* @return true if the feature exists, false otherwise.
*/
public boolean isInfoPieceFeature(String feature)
{
return this.features.containsKey(feature) && this.infoPiecesFeatureNames.contains(feature);
}
/**
* Obtains the names of the user features.
* @return a list containing the user features.
*/
public List getUserFeatureNames()
{
return this.userFeatureNames;
}
/**
* Obtains the names of the information piece features.
* @return a list containing the information piece features.
*/
public List getInfoPiecesFeatureNames()
{
return this.infoPiecesFeatureNames;
}
/**
* Checks if a feature value exists.
* @param feature the feature name.
* @param value the feature value we want to check.
* @return true if the value exists, false otherwise.
*/
public boolean containsFeatureValue(String feature, F value)
{
if(this.doesFeatureExist(feature))
{
return this.features.get(feature).containsObject(value);
}
return false;
}
/**
* Obtains all users with a certain feature value.
* @param feature the name of the feature.
* @param value the value of the feature.
* @return a stream containing the different pairs (user, value) that are represented
* by the value parameter.
*/
public Stream> getUsersWithFeature(String feature, F value)
{
if(this.containsFeatureValue(feature, value))
{
int pidx = this.features.get(feature).object2idx(value);
return this.userFeatures.get(feature).getIdsFirst(pidx).map(pair ->
{
U u = this.users.idx2object(pair.getIdx());
return new Tuple2od<>(u, pair.getValue());
});
}
else
{
return Stream.empty();
}
}
/**
* Obtains all information pieces with a certain feature value.
* @param feature the name of the feature.
* @param value the value of the feature.
* @return a stream containing the different pairs (infopiece, value) that are represented
* by the value parameter.
*/
public Stream> getInformationPiecesWithFeature(String feature, F value)
{
if(this.containsFeatureValue(feature, value))
{
int pidx = this.features.get(feature).object2idx(value);
return this.infoPiecesFeatures.get(feature).getIdsFirst(pidx).map(pair ->
{
I i = this.informationPieces.idx2object(pair.getIdx());
return new Tuple2od<>(i, pair.getValue());
});
}
else
{
return Stream.empty();
}
}
/**
* Given an information piece, obtains the set of users that repropagated them in a real scenario.
* @param piece the information piece.
* @return the stream of users that repropagated the piece.
*/
public Stream getRealPropagatedUsers(I piece)
{
if(this.informationPieces.containsObject(piece))
{
int iidx = this.informationPieces.object2idx(piece);
return this.realPropagated.getIdsFirst(iidx).map(tuple -> this.users.idx2object(tuple.getIdx()));
}
return Stream.empty();
}
/**
* Given a user, obtains the set of information pieces repropagated in a real scenario.
* @param user the user.
* @return the stream of pieces repropagated by the user.
*/
public Stream getRealPropagatedPieces(U user)
{
if(this.users.containsObject(user))
{
int uidx = this.users.object2idx(user);
return this.realPropagated.getIdsSecond(uidx).map(tuple -> this.informationPieces.idx2object(tuple.getIdx()));
}
return Stream.empty();
}
/**
* Given a user, obtains the set of information pieces repropagated in a real scenario.
* @param user the user.
* @return the stream of pieces repropagated by the user and their timestamps.
*/
public Stream> getRealPropagatedPiecesWithTimestamp(U user)
{
if(this.users.containsObject(user))
{
int uidx = this.users.object2idx(user);
return this.realPropagated.getIdsSecond(uidx).map(tuple -> new Tuple2ol<>(this.informationPieces.idx2object(tuple.getIdx()), tuple.getValue()));
}
return Stream.empty();
}
/**
* Checks if a user repropagated or not an information piece.
* @param user the user.
* @param piece the piece.
* @return true if the user repropagated the piece, false if he/she did not.
*/
public boolean isRealRepropagatedPiece(U user, I piece)
{
if(this.users.containsObject(user) && this.informationPieces.containsObject(piece))
{
int uidx = this.users.object2idx(user);
int iidx = this.informationPieces.object2idx(piece);
return this.realPropagated.containsPair(uidx, iidx);
}
return false;
}
/**
* Obtains the timestamp for an information piece.
* @param user the user.
* @param info the piece.
* @return the timestamp if the user repropagated the piece, -1 if he/she did not.
*/
public long getRealPropagatedTimestamp(U user, I info)
{
if(this.isRealRepropagatedPiece(user, info))
{
int uidx = this.users.object2idx(user);
int iidx = this.informationPieces.object2idx(info);
return this.realPropagated.getValue(uidx, iidx);
}
return -1L;
}
/**
* Obtains the list of timestamps.
* @return the list of timestamps.
*/
public TreeSet getTimestamps()
{
return this.timestamps;
}
/**
* Obtains the list of pieces that a user has propagated in a given time.
* @param timestamp the timestamp.
* @param user the user.
* @return an stream containing the pieces propagated by the user at the given time.
*/
public Stream getPiecesByTimestamp(long timestamp, U user)
{
if(this.propagatedByTS.containsKey(timestamp) && this.propagatedByTS.get(timestamp).containsKey(user))
return this.propagatedByTS.get(timestamp).get(user).stream();
return Stream.empty();
}
/**
* Obtains the list of pieces which have been repropagated by a user at a given time.
* @param timestamp the timestamp.
* @param user the user.
* @return an stream containing the pieces repropagated by the user at the given time.
*/
public Stream getRealPropPiecesByTimestamp(long timestamp, U user)
{
if(this.realPropagatedByTS.containsKey(timestamp) && this.realPropagatedByTS.get(timestamp).containsKey(user))
return this.realPropagatedByTS.get(timestamp).get(user).stream();
return Stream.empty();
}
/**
* Obtains the list of users which have propagated pieces at a given time.
* @param timestamp the timestamp.
* @return a stream containing all users which have propagated information at the given time.
*/
public Stream getUsersByTimestamp(long timestamp)
{
if(this.propagatedByTS.containsKey(timestamp))
{
return this.propagatedByTS.get(timestamp).keySet().stream();
}
return Stream.empty();
}
/**
* Obtains the list of users which have repropagated pieces at a given time.
* @param timestamp the timestamp.
* @return a stream containing all users which have repropagated information at the given time.
*/
public Stream getRealPropUsersByTimestamp(long timestamp)
{
if(this.realPropagatedByTS.containsKey(timestamp))
{
return this.realPropagatedByTS.get(timestamp).keySet().stream();
}
return Stream.empty();
}
/**
* Obtains a string containing a summary of the data.
* @return The summary of the data.
*/
public String dataSummary()
{
StringBuilder summary = new StringBuilder();
summary.append("Graph:\n");
summary.append("\tNum. Nodes: ").append(this.graph.getVertexCount()).append("\n");
summary.append("\tNum. Edges: ").append(this.graph.getEdgeCount()).append("\n");
summary.append("Information:\n");
summary.append("\tNum. Pieces: ").append(this.informationPieces.getAllObjects().count()).append("\n");
summary.append("\tNum. Users with Info: ").append(this.users.getAllObjects().mapToInt(user -> this.getPieces(user).count() > 0 ? 1 : 0).sum()).append("\n");
summary.append("User Features:\n");
for(String name : this.userFeatureNames)
{
summary.append("\tname: ").append(name).append("\n");
summary.append("\t\tNum. values: ").append(this.features.get(name).numObjects()).append("\n");
summary.append("\t\tNum. relations: ").append(this.userFeatures.get(name).getAllFirst().mapToLong(u -> this.userFeatures.get(name).numSecond(u)).sum()).append("\n");
summary.append("\t\tNum. users with feat.: ").append(this.users.getAllObjects().mapToInt(user -> this.getUserFeatures(user, name).count() > 0 ? 1 : 0).sum()).append("\n");
}
summary.append("Information Pieces Features:\n");
for(String name : this.infoPiecesFeatureNames)
{
summary.append("\tname: ").append(name).append("\n");
summary.append("\t\tNum. values: ").append(this.features.get(name).numObjects()).append("\n");
summary.append("\t\tNum. relations: ").append(this.infoPiecesFeatures.get(name).getAllFirst().mapToLong(u -> this.infoPiecesFeatures.get(name).numSecond(u)).sum()).append("\n");
summary.append("\t\tNum. info. pieces with feat.: ").append(this.informationPieces.getAllObjects().mapToInt(info -> this.getInfoPiecesFeatures(info, name).count() > 0 ? 1 : 0).sum()).append("\n");
}
summary.append("Information Pieces real propagation");
{
summary.append("\tNum. users that propagate other pieces:").append(this.realPropagated.numFirst()).append("\n");
summary.append("\tNum. propagated info. pieces: ").append(this.realPropagated.numSecond()).append("\n");
summary.append("\tNum. propagations: ").append(this.realPropagated.getAllFirst().mapToLong(this.realPropagated::numSecond).sum()).append("\n");
}
return summary.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy