Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group entity #175

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d89dd45
Added structure for group entity
zugnachpankow May 2, 2022
ffc4927
Update group.py
zugnachpankow May 2, 2022
7aebe13
social_system
zugnachpankow May 13, 2022
710242a
typo cleanup
zugnachpankow May 31, 2022
1ffd331
Fix Social Update
zugnachpankow Jun 1, 2022
c0994c4
Implementing Individual to Group relationships via a group_membership…
zugnachpankow Jun 8, 2022
2895209
Implement Network Solution for Group Memberships
zugnachpankow Jun 8, 2022
9c473e1
Update run_groups_test_seven_dwarfs.py
zugnachpankow Jun 8, 2022
284b877
Merge remote-tracking branch 'origin/group_entity' into group_entity
zugnachpankow Jun 8, 2022
fbb26f6
Group now gets culture and further things over being part of a world.
zugnachpankow Jun 8, 2022
bdeb128
little fix
zugnachpankow Jun 8, 2022
9747ce5
run_group_test_seven_dwarfs.py now demonstrates minimum features of t…
zugnachpankow Jun 9, 2022
032528c
run_group_test_seven_dwarfs.py now demonstrates minimum features of t…
zugnachpankow Jun 13, 2022
b3bc2c6
- Change group from living in World to living in Culture
zugnachpankow Jun 16, 2022
4019e10
add/adjust documentation
zugnachpankow Jun 20, 2022
30409da
Added structure for group entity
zugnachpankow May 2, 2022
03ff3a0
Update group.py
zugnachpankow May 2, 2022
9b4aaa9
social_system
zugnachpankow May 13, 2022
f088423
typo cleanup
zugnachpankow May 31, 2022
329ab84
Implementing Individual to Group relationships via a group_membership…
zugnachpankow Jun 8, 2022
696eb74
Group now gets culture and further things over being part of a world.
zugnachpankow Jun 8, 2022
75580f4
little fix
zugnachpankow Jun 8, 2022
244a601
run_group_test_seven_dwarfs.py now demonstrates minimum features of t…
zugnachpankow Jun 9, 2022
53f58d9
run_group_test_seven_dwarfs.py now demonstrates minimum features of t…
zugnachpankow Jun 13, 2022
b602e71
- Change group from living in World to living in Culture
zugnachpankow Jun 16, 2022
07035ab
add/adjust documentation
zugnachpankow Jun 20, 2022
ae3024d
Merge remote-tracking branch 'origin/group_entity' into group_entity
zugnachpankow Jun 20, 2022
356df4b
- bypassed AttributeErrors in base implementation for group by gettin…
zugnachpankow Jul 28, 2022
76474cd
Add simple test function and plot groupmembership for a single dwarf …
zugnachpankow Aug 5, 2022
447b6b8
Make illustration study more clear
zugnachpankow Aug 10, 2022
34904c6
Make illustration study more clear
zugnachpankow Aug 11, 2022
bf446bf
resolve #175
zugnachpankow Nov 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ may not be sufficient and a distinction of social strata or other social groups
"indigenous people", "social democrats", a certain NGO, ...)
that is transverse to the former partitioning is helpful in addition.

For this, we will in the future provide an entity-type "group"
For this, the entity-type "group" is provided
which is meant to represent any grouping of individuals (that may come from one or several social systems)
by meaningful cultural or social-metabolic aspects.

Expand All @@ -33,16 +33,19 @@ Basic relationships to other entity-types

A group will usually...

- have several member :doc:`individuals<individual>`
- have several members :doc:`individuals<individual>`,
which is represented by a group membership directed network owned by the culture taxon

In addition, a group may...

- have one or several "leader" :doc:`individuals<individual>`,
- have an "intra" group network between members :doc:`individuals<individual>`

- have one or several "leader" :doc:`individuals<individual>`,
of which one may be the dominant leader

- have a "headquarters" :doc:`cell<cell>`

- be related to other groups via some network owned by the culture taxon
- be related to other groups via an "inter" network owned by the culture taxon
(which will typically interact with the network of personal acquaintance between member individuals)

- act as the current "elite" in some :doc:`social system<social system>`
Expand Down
3 changes: 3 additions & 0 deletions pycopancore/data_model/master_data_model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,8 @@
from .individual import Individual as I
from .individual import Individual as individual
from .individual import Individual
from .group import Group as G
from .group import Group as group
from .group import Group

from .. import unity
19 changes: 18 additions & 1 deletion pycopancore/data_model/master_data_model/culture.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,24 @@ class Culture:
scale='nominal',
datatype=set)



# group entity related networks

inter_group_network = \
Variable("inter group network",
"""Basic undirected social network between
Groups.""",
ref="https://en.wikipedia.org/wiki/Social_network#Meso_level",
scale='nominal',
datatype=Graph)

group_membership_network = \
Variable("group membership network",
"""Directed network from individual to group that
signifies membership (to avoid problems due to n to n relation)""",
scale='nominal',
datatype=DiGraph)

# socio-cultural traits that may occur on different levels:

is_environmentally_friendly = \
Expand Down
33 changes: 33 additions & 0 deletions pycopancore/data_model/master_data_model/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Master data model for group."""

"""https://github.com/pik-copan/pycopancore/blob/master/docs/framework_documentation/abstract_level/entity_types/group.rst"""
Copy link

@jnnsbrr jnnsbrr Oct 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not add absolute url paths to the code.


from .. import Variable

from networkx import Graph

class Group:

#TODO: specify edges

intra_group_network = \
Variable("intra group network",
"""Basic undirected social network between
Group members.""",
scale='nominal',
datatype=Graph)

has_leader = \
Variable("has a leader",
"whether the group has a leader",
scale="ordinal", levels=[False, True], default=False)

has_headquarter = \
Variable("has a headquarter",
"whether the group has a headquarter located in a cell",
scale="ordinal", levels=[False, True], default=False)





1 change: 1 addition & 0 deletions pycopancore/model_components/abstract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from .social_system import SocialSystem
from .cell import Cell
from .individual import Individual
from .group import Group

from .environment import Environment
from .metabolism import Metabolism
Expand Down
25 changes: 25 additions & 0 deletions pycopancore/model_components/abstract/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Abstract Group entity type class, inherited by base model component."""

# This file is part of pycopancore.
#
# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
# Impact Research
#
# URL: <http://www.pik-potsdam.de/copan/software>
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license

from ...private import _AbstractEntityMixin
from ...data_model import OrderedSet


class Group (_AbstractEntityMixin):
"""Abstract Group entity type class.

Inherited by base model component.
"""

variables = OrderedSet()
"""All variables occurring in this entity type"""


Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .social_system import SocialSystem
from .cell import Cell
from .individual import Individual
from .group import Group

from .environment import Environment
from .metabolism import Metabolism
Expand Down
19 changes: 17 additions & 2 deletions pycopancore/model_components/base/implementation/culture.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

from .. import interface as I

from networkx import Graph

from networkx import Graph, DiGraph

class Culture (I.Culture, abstract.Culture):
"""Culture process taxon mixin implementation class."""
Expand All @@ -25,6 +24,7 @@ class Culture (I.Culture, abstract.Culture):
def __init__(self,
*,
acquaintance_network=None,
group_membership_network=None,
**kwargs):
"""Initialize the unique instance of Culture.

Expand All @@ -33,6 +33,9 @@ def __init__(self,
acquaintance_network: Graph
The Network of acquaintances which is managed by Culture
(default is None)
group_membership_network: DiGraph
The Network between Individiuals and groups, which is managed
by Culture (default is None)
**kwargs
keyword arguments passed to super()

Expand All @@ -43,7 +46,14 @@ def __init__(self,
acquaintance_network = Graph()
assert isinstance(acquaintance_network, Graph)
self.acquaintance_network = acquaintance_network

if group_membership_network is None:
group_membership_network = DiGraph()
assert isinstance(group_membership_network, DiGraph)
self.group_membership_network = group_membership_network

self._worlds = set()
self._groups = set()

# make sure all variable values are valid:
self.assert_valid()
Expand All @@ -54,6 +64,11 @@ def worlds(self):
"""Get the set of all Worlds this Culture acts in."""
return self._worlds

@property # read-only
def groups(self):
"""Get the set of all Groups in this Culture."""
return self._groups

# no process-related methods

processes = [] # no processes in base
140 changes: 140 additions & 0 deletions pycopancore/model_components/base/implementation/group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
""" """

# This file is part of pycopancore.
#
# Copyright (C) 2016-2017 by COPAN team at Potsdam Institute for Climate
# Impact Research
#
# URL: <http://www.pik-potsdam.de/copan/software>
# Contact: core@pik-potsdam.de
# License: BSD 2-clause license

# only used in this component, not in others:
from ... import abstract
from .... import master_data_model as D
from ....private import unknown

from .. import interface as I


class Group (I.Group, abstract.Group):
"""Gropp entity type mixin implementation class.

Base component's Group mixin that every model must use in composing
their Group class. Inherits from I.Group as the interface with all
necessary variables and parameters.
"""

# standard methods:

def __init__(self,
*,
culture,
world,
**kwargs
):
"""Initialize an instance of Group.

Parameters
----------
culture: obj
Culture the Group belongs to
world: obj
World the Group belongs to (to bypass AttributeErrors for now)
**kwargs
keyword arguments passed to super()

"""
super().__init__(**kwargs) # must be the first line

# init and set variables implemented via properties:
self._culture = None
self.culture = culture
self._world = None
self.world = world

if self.culture:
self.culture.group_membership_network.add_node(self, type="Group", color="green")

def deactivate(self):
"""Deactivate a group.

In particular, deregister from all networks.

"""
# deregister from all networks:
if self.culture:
self.culture.group_membership_network.remove_node(self)
super().deactivate() # must be the last line

def reactivate(self):
"""Reactivate a group.

In particular, deregister with all mandatory networks.

"""
super().reactivate() # must be the first line
# reregister with all mandatory networks:
if self.culture:
self.culture.group_membership_network.add_node(self, type="Group", color="green")


# getters and setters for references:

#culture needs to be before world, as group gets its world etc. over its culture
@property
def culture(self):
"""Get culture group is part of."""
return self._culture

@culture.setter
def culture(self, c):
"""Set culture group is part of."""
if self._culture is not None:
# first deregister from previous culture's list of worlds:
self._culture.groups.remove(self)
if c is not None:
assert isinstance(c, I.Culture), \
"Culture must be taxon type Culture"
c._groups.add(self)
self._culture = c

@property
def world(self):
"""Get the World the Group is part of."""
return self._world

@world.setter
def world(self, w):
"""Set the World the Group is part of."""
if self._world is not None:
# first deregister from previous world's list of cells:
self._world.groups.remove(self)
assert isinstance(w, I.World), "world must be of entity type World"
w._groups.add(self)
self._world = w

# getters for backwards references and convenience variables:

@property # read-only
def environment(self):
"""Get the Environment of which the Group is a part."""
return self._world.environment

@property # read-only
def metabolism(self):
"""Get the Metabolism of which the Group is a part."""
return self._world.metabolism

@property
def group_members(self):
"""Get the set of Individuals associated with this Group."""
# return self.culture.group_membership_network.neighbors(self)
return self.culture.group_membership_network.predecessors(self) # .predecessors as network is directed from inds to groups


# no process-related methods

processes = [] # no processes in base


Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from .. import interface as I


class Individual (I.Individual, abstract.Individual):
"""Individual entity type mixin implementation class.

Expand Down Expand Up @@ -55,6 +54,7 @@ def __init__(self,
# register with all mandatory networks:
if self.culture:
self.culture.acquaintance_network.add_node(self)
self.culture.group_membership_network.add_node(self, type="Individual", color="yellow")

def deactivate(self):
"""Deactivate an individual.
Expand All @@ -65,6 +65,7 @@ def deactivate(self):
# deregister from all networks:
if self.culture:
self.culture.acquaintance_network.remove_node(self)
self.culture.group_membership_network.remove_node(self)
super().deactivate() # must be the last line

def reactivate(self):
Expand All @@ -77,6 +78,7 @@ def reactivate(self):
# reregister with all mandatory networks:
if self.culture:
self.culture.acquaintance_network.add_node(self)
self.culture.group_membership_network.add_node(self, type="Individual", color="yellow")

# getters and setters for references:

Expand Down Expand Up @@ -156,6 +158,11 @@ def acquaintances(self):
"""Get the set of Individuals the Individual is acquainted with."""
return self.culture.acquaintance_network.neighbors(self)

@property
def group_memberships(self):
"""Get the set of Groups the Individual is associated with."""
return self.culture.group_membership_network.neighbors(self) # .successors as network is directed from inds to groups

# no process-related methods

processes = [] # no processes in base