Discussion:
[PEAK] trellis attrs
nicky van foreest
2011-09-29 20:53:13 UTC
Permalink
Hi,

I would like to have an trellis.component with a trellis.set as one of
its attributes. For instance, (stupid example) suppose a child's first
names will be the first names of all its uncles and aunts. Then I
don't know beforehand how many names the child will get, so I cannot
specify a fixed number of attrs at the beginning of the
trellis.component that represents a child. I tried to achieve this by
using a trellis.set, but then it turns out that each child gets the
same trellis.set, rather than its own. Is there some other way to
resolve this?

Thanks.

Nicky
PJ Eby
2011-09-29 22:57:11 UTC
Permalink
Post by nicky van foreest
Hi,
I would like to have an trellis.component with a trellis.set as one of
its attributes. For instance, (stupid example) suppose a child's first
names will be the first names of all its uncles and aunts. Then I
don't know beforehand how many names the child will get, so I cannot
specify a fixed number of attrs at the beginning of the
trellis.component that represents a child. I tried to achieve this by
using a trellis.set, but then it turns out that each child gets the
same trellis.set, rather than its own. Is there some other way to
resolve this?
You'll need to give a more concrete example, preferably including some code.
So far, I have no idea what it is that you're trying to do. (It sounds
like you're saying you want one attribute, but then later it sounds like you
want more than one attribute, and at one place it sounds like you want a set
that's derived from some other set, and then... I'm not sure what you want.
;-) )
Post by nicky van foreest
Thanks.
Nicky
_______________________________________________
PEAK mailing list
http://www.eby-sarna.com/mailman/listinfo/peak
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eby-sarna.com/pipermail/peak/attachments/20110929/ef1c7b5c/attachment.html
nicky van foreest
2011-09-30 13:05:40 UTC
Permalink
Dear Philip,

Thanks your answer, and sorry for the confusion. Hopefully the
following is a more illustrative example. It originates from a problem
of one of my students who is doing simulations on job schedules.

There are two jobs j1 and j2. Job j1 consists of tasks t11 and t12,
and job j2 of tasks t21 and t22. There is a machine that processes
these tasks as batches. Suppose a schedule is like this. The first
batch consists of task t11, the second batch of tasks t12 and t21, and
the third batch of task t22. Batches have to be served by the machine
in sequence, and a batch can only start when the previous batch in
finished. Thus, for instance, before batch 3 can start, all tasks in
batch 2 have to be finished. Given processing times for each task, I
need to compute the total completion time of all jobs.

I would like to implemented this with trellis, because this allows me
to formulate the problem in the form of a recursion. A batch can only
start when all previous tasks related to the jobs in the batch have
been finished (in the example of batch 3, this set of previous tasks
consists of task 21), and the starting time of a batch is the latest
finish time of all these previous tasks. Then the finish time of a
batch is its starting time plus its processing time, and the finish
times of all tasks in a batch are equal to the finish time of the
batch, and so forth. Moreover, if I change a processing time of some
task, the effect of this will be automatically propagated by trellis.
So all in all, I can write neat, nice and concise code, and let
trellis handle the hard parts.

Now it comes to implementing a batch. I had in mind to implement the
set of previous tasks (of a batch) as a trellis set, because if I add
another task to a batch, the set of previous tasks will be affected,
hence a lot of starting and finish times need to be updated (which I
would like to be handled by trellis). I tried the following, but this
failed.

class Batch(trellis.Component):
trellis.attrs(
prevs = trellis.Set([],
duration = 0,
)

...

The problem is that all batches use the same trellis.Set, but I want
each batch to have its own trellis.Set. How can I achieve this? Or
otherwise, suppose the set of previous tasks and batch tasks are
implemented in the form of regular python sets. How can I use trellis
to update the entire schedule (and all involved times) when I add or
remove tasks from the set of batch tasks? (I know that removing an
item from a trellis.set is impossible. For that reason I actually
would prefer to use regular sets, rather than trellis sets. )

Nicky
Post by PJ Eby
Post by nicky van foreest
Hi,
I would like to have an trellis.component with a trellis.set as one of
its attributes. For instance, (stupid example) suppose a child's first
names will be the first names of all its uncles and aunts. Then I
don't know beforehand how many names the child will get, so I cannot
specify a fixed number of attrs at the beginning of the
trellis.component that represents a child. I tried to achieve this by
using a trellis.set, but then it turns out that each child gets the
same trellis.set, rather than its own. Is there some other way to
resolve this?
You'll need to give a more concrete example, preferably including some code.
?So far, I have no idea what it is that you're trying to do. ?(It sounds
like you're saying you want one attribute, but then later it sounds like you
want more than one attribute, and at one place it sounds like you want a set
that's derived from some other set, and then... ?I'm not sure what you want.
?;-) )
Post by nicky van foreest
Thanks.
Nicky
_______________________________________________
PEAK mailing list
http://www.eby-sarna.com/mailman/listinfo/peak
Lloyd Kvam
2011-09-30 13:39:16 UTC
Permalink
Post by nicky van foreest
trellis.attrs(
prevs = trellis.Set([],
duration = 0,
)
...
The problem is that all batches use the same trellis.Set, but I want
each batch to have its own trellis.Set.
The trellis.Set is getting assigned as a class variable. With immutable
types, this works as you'd expect, and the objects will get their own
object references when you assign new values. If prevs were an integer,
assigning to to b3.prevs would work as you want.

Try:

b3 = Batch( prevs=trellis.Set([]) )

I think that's the correct way to approach what you're trying to do. I
trust PJE will set things straight if I'm pushing you in the wrong
direction. My experience with Trellis is quite limited.
--
Lloyd Kvam
Venix Corp
DLSLUG/GNHLUG library
http://dlslug.org/library.html
http://www.librarything.com/catalog/dlslug
http://www.librarything.com/catalog/dlslug&sort=stamp
http://www.librarything.com/rss/recent/dlslug
nicky van foreest
2011-09-30 19:52:24 UTC
Permalink
Hi,
Post by Lloyd Kvam
b3 = Batch( prevs=trellis.Set([]) )
I think that's the correct way to approach what you're trying to do. ?I
trust PJE will set things straight if I'm pushing you in the wrong
direction. ?My experience with Trellis is quite limited.
Thanks very much for your answer. I'll try this, and the idea of
Philip in the other mail, and see whether these ideas work for my
case.

Nicky
Lloyd Kvam
2011-09-30 20:31:08 UTC
Permalink
Post by nicky van foreest
Hi,
Post by Lloyd Kvam
b3 = Batch( prevs=trellis.Set([]) )
I think that's the correct way to approach what you're trying to do. I
trust PJE will set things straight if I'm pushing you in the wrong
direction. My experience with Trellis is quite limited.
Thanks very much for your answer. I'll try this, and the idea of
Philip in the other mail, and see whether these ideas work for my
case.
Stick with Phillip's recommendation of using trellis.make. That's
designed to produce a new Set each time you create an object. It's much
less error prone than remembering to specify a new set each time you
create an object.
--
Lloyd Kvam
Venix Corp
DLSLUG/GNHLUG library
http://dlslug.org/library.html
http://www.librarything.com/catalog/dlslug
http://www.librarything.com/catalog/dlslug&sort=stamp
http://www.librarything.com/rss/recent/dlslug
PJ Eby
2011-09-30 20:32:03 UTC
Permalink
Post by nicky van foreest
Hi,
Post by Lloyd Kvam
b3 = Batch( prevs=trellis.Set([]) )
I think that's the correct way to approach what you're trying to do. I
trust PJE will set things straight if I'm pushing you in the wrong
direction. My experience with Trellis is quite limited.
Thanks very much for your answer. I'll try this, and the idea of
Philip in the other mail, and see whether these ideas work for my
case.
They will actually work together. If you do what I said, then you can also
pass in a specific set as Lloyd suggests... there's just no need to unless
you want to use a specific set instead of having a empty default set
created.
Post by nicky van foreest
"Trellis Set objects offer nearly all the comforts of the Python
standard library's sets.Set objects (minus .pop(), and support for
sets of mutable sets), but with observability:""
Yes, it just means you can't pop() items from a set, not that you can't,
say, .remove() them.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eby-sarna.com/pipermail/peak/attachments/20110930/7e4984c2/attachment.html
nicky van foreest
2011-09-30 21:16:51 UTC
Permalink
They will actually work together. ?If you do what I said, then you can also
pass in a specific set as Lloyd suggests... ?there's just no need to unless
you want to use a specific set instead of having a empty default set
created.
Ok. Thanks.

Sorry to bug you, but I tried also the following:

class Step(trellis.Component):
duration = trellis.attr(0)

def __init__(self, machine):
self.machine = machine
self.prevs = trellis.Set([])

instead of

class Step(trellis.Component):
prevs = trellis.make(trellis.Set)
duration = trellis.attr(0)

def __init__(self, machine):
self.machine = machine

This also works (that is, I get the same schedule in both cases). Is
there a difference between the two implementations? The second
implementation sets prevs as a class variable, but this does not
appear necessary (telling from implementation 1).

Nicky
PJ Eby
2011-09-30 22:17:46 UTC
Permalink
Post by PJ Eby
duration = trellis.attr(0)
self.machine = machine
self.prevs = trellis.Set([])
instead of
prevs = trellis.make(trellis.Set)
duration = trellis.attr(0)
self.machine = machine
This also works (that is, I get the same schedule in both cases). Is
there a difference between the two implementations?
The reason that your code currently *appears* to work is because you're not
changing the value of 'prevs' at runtime.

If at some point you did, say, "someStep.prevs = trellis.Set(somedata)",
your program would break because none of the listeners of someStep.prevs
would notice the change. That's why you should always declare your
attributes using trellis.* descriptors.

The more "correct" (trellisthonic?) way to write your code above is:

class Step(trellis.Component):
duration = trellis.attr(0)
prevs = trellis.make(trellis.Set)
machine = None
# No __init__ method necessary!

That is, there's no reason to have an __init__ method at all, since
trellis.Component() already takes keyword arguments and assigns them to
attributes, as long as they are defined in the class.
Post by PJ Eby
The second
implementation sets prevs as a class variable, but this does not
appear necessary (telling from implementation 1).
Please note that 'prevs' is *not* a "class variable". It's a descriptor.
That is, Step.prevs is a descriptor object, but someStep.prevs (where
someStep is an instance of Step) will be a distinct trellis.Set() instance,
unless overridden when created (e.g. via "someStep=Step(prevs=...)").
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eby-sarna.com/pipermail/peak/attachments/20110930/1b5ad8a4/attachment-0001.html
nicky van foreest
2011-10-01 19:26:14 UTC
Permalink
Thank you very much for your explanations.
Please note that 'prevs' is *not* a "class variable".? It's a descriptor.
That is, Step.prevs is a descriptor object, but someStep.prevs (where
someStep is an instance of Step) will be a distinct trellis.Set() instance,
unless overridden when created (e.g. via "someStep=Step(prevs=...)").
I never read about python descriptors before, and even didn't know
such a thing exists. Do you perhaps of one particular book/source that
can be of help in this direction?

Nicky
nicky van foreest
2011-10-02 19:17:24 UTC
Permalink
Thanks for the ref.

NIcky
Post by nicky van foreest
I never read about python descriptors before, and even didn't know
such a thing exists. Do you perhaps of one particular book/source that
can be of help in this direction?
?http://docs.python.org/howto/descriptor.html
--
jean? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? . .. .... //\\\oo///\\
P.J. Eby
2011-09-30 22:31:37 UTC
Permalink
Post by PJ Eby
duration = trellis.attr(0)
self.machine = machine
self.prevs = trellis.Set([])
instead of
prevs = trellis.make(trellis.Set)
duration = trellis.attr(0)
self.machine = machine
This also works (that is, I get the same schedule in both cases). Is
there a difference between the two implementations?
The reason that your code currently *appears* to work is because
you're not changing the value of 'prevs' at runtime.

If at some point you did, say, "someStep.prevs =
trellis.Set(somedata)", your program would break because none of the
listeners of someStep.prevs would notice the change. That's why you
should always declare your attributes using trellis.* descriptors.

The more "correct" (trellisthonic?) way to write your code above is:

class Step(trellis.Component):
duration = trellis.attr(0)
prevs = trellis.make(trellis.Set)
machine = None
# No __init__ method necessary!

That is, there's no reason to have an __init__ method at all, since
trellis.Component() already takes keyword arguments and assigns them
to attributes, as long as they are defined in the class.
Post by PJ Eby
The second implementation sets prevs as a class variable, but this does not
appear necessary (telling from implementation 1).
Please note that 'prevs' is *not* a "class variable". It's a
descriptor. That is, Step.prevs is a descriptor object, but
someStep.prevs (where someStep is an instance of Step) will be a
distinct trellis.Set() instance, unless overridden when created (e.g.
via "someStep=Step(prevs=...)").
PJ Eby
2011-09-30 17:57:07 UTC
Permalink
I tried the following, but this failed.
trellis.attrs(
prevs = trellis.Set([],
duration = 0,
)
...
The problem is that all batches use the same trellis.Set, but I want
each batch to have its own trellis.Set. How can I achieve this?
I'll go ahead and just answer this bit, because it's the part I can
understand without more detailed study. Hopefully it'll get you what you
need. ;-)

Do this:

class Batch(trellis.Component):
prevs = trellis.make(trellis.Set)
duration = trellis.attr(0)
(I know that removing an item from a trellis.set is impossible.
Uh, what? Where'd you get that idea?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eby-sarna.com/pipermail/peak/attachments/20110930/10246ba8/attachment.html
nicky van foreest
2011-09-30 19:46:34 UTC
Permalink
Post by PJ Eby
I tried the following, but this failed.
trellis.attrs(
prevs = trellis.Set([],
duration = 0,
)
...
The problem is that all batches use the same trellis.Set, but I want
each batch to have its own trellis.Set. How can I achieve this?
I'll go ahead and just answer this bit, because it's the part I can
understand without more detailed study. Hopefully it'll get you what you
need. ;-)
prevs = trellis.make(trellis.Set)
duration = trellis.attr(0)
I'll try this right now.
Post by PJ Eby
(I know that removing an item from a trellis.set is impossible.
Uh, what? Where'd you get that idea?
I simply misinterpreted the following documentation:

"Trellis Set objects offer nearly all the comforts of the Python
standard library's sets.Set objects (minus .pop(), and support for
sets of mutable sets), but with observability:""

Thanks for your tips.

Nicky
nicky van foreest
2011-09-30 20:28:27 UTC
Permalink
Post by PJ Eby
I'll go ahead and just answer this bit, because it's the part I can
understand without more detailed study. ?Hopefully it'll get you what you
need. ?;-)
? ? ?prevs = trellis.make(trellis.Set)
? ? ?duration = trellis.attr(0)
Fantastic. This works neat.

I also tried the other idea of Lloyd, but that didn't work. Anyway, many thanks.

Nicky
Loading...