InfluenceDiffusion 0.0.11__tar.gz → 0.0.13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/Graph.py +29 -104
  2. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/estimation_models/BaseWeightEstimator.py +3 -4
  3. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/influence_models.py +6 -4
  4. influencediffusion-0.0.13/InfluenceDiffusion.egg-info/PKG-INFO +96 -0
  5. influencediffusion-0.0.13/PKG-INFO +96 -0
  6. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/setup.py +4 -2
  7. influencediffusion-0.0.11/InfluenceDiffusion.egg-info/PKG-INFO +0 -22
  8. influencediffusion-0.0.11/PKG-INFO +0 -22
  9. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/Trace.py +0 -0
  10. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/__init__.py +0 -0
  11. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/estimation_models/EMEstimation.py +0 -0
  12. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/estimation_models/OptimEstimation.py +0 -0
  13. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/estimation_models/__init__.py +0 -0
  14. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/utils.py +0 -0
  15. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion/weight_samplers.py +0 -0
  16. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion.egg-info/SOURCES.txt +0 -0
  17. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion.egg-info/dependency_links.txt +0 -0
  18. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion.egg-info/requires.txt +0 -0
  19. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/InfluenceDiffusion.egg-info/top_level.txt +0 -0
  20. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/LICENSE +0 -0
  21. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/README.md +0 -0
  22. {influencediffusion-0.0.11 → influencediffusion-0.0.13}/setup.cfg +0 -0
@@ -1,4 +1,3 @@
1
- import pandas as pd
2
1
  import numpy as np
3
2
  from typing import List, Tuple, Union, Dict
4
3
  import networkx as nx
@@ -7,67 +6,41 @@ __all__ = ["Graph"]
7
6
 
8
7
 
9
8
  class Graph(nx.DiGraph):
10
- def __init__(self, edge_list: List[Tuple[int, int]],
11
- directed: bool = True,
12
- weights: Union[np.array, List[float]] = None):
13
- """
14
- Initialize a directed or undirected graph from an edge list.
15
-
16
- Parameters
17
- ----------
18
- edge_list : List[Tuple[int, int]]
19
- List of tuples (source, sink) representing edges of the graph.
20
- directed : bool, optional
21
- Flag to indicate whether the graph is directed (default is True).
22
- weights : Union[None, List[float]], optional
23
- Optional weights for each edge. If None, all edges are assigned a weight of 1.
24
- """
25
- self.directed = directed
26
- self.edge_array = np.array(edge_list, dtype=int)
27
-
28
- if not self.directed:
29
- reverse_edge_array = self.edge_array[:, [1, 0]]
30
- self.edge_array = np.concatenate([self.edge_array, reverse_edge_array])
31
-
32
- super().__init__(self.edge_array.tolist())
33
-
34
- if weights is not None:
35
- assert len(weights) == len(edge_list), "number of edges is different from number of weights"
9
+ def __init__(self, incoming_graph_data=None, weights: Union[List, np.array] = None, **attr):
10
+ super().__init__(incoming_graph_data, **attr)
11
+ self.edge_array = np.array(self.edges)
12
+ if weights is None:
13
+ self.weights = np.ones(len(self.edges))
36
14
  else:
37
- weights = np.ones(len(edge_list))
38
- self.weights = np.array(weights) if directed else np.hstack([weights] * 2)
39
- self.edge_2_index = {tuple(edge): idx for idx, edge in enumerate(self.edge_array)}
15
+ assert len(weights) == self.count_edges(), "number of weights different from the number of edges"
16
+ self.weights = np.array(weights)
17
+ nx.set_edge_attributes(self, dict(zip(self.edges, self.weights)), "weight")
40
18
 
41
- def rename_graph_vertices(self, old_2_new_vertex_name_dict: Union[None, Dict] = None) -> "Graph":
42
- """
43
- Rename graph vertices according to the provided mapping or re-index them.
19
+ def add_edge(self, u_of_edge, v_of_edge, **attr):
20
+ super().add_edge(u_of_edge, v_of_edge, **attr)
21
+ self.edge_array = np.array(self.edges)
22
+ self.weights = self._get_edge_weight_attributes()
44
23
 
45
- Parameters
46
- ----------
47
- old_2_new_vertex_name_dict : Union[None, Dict], optional
48
- Mapping of old vertex names to new names.
49
- If None, re-indexes vertices to [0, 1, ..., |V|-1].
24
+ def add_edges_from(self, ebunch_to_add, **attr):
25
+ super().add_edges_from(ebunch_to_add, **attr)
26
+ self.edge_array = np.array(self.edges)
27
+ self.weights = self._get_edge_weight_attributes()
50
28
 
51
- Returns
52
- -------
53
- Graph
54
- The updated graph instance with renamed vertices.
55
- """
56
- if old_2_new_vertex_name_dict is None:
57
- old_vertex_names = sorted(list(self.get_vertices()))
58
- old_2_new_vertex_name_dict = {name: idx for idx, name in enumerate(old_vertex_names)}
29
+ def add_weighted_edges_from(self, ebunch_to_add, weight='weight', **attr):
30
+ super().add_weighted_edges_from(ebunch_to_add, weight=weight, **attr)
31
+ self.edge_array = np.array(self.edges)
32
+ self.weights = self._get_edge_weight_attributes()
59
33
 
60
- self.edge_array[:, 0] = list(map(lambda v: old_2_new_vertex_name_dict[v], self.edge_array[:, 0]))
61
- self.edge_array[:, 1] = list(map(lambda v: old_2_new_vertex_name_dict[v], self.edge_array[:, 1]))
62
- return self
34
+ def _get_edge_weight_attributes(self):
35
+ return np.array([edge[2] for edge in self.edges.data("weight", default=1)])
63
36
 
64
- def set_weights(self, weights: Union[str, np.array]) -> "Graph":
37
+ def set_weights(self, weights: Union[List, np.array]) -> "Graph":
65
38
  """
66
39
  Set weights for the edges in the graph.
67
40
 
68
41
  Parameters
69
42
  ----------
70
- weights : Union[str, np.array]
43
+ weights : Union[list, np.array]
71
44
  Array of weights for the edges.
72
45
 
73
46
  Returns
@@ -81,7 +54,8 @@ class Graph(nx.DiGraph):
81
54
  If the number of weights does not match the number of edges.
82
55
  """
83
56
  assert len(weights) == self.count_edges(), "number of weights different from the number of edges"
84
- self.weights = np.array(weights)
57
+ nx.set_edge_attributes(self, dict(zip(self.edges, weights)), 'weight')
58
+ self.weights = self._get_edge_weight_attributes()
85
59
  return self
86
60
 
87
61
  def get_edges(self, as_array: bool = False) -> Union[np.array, List[Tuple[int, int]]]:
@@ -100,7 +74,7 @@ class Graph(nx.DiGraph):
100
74
  """
101
75
  if as_array:
102
76
  return self.edge_array
103
- return [tuple(edge) for edge in self.edge_array]
77
+ return list(self.edges)
104
78
 
105
79
  def get_vertices(self) -> set:
106
80
  """
@@ -144,7 +118,7 @@ class Graph(nx.DiGraph):
144
118
  int
145
119
  The total number of edges.
146
120
  """
147
- return len(self.edge_array)
121
+ return len(self.edges)
148
122
 
149
123
  def count_vertices(self) -> int:
150
124
  """
@@ -155,7 +129,7 @@ class Graph(nx.DiGraph):
155
129
  int
156
130
  The total number of vertices.
157
131
  """
158
- return len(self.get_vertices())
132
+ return len(self.nodes)
159
133
 
160
134
  def get_children_mask(self, vertex: int) -> np.array:
161
135
  """
@@ -392,38 +366,6 @@ class Graph(nx.DiGraph):
392
366
  """
393
367
  return np.mean(self.get_all_indegrees(weighted))
394
368
 
395
- def get_edge_index(self, edge: Tuple[int, int]) -> int:
396
- """
397
- Get the index of a specified edge.
398
-
399
- Parameters
400
- ----------
401
- edge : Tuple[int, int]
402
- The edge for which to find the index.
403
-
404
- Returns
405
- -------
406
- int
407
- The index of the edge in the graph.
408
- """
409
- return self.edge_2_index[tuple(edge)]
410
-
411
- def get_edge_weight(self, edge: Tuple[int, int]) -> float:
412
- """
413
- Get the weight of a specified edge.
414
-
415
- Parameters
416
- ----------
417
- edge : Tuple[int, int]
418
- The edge for which to retrieve the weight.
419
-
420
- Returns
421
- -------
422
- float
423
- The weight of the edge.
424
- """
425
- return self.weights[self.get_edge_index(edge)]
426
-
427
369
  def get_edges_mask_from_set_to_vertex(self, vertex_set: set, vertex: int) -> np.array:
428
370
  """
429
371
  Create a mask for edges leading from a set of vertices to a specified vertex.
@@ -445,23 +387,6 @@ class Graph(nx.DiGraph):
445
387
  parent_edges_mask[parent_edges_mask] = [(parent in vertex_set) for parent in parent_vertices]
446
388
  return parent_edges_mask
447
389
 
448
- def get_adj_matrix(self) -> np.array:
449
- """
450
- Generate the adjacency matrix of the graph.
451
-
452
- Returns
453
- -------
454
- np.array
455
- The adjacency matrix as a numpy array.
456
- """
457
- vertices = list(self.get_vertices())
458
- n_vertex = len(vertices)
459
- adj_matrix = pd.DataFrame(np.zeros((n_vertex, n_vertex)), columns=vertices, index=vertices)
460
- for (v1, v2), weight in zip(self.edge_array, self.weights):
461
- adj_matrix.at[v1, v2] = weight
462
-
463
- return adj_matrix
464
-
465
390
  def is_edge_in_graph(self, edge: Tuple[int, int]) -> bool:
466
391
  """
467
392
  Check if a specified edge exists in the graph.
@@ -2,7 +2,6 @@ from typing import List, Union, Dict
2
2
  import os
3
3
  import pickle
4
4
  import numpy as np
5
- from tqdm import tqdm
6
5
  from joblib import Parallel, delayed
7
6
  from scipy.stats import uniform
8
7
  from scipy.stats._distn_infrastructure import rv_frozen
@@ -144,13 +143,13 @@ class BaseWeightEstimator:
144
143
  vertex_2_active_parent_mask_t = {vertex: [] for vertex in self.informative_vertices}
145
144
  failed_vertices_masks = {vertex: [] for vertex in self.informative_vertices}
146
145
 
147
- for vertex, vertex_pseudo_traces in tqdm(traces.items()):
146
+ for vertex, vertex_pseudo_traces in traces.items():
148
147
  for vertices_tm1, new_vertices_t in vertex_pseudo_traces:
149
148
  parents = self.graph.get_parents(vertex, out_type=np.array)
150
- active_parents_mask_tm1 = np.in1d(parents, np.array(list(vertices_tm1)))
149
+ active_parents_mask_tm1 = np.isin(parents, np.array(list(vertices_tm1)))
151
150
  if new_vertices_t:
152
151
  vertices_t = vertices_tm1 | new_vertices_t
153
- active_parents_mask_t = np.in1d(parents, np.array(list(vertices_t)))
152
+ active_parents_mask_t = np.isin(parents, np.array(list(vertices_t)))
154
153
  vertex_2_active_parent_mask_tm1[vertex].append(active_parents_mask_tm1)
155
154
  vertex_2_active_parent_mask_t[vertex].append(active_parents_mask_t)
156
155
  else:
@@ -48,6 +48,7 @@ class InfluenceModel:
48
48
  self.vertices = list(self.g.get_vertices())
49
49
  self.random_state = random_state
50
50
  self.n_jobs = n_jobs
51
+ self._edge_2_index = {edge: idx for idx, edge in enumerate(g.edges)}
51
52
  if check_init:
52
53
  self.check_param_init_correctness()
53
54
 
@@ -179,7 +180,7 @@ class InfluenceModel:
179
180
  self._pre_simulation_init(seed_set, simulation_rvs=simulation_rvs)
180
181
  return self._simulate_trace(out_trace_type=out_trace_type)
181
182
 
182
- def make_simulation(self, seed_set: Set[int], simulation_rvs=None) -> np.ndarray:
183
+ def make_simulation(self, seed_set: Set[int], simulation_rvs=None) -> Union[Trace, List[Set[int]]]:
183
184
  """Run a simulation and return the propagation trace.
184
185
 
185
186
  Parameters
@@ -219,7 +220,8 @@ class InfluenceModel:
219
220
  seed_sets = self._sample_seeds(n_seeds=n_traces, seed_size_range=seed_size_range)
220
221
  return self.sample_traces_from_seeds(seed_sets, out_trace_type=out_trace_type)
221
222
 
222
- def sample_traces_from_seeds(self, seed_sets: List[Set[int]], out_trace_type: bool = True) -> Union[Traces, List[List[Set[int]]]]:
223
+ def sample_traces_from_seeds(self, seed_sets: List[Set[int]],
224
+ out_trace_type: bool = True) -> Union[Traces, List[List[Set[int]]]]:
223
225
  """Sample traces from a list of seed sets.
224
226
 
225
227
  Parameters
@@ -441,7 +443,7 @@ class LTM(InfluenceModel):
441
443
  bool
442
444
  True if the adjacent vertex is influenced, otherwise False.
443
445
  """
444
- self.vertex_2_influence_counter[v_adj] += self.g.get_edge_weight((v, v_adj))
446
+ self.vertex_2_influence_counter[v_adj] += self.g.get_edge_data(v, v_adj)["weight"]
445
447
  return self.vertex_2_threshold[v_adj] <= self.vertex_2_influence_counter[v_adj]
446
448
 
447
449
  def check_param_init_correctness(self, eps: float = 1e-6) -> None:
@@ -574,7 +576,7 @@ class ICM(InfluenceModel):
574
576
  bool
575
577
  True if the adjacent vertex is influenced, otherwise False.
576
578
  """
577
- return self.edge_activations[self.g.get_edge_index((v, v_adj))]
579
+ return self.edge_activations[self._edge_2_index[(v, v_adj)]]
578
580
 
579
581
  def _generate_simulation_rvs(self, n_runs: int = 1) -> List:
580
582
  """Generate random activations for edges.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: InfluenceDiffusion
3
+ Version: 0.0.13
4
+ Summary: InfluenceDiffusion package
5
+ Author: Alexander Kagan
6
+ Author-email: <amkagan@umich.edu>
7
+ Keywords: python,Influence Maximization,Network diffusion models,General Linear Threshold model,Social Networks,Independent Cascade model
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: Programming Language :: Python :: 2
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: MacOS :: MacOS X
13
+ Classifier: Operating System :: Microsoft :: Windows
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy
17
+ Requires-Dist: scipy
18
+ Requires-Dist: networkx
19
+ Requires-Dist: typing
20
+ Requires-Dist: joblib
21
+
22
+
23
+ # InfluenceDiffusion
24
+
25
+ InfluenceDiffusion is a Python library that provides instruments for working with influence diffusion models on graphs. In particular, it contains implementations of
26
+ - Popular diffusion models such as Independent Cascade, (General) Linear Threshold, etc.
27
+ - Methods for estimating parameters of these models
28
+
29
+
30
+ ## Installation
31
+
32
+ Use the package manager [pip](https://pip.pypa.io/en/stable/) to install InfluenceDiffusion.
33
+
34
+ ```bash
35
+ pip install InfluenceDiffusion
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ # Imports
42
+ import matplotlib.pyplot as plt
43
+ from networkx import erdos_renyi_graph
44
+
45
+ from InfluenceDiffusion.Graph import Graph # class inheriting from nx.DiGraph
46
+ from InfluenceDiffusion.influence_models import LTM
47
+ from InfluenceDiffusion.estimation_models.EMEstimation import LTWeightEstimatorEM
48
+ from InfluenceDiffusion.weight_samplers import make_random_weights_with_indeg_constraint
49
+
50
+ # Sample an Erdos-Renyi graph
51
+ g_nx = erdos_renyi_graph(50, p=0.1, directed=True)
52
+ g = Graph(edge_list=g_nx.edges)
53
+
54
+ # Set ground-truth LT model edge weights (in-degree of each node is at most 1)
55
+ weights = make_random_weights_with_indeg_constraint(g, indeg_ub=1)
56
+ g.set_weights(weights)
57
+
58
+ # Sample traces from an LT model on this graph
59
+ ltm = LTM(g)
60
+ traces = ltm.sample_traces(1000)
61
+
62
+ # Estimate the weights using the traces
63
+ ltm_estimator = LTWeightEstimatorEM(g)
64
+ pred_weights = ltm_estimator.fit(traces)
65
+
66
+ # Compare with the ground-truth weights
67
+ plt.scatter(weights, pred_weights)
68
+ plt.plot([0, 1], [0, 1], linestyle='--', c='black')
69
+ plt.xlabel("True weights")
70
+ plt.ylabel("Predicted weights")
71
+ plt.show()
72
+ ```
73
+
74
+ ## License
75
+
76
+ MIT License
77
+
78
+ Copyright (c) 2024 Alexander Kagan
79
+
80
+ Permission is hereby granted, free of charge, to any person obtaining a copy
81
+ of this software and associated documentation files (the "Software"), to deal
82
+ in the Software without restriction, including without limitation the rights
83
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84
+ copies of the Software, and to permit persons to whom the Software is
85
+ furnished to do so, subject to the following conditions:
86
+
87
+ The above copyright notice and this permission notice shall be included in all
88
+ copies or substantial portions of the Software.
89
+
90
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
95
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
96
+ SOFTWARE.
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.1
2
+ Name: InfluenceDiffusion
3
+ Version: 0.0.13
4
+ Summary: InfluenceDiffusion package
5
+ Author: Alexander Kagan
6
+ Author-email: <amkagan@umich.edu>
7
+ Keywords: python,Influence Maximization,Network diffusion models,General Linear Threshold model,Social Networks,Independent Cascade model
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Education
10
+ Classifier: Programming Language :: Python :: 2
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: MacOS :: MacOS X
13
+ Classifier: Operating System :: Microsoft :: Windows
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy
17
+ Requires-Dist: scipy
18
+ Requires-Dist: networkx
19
+ Requires-Dist: typing
20
+ Requires-Dist: joblib
21
+
22
+
23
+ # InfluenceDiffusion
24
+
25
+ InfluenceDiffusion is a Python library that provides instruments for working with influence diffusion models on graphs. In particular, it contains implementations of
26
+ - Popular diffusion models such as Independent Cascade, (General) Linear Threshold, etc.
27
+ - Methods for estimating parameters of these models
28
+
29
+
30
+ ## Installation
31
+
32
+ Use the package manager [pip](https://pip.pypa.io/en/stable/) to install InfluenceDiffusion.
33
+
34
+ ```bash
35
+ pip install InfluenceDiffusion
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ # Imports
42
+ import matplotlib.pyplot as plt
43
+ from networkx import erdos_renyi_graph
44
+
45
+ from InfluenceDiffusion.Graph import Graph # class inheriting from nx.DiGraph
46
+ from InfluenceDiffusion.influence_models import LTM
47
+ from InfluenceDiffusion.estimation_models.EMEstimation import LTWeightEstimatorEM
48
+ from InfluenceDiffusion.weight_samplers import make_random_weights_with_indeg_constraint
49
+
50
+ # Sample an Erdos-Renyi graph
51
+ g_nx = erdos_renyi_graph(50, p=0.1, directed=True)
52
+ g = Graph(edge_list=g_nx.edges)
53
+
54
+ # Set ground-truth LT model edge weights (in-degree of each node is at most 1)
55
+ weights = make_random_weights_with_indeg_constraint(g, indeg_ub=1)
56
+ g.set_weights(weights)
57
+
58
+ # Sample traces from an LT model on this graph
59
+ ltm = LTM(g)
60
+ traces = ltm.sample_traces(1000)
61
+
62
+ # Estimate the weights using the traces
63
+ ltm_estimator = LTWeightEstimatorEM(g)
64
+ pred_weights = ltm_estimator.fit(traces)
65
+
66
+ # Compare with the ground-truth weights
67
+ plt.scatter(weights, pred_weights)
68
+ plt.plot([0, 1], [0, 1], linestyle='--', c='black')
69
+ plt.xlabel("True weights")
70
+ plt.ylabel("Predicted weights")
71
+ plt.show()
72
+ ```
73
+
74
+ ## License
75
+
76
+ MIT License
77
+
78
+ Copyright (c) 2024 Alexander Kagan
79
+
80
+ Permission is hereby granted, free of charge, to any person obtaining a copy
81
+ of this software and associated documentation files (the "Software"), to deal
82
+ in the Software without restriction, including without limitation the rights
83
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84
+ copies of the Software, and to permit persons to whom the Software is
85
+ furnished to do so, subject to the following conditions:
86
+
87
+ The above copyright notice and this permission notice shall be included in all
88
+ copies or substantial portions of the Software.
89
+
90
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
95
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
96
+ SOFTWARE.
@@ -1,8 +1,10 @@
1
1
  from setuptools import setup, find_packages
2
+ from pathlib import Path
3
+ this_directory = Path(__file__).parent
4
+ LONG_DESCRIPTION = (this_directory / "README.md").read_text()
2
5
 
3
- VERSION = '0.0.11'
6
+ VERSION = '0.0.13'
4
7
  DESCRIPTION = 'InfluenceDiffusion package'
5
- LONG_DESCRIPTION = 'In this package, we implement popular network diffusion models and methods for their estimation.'
6
8
 
7
9
  setup(
8
10
  name="InfluenceDiffusion",
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: InfluenceDiffusion
3
- Version: 0.0.11
4
- Summary: InfluenceDiffusion package
5
- Author: Alexander Kagan
6
- Author-email: <amkagan@umich.edu>
7
- Keywords: python,Influence Maximization,Network diffusion models,General Linear Threshold model,Social Networks,Independent Cascade model
8
- Classifier: Development Status :: 3 - Alpha
9
- Classifier: Intended Audience :: Education
10
- Classifier: Programming Language :: Python :: 2
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Operating System :: MacOS :: MacOS X
13
- Classifier: Operating System :: Microsoft :: Windows
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: numpy
17
- Requires-Dist: scipy
18
- Requires-Dist: networkx
19
- Requires-Dist: typing
20
- Requires-Dist: joblib
21
-
22
- In this package, we implement popular network diffusion models and methods for their estimation.
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: InfluenceDiffusion
3
- Version: 0.0.11
4
- Summary: InfluenceDiffusion package
5
- Author: Alexander Kagan
6
- Author-email: <amkagan@umich.edu>
7
- Keywords: python,Influence Maximization,Network diffusion models,General Linear Threshold model,Social Networks,Independent Cascade model
8
- Classifier: Development Status :: 3 - Alpha
9
- Classifier: Intended Audience :: Education
10
- Classifier: Programming Language :: Python :: 2
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Operating System :: MacOS :: MacOS X
13
- Classifier: Operating System :: Microsoft :: Windows
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: numpy
17
- Requires-Dist: scipy
18
- Requires-Dist: networkx
19
- Requires-Dist: typing
20
- Requires-Dist: joblib
21
-
22
- In this package, we implement popular network diffusion models and methods for their estimation.