two step link

33 views
Skip to first unread message

Alexis EidelMan

unread,
May 8, 2013, 8:22:59 AM5/8/13
to liam2...@googlegroups.com
I'm stuck on the following issue.
I want to know a two step link person when the intermediate one had been removed.

I mean in case of grandfather, which is a two step link father.father, How can access him if he still alive but the father is no more in the database.
Obviously, there is no solution except create a one step link "grandfather" if the father is no more in database. But as it's very ad-hoc, I'm lookinf for an other solution which could prevent me to have 4 more variables and 8 more if I want an other generation (3-step link) + it's demand many lines in yaml.
The case of grandfathers may be easier as it is two many2one link. I also want to know grandchildren.

According to me, the lonely other option is to keep the father in a different entity when removed. It was suggested by Gaetan in an other topic.
But I still stuck.

I got something like that :

entities:
    person:
        fields:
            - pere:   int
            - mere:   int
         links:
            l_mere:     {type: many2one, target: person, field: mere}  # to know mother alive
            l_pere:     {type: many2one, target: person, field: pere}
            invl_mere:  {type: one2many, target: person, field: mere}  # to know children alive
            invl_pere:  {type: one2many, target: person, field: pere}
            invl_d_mere:  {type: one2many, target: dead, field: mere_d}  # to know dead children
            invl_d_pere:  {type: one2many, target: dead, field: pere_d}

dead:
        fields:  
            - pere_d:   {type: int, initialdata: false}
            - mere_d:   {type: int, initialdata: false}
        links:
            invl_l_mere:  {type: one2many, target: person, field: mere}      # to know alive children
            invl_l_pere:  {type: one2many, target: person, field: pere}
            l_d_mere:     {type: many2one, target: dead, field: mere_d}   # to know dead mother
            l_d_pere:     {type: many2one, target: dead, field: pere_d}
            invl_d_mere:  {type: one2many, target: dead, field: mere_d}  # to know dead children
            invl_d_pere:  {type: one2many, target: dead, field: pere_d}


And the process in case of a person death is:
                - conj: if(dead,                                       #the choice of conj is arbitrary, it changes only for dead who are removed)
                        new('dead',age=age,sexe=sexe,id=id,pere_d=pere,mere_d=mere,findet=findet),  
                        conj)
                - remove(dead)  

When in a process for entity 'dead' I try to count the number of alive children  invl_l_pere.count() it raise an error (see end of that email).
Do you see a solution ? In that way or in other.


Error :
    simulation.run(False)
  File "C:\Myliam2\src\simulation.py", line 366, in run
    self.processes, self.entities)
  File "C:\Myliam2\src\simulation.py", line 330, in simulate_period
    const_dict)
  File "C:\Myliam2\src\utils.py", line 56, in gettime
    res = func(*args, **kwargs)
  File "C:\Myliam2\src\process.py", line 123, in run_guarded
    utils.timed(v.run_guarded, simulation, const_dict)
  File "C:\Myliam2\src\utils.py", line 61, in timed
    elapsed, res = gettime(func, *args, **kwargs)
  File "C:\Myliam2\src\utils.py", line 56, in gettime
    res = func(*args, **kwargs)
  File "C:\Myliam2\src\process.py", line 24, in run_guarded
    self.run(context)
  File "C:\Myliam2\src\process.py", line 71, in run
    value = expr_eval(self.expr, context)
  File "C:\Myliam2\src\expr.py", line 168, in expr_eval
    return expr.evaluate(context)
  File "C:\Myliam2\src\links.py", line 188, in evaluate
    source_rows = id_to_rownum[source_ids]
IndexError: index 17997 is out of bounds for size 310

Gijs Dekkers

unread,
May 8, 2013, 10:29:04 AM5/8/13
to liam2...@googlegroups.com
I am not sure that I fully understand this, but it  looks as if you created a "dead" copy of a living person, at the moment of death of this person but _before_ you removed him or her. So, you made a zombie :-)
 
But by doing this, I do not think that circumvented the problem, because if you want to establish a link between the "zombie" and the living children, LIAM2 goes via the father. But he has been removed...
 
I see no solution, other than not removing the father until his children are dead too.
 
But Gaëtan surely will have a better solution. :-)
 
Gijs

Op woensdag 8 mei 2013 14:22:59 UTC+2 schreef Alexis EidelMan het volgende:

Gaëtan de Menten

unread,
May 14, 2013, 3:30:50 AM5/14/13
to liam2...@googlegroups.com

On 08/05/2013 14:22, Alexis EidelMan wrote:

> I'm stuck on the following issue.
> I want to know a two step link person when the intermediate one had been
> removed.
>
> I mean in case of grandfather, which is a two step link father.father,
> How can access him if he still alive but the father is no more in the
> database.

> Obviously, there is no solution except create a one step link
> "grandfather" if the father is no more in database. But as it's very
> ad-hoc, I'm lookinf for an other solution which could prevent me to have
> 4 more variables and 8 more if I want an other generation (3-step link)
> + it's demand many lines in yaml.

Yes, it is ugly, but it still seems like the best solution with the
current version.

> The case of grandfathers may be easier as it is two many2one link. I
> also want to know grandchildren.

Depending on what you want to do with the grand children, having a
direct link might be the only option at all (dead parents or not),
because you cannot combine several levels of one2many and aggregate at
that point: you need to aggregate at each level. For example, to compute
the average age of grand children, you would have to do something like:

children.sum(children.sum(age)) / children.sum(children.count())

This is somewhat ugly but should work. I fear some operations will be
harder (or even impossible) to translate to a "two step" aggregation
like this.

> According to me, the lonely other option is to keep the father in a
> different entity when removed. It was suggested by Gaetan in an other
> topic.

Well, this seems like even more work/trouble than the multiple-link
approach. It should be possible to use this method, but that will need a
lot (more) code.

The best solution in my opinion requires a new feature in liam2: support
for some kind of global filter that can be easily applied to all (or a
subset of) (sub)processes.

If that feature was present (feel free to implement it ;-)), you would
simply have a dead field and not actually remove the dead, but rather
filter them out for most processes. Of course, you can do this already
(by manually adding the filter everywhere) but it would be error-prone,
inefficient and would massively clutter your model.

Hope it helps,
Gaetan


----------------------------------------------------------------------------

Disclaimer: please see "www.plan.be/disclaimer.html"

Please consider your environmental responsibility before printing this email

----------------------------------------------------------------------------

Alexis EidelMan

unread,
May 15, 2013, 6:46:19 AM5/15/13
to liam2...@googlegroups.com
My idea evolved a little, instead or having an entity "dead", I create an entity register. In that base, I put every one, in the original base and append each new born. I keep intrinsic fields (gender), and links I need. Link with the corresponding entity is made by fields "id". So it is very easy since father in the register as the same id as in the relative entity.

The key difference between both is that I don't remove dead people in the register.
I have an "alive" fields alive: : (reg2pers.id>0)  where reg2pers is a linked from "register" to   {type: many2one, target: person, field: id}
So if I want to access the grandfather fields even if the father is dead I can do something like :
pers2reg.reg_father.reg_father.reg2pers.fields

It can be a solution for now. Note it would be also an answer to an other post as we could in that register keep life cycle information when before removing someone and about space disk, we could write on disk only the register of the last period.

By the, It should be in the dev-group, but using these two mirror entities, would be very more user friendly if it was possible to do something like.
pers2reg.alive : if(dead, False, True)
I mean change a fields of entity A through a link in a entity B process.
Gaetan already told me it wouldn't be too hard to enable that option. But, I think it need a very good and precise understanding of what a link is in Python and that only Gaetan can do it easily.

Alexis
Reply all
Reply to author
Forward
0 new messages