Opened 6 years ago

Closed 6 years ago

# in case of alap: ticket starts earlier than its predecessor ticket finishes

Reported by: Owned by: falkb Chris Nelson normal TracJsGanttPlugin major Ryan J Ollos 0.12

### Description

Predecessor means to me that it has to be finished before its successor can start.

Function _schedule_task_alap() actually must consider the latest finish time of the predecessor but it does not. It just considers successors and parents somehow. So I can see that some tickets starts earlier than their predecessor finish.

For a test, you must not explicitely set start and end dates at all. It's enough to set some successor and predecessor dependencies.

### comment:1 Changed 6 years ago by Chris Nelson

Status: new → assigned

I'm in the thick of a major rewrite of the scheduling parts, including resource-based scheduling. I hope to post an update in a week or so and will try to make sure it addresses this case.

### comment:2 Changed 6 years ago by Ryan J Ollos

Cc: Ryan J Ollos added; anonymous removed

### comment:3 follow-up:  4 Changed 6 years ago by falkb

Still watching this bug after the latest refactoring on 30/Dec/2011.

More details for the bug environment: I've set:

fields.pred = blockedby
fields.succ = blocking
fields.parent = parents


I also have about 50 tickets in a milestone, about 5 of them are parent tickets for grouping the others. And I'm too lazy to set all start and end dates, so I just have set start and end date of the parent tickets. Additionally, I've set a succession order for all parent tickets. That means this way I don't need to set any schedule information in the child tickets, everything has been put in the parent tickets.

### The error

But all my parent tickets start on the same day in the chart, although that succession set by fields.pred and fields.succ

### comment:4 in reply to:  3 ; follow-up:  6 Changed 6 years ago by Chris Nelson

Still watching this bug after the latest refactoring on 30/Dec/2011.

More details for the bug environment: I've set:

fields.pred = blockedby
fields.succ = blocking
fields.parent = parents


I also have about 50 tickets in a milestone, about 5 of them are parent tickets for grouping the others. And I'm too lazy to set all start and end dates, so I just have set start and end date of the parent tickets. Additionally, I've set a succession order for all parent tickets. That means this way I don't need to set any schedule information in the child tickets, everything has been put in the parent tickets.

### The error

But all my parent tickets start on the same day in the chart, although that succession set by fields.pred and fields.succ

Can you attach a screen shot? Perhaps narrow this down to 2-4 tickets so I can easily create the same dependency in my system? Just for completeness, the trac-jsgantt and TracPM sections of your trac.ini would be nice.

### comment:5 Changed 6 years ago by falkb

It'll take a while to get back to my test bench. It should be enough to create a milestone with those 4 simple tickets:

• A
• is a child ticket of C
• has 40 planned and 40 remaining hours
• has no planned start and end time
• B
• is a child ticket of D
• has 40 planned and remaining hours
• has no planned start and end time
• C
• is a parent of A
• is a predecessor of D
• has no planned and remaining hours
• has no planned start and end time
• D
• is a parent of B
• is a successor of C
• has no planned and remaining hours
• has no planned start and end time

Then the chart will display C and D starting at the same day and the dependency arrow from C to D goes back in the past

### comment:6 in reply to:  4 ; follow-up:  18 Changed 6 years ago by anonymous

Can you attach a screen shot?

[TracPM]
date_format = %Y-%m-%d
days_per_estimate = 0.125
fields.estimate = estimatedhours
fields.finish = userfinish
fields.parent = parents
fields.pred = blockedby
fields.start = userstart
fields.succ = blocking
fields.worked = totalhours
milestone_type = milestone

[ticket-custom]
billable = checkbox
billable.label = Billable?
billable.order = 3
billable.value = 1
blockedby = text
blockedby.label = Blocked By
blocking = text
blocking.label = Blocking
estimatedhours = text
estimatedhours.label = Planned Hours
estimatedhours.order = 1
estimatedhours.value = 8
hours = text
hours.label = Add Hours to Ticket
hours.order = 2
hours.value = 0
parents = text
parents.label = Parent Tickets
remaininghours = text
remaininghours.label = Remaining Hours
remaininghours.order = 1
remaininghours.value = 8
totalhours = text
totalhours.label = Total Hours
totalhours.order = 4
totalhours.value = 0
userfinish = text
userfinish.label = Planned Finish
userfinish.order = 4
userfinish.value =
userstart = text
userstart.label = Planned Start
userstart.order = 4
userstart.value =


### comment:7 Changed 6 years ago by Chris Nelson

I've reproduced this locally. I'll see what I can do.

### comment:8 Changed 6 years ago by Chris Nelson

I'm a big mystified why A takes 8 days and B takes 7.

### comment:9 follow-ups:  11  13 Changed 6 years ago by falkb

Yes, I checked again and both are really set to 40 hours, as written above. I didn't already noticed that 8 vs. 7 problem. :)

P.S.: You can remove 9566.JPG. I haven't got permissions to change or delete.

### comment:10 Changed 6 years ago by Chris Nelson

The problem appears to be the dependency between tickets with no estimate. The scheduler computes start + default_estimate = finish and propagates that from parent to child (the default estimate of 4 hours rounds to show a one-day offset). The chart then ignores dates for parents and rolls up values from children so the parent tasks stretch to encompass the duration of their child(ren).

When I configure default_estimate to 0, the tasks all line up on the same day.

Now that I know where it's going wrong, I have to figure out how to propagate durations better.

### comment:11 in reply to:  9 Changed 6 years ago by Chris Nelson

... P.S.: You can remove 9566.JPG. I haven't got permissions to change or delete.

Neither have I.

### comment:12 follow-up:  14 Changed 6 years ago by Chris Nelson

The essence of the problem seems to be that a group (parent) finish is based on:

1. An explicit date, if any
2. The earliest successor start
3. The latest ancestor finish
4. The latest descendant finish

and its start is based on:

1. An explicit date, if any
2. The finish minus hours, if specified
3. The earliest descendant start

I have not yet accounted for the last term in each of those lists.

### comment:13 in reply to:  9 ; follow-up:  16 Changed 6 years ago by Ryan J Ollos

P.S.: You can remove 9566.JPG. I haven't got permissions to change or delete.

Removed.

### comment:14 in reply to:  12 ; follow-up:  15 Changed 6 years ago by falkb

1. An explicit date, if any
2. The earliest successor start
3. The latest ancestor finish
4. The latest descendant finish

The latest predecessor finish also. Don't know what is more important if there is too less time between set predecessor finish and set successor start.

### comment:15 in reply to:  14 Changed 6 years ago by falkb

The latest predecessor finish also. Don't know what is more important if there is too less time between set predecessor finish and set successor start.

But that is just important for the parent start.

### comment:16 in reply to:  13 Changed 6 years ago by falkb

Removed.

wrong one :) We need the image file suffix in lower case. Can you rename it?

### comment:17 Changed 6 years ago by Ryan J Ollos

Yeah, sorry about that. Should be fixed now.

### comment:18 in reply to:  6 Changed 6 years ago by falkb

Can you attach a screen shot?

If you look at the image, you may also wonder if it's right to have the bars in the past month. Remember neither the milestone nor the tickets have any set timestamps when they begin and end. In this case I tend to expect the beginning of the first gantt char bar at the current day (blue week).

### comment:19 follow-up:  20 Changed 6 years ago by Chris Nelson

This actually signals a more general problem which is turning out to be hard to fix, especially in anticipation of resource leveling.

### comment:20 in reply to:  19 ; follow-up:  21 Changed 6 years ago by falkb

This actually signals a more general problem which is turning out to be hard to fix, especially in anticipation of resource leveling.

Then maybe it's better to swap this out to an extra ticket

### comment:21 in reply to:  20 Changed 6 years ago by Chris Nelson

This actually signals a more general problem which is turning out to be hard to fix, especially in anticipation of resource leveling.

Then maybe it's better to swap this out to an extra ticket

My "this" referred to the ticket summary, not "should an ALAP schedule end today or make-span from today. It's a hard problem that the naive algorithm neglects. Working on it...

### comment:22 follow-up:  27 Changed 6 years ago by Chris Nelson

I may have a nice, general solution which will handle resource leveling but I can't get it to work because of either a bug in Trac or Python or my misunderstanding of deepcopy(). My question to trac-dev hasn't gotten any response.

### comment:23 Changed 6 years ago by Chris Nelson

A subclass of list should populate the list in __init__, not __new__, usually by calling list.init, as lists are mutable and subclasses thereof should be too.

I don't believe TracPM has any subclass of list and I think Ticket maybe which suggests to me there's something wrong in Trac core.

### comment:24 follow-up:  25 Changed 6 years ago by anonymous

you may also find this useful for looking through: http://bytes.com/topic/python/answers/101464-more-deepcopy-tkinter

Note: Strange, some comments of a few minutes ago are missing

### comment:25 in reply to:  24 Changed 6 years ago by Ryan J Ollos

Note: Strange, some comments of a few minutes ago are missing

That was my fault. I delete a lot of spam, and some of the recent comments, without given much thought, looked to be spam. I'll try to be more careful.

### comment:26 Changed 6 years ago by anonymous

No worries. We've still got the emails... somehow it was spam as well ;)

### comment:27 in reply to:  22 ; follow-up:  28 Changed 6 years ago by falkb

I slightly wonder why you want to copy a ticket deep down. Isn't it enough to just grab the common and custom fields including their value, and build up your desired dicts with that information?

### comment:28 in reply to:  27 Changed 6 years ago by Chris Nelson

I slightly wonder why you want to copy a ticket deep down. Isn't it enough to just grab the common and custom fields including their value, and build up your desired dicts with that information?

My scheduler could copy just the fields it cares about and work in a scratch space -- and that may be the approach I take if I can't resolve this -- but it's more general if TracPM.computeSchedule() gives the scheduler a set of tickets it can write all over.

OTOH, I tried:

• Back up certain fields (with copy)
• Schedule (overwriting original values)
• Assign fields back to copied value

and the copy seemed to have no effect. <shrug>

### comment:29 follow-ups:  30  31 Changed 6 years ago by falkb

http://tinypaste.com/1a0ff869 - A snippet of my patch for #6168 where I successfully used deepcopy() for reusing the options list. Hope this helps.

### comment:30 in reply to:  29 Changed 6 years ago by falkb

argh... I mean #6186

### comment:31 in reply to:  29 Changed 6 years ago by Chris Nelson

http://tinypaste.com/1a0ff869 - A snippet of my patch for #6168 where I successfully used deepcopy() for reusing the options list. Hope this helps.

I don't see how it applies as I'm trying to copy a ticket and I've been advised on trac-dev that that can't work (Ticket is simply a derivative of a Python list). Even doing field-by-field copies (or deep copies) doesn't seem to help. Using your test case and:

        # I can't deep copy tickets so let's save what we're going to
# mess up so we can put it back.
# FIXME - this doesn't work, either. <shrug>
pred = {}
succ = {}
for tid in ticketsByID:
# Neither copy or deepcopy here make a difference
pred[tid] = copy.deepcopy(ticketsByID[tid][self.pm.fields['pred']])
succ[tid] = copy.deepcopy(ticketsByID[tid][self.pm.fields['succ']])

# Main schedule processing
_augmentTickets(ticketsByID)

for id in ticketsByID:
if options['schedule'] == 'alap':
else:

for tid in ticketsByID:
# This doesn't work with or without copy.
ticketsByID[tid][self.pm.fields['pred']] = copy.copy(pred[tid])
ticketsByID[tid][self.pm.fields['succ']] = copy.copy(succ[tid])


the augmented dependencies how up in the chart. I'm boggled.

### comment:32 Changed 6 years ago by falkb

you should go to IRC and try to get enlighted there...

### comment:33 Changed 6 years ago by Chris Nelson

I have a working fix for this but I'm integrating it into our system and verifying it. I hope to post this weekend or early next week.

### comment:34 Changed 6 years ago by Chris Nelson

(In [11141]) Clarify some comments. Add a FIXME. Refs #9566.

Also a couple of minor white space tweaks.

### comment:35 Changed 6 years ago by Chris Nelson

(In [11143]) Pass scheduler tickets by ID, not unordered list. Refs #9566.

Any scheduler will need a fast lookup of tickets by ID so this takes the work of building that lookup off the schedulers, reducing duplicated code.

It also copies the ticket attributes so that the scheduler can change them without concern that it will break things. This enforces the pre- and post-conditions for computeSchedule() that only 'calc_start' and 'calc_finish' are set/changed.

It would seem that I could done

        for t in tickets:
ticketsByID[t['id']] = copy.deepcopy(t)


but that raised errors.

### comment:36 Changed 6 years ago by Chris Nelson

(In [11144]) Tasks inherit their ancestors' dependencies. Refs #9566.

If A has children B and C, and D has children E and F, if A is required for D then B and C have to be completed before D.

This copies predecessor and successor dependencies down the tree before scheduling so those dependencies can be honored by the scheduler.

It uses functions as objects and takes advantage of the fact that the accessor functions don't return values, they return references to the original lists so those lists can be updated without more complicated access wrappers to append, remove, etc.

Also fix a bug in creating milestone pseudotickets where [] and None were not used consistently with the rest of the module.

### comment:37 follow-up:  38 Changed 6 years ago by falkb

Thanks! Seems 2012 will be a good year for TracJsGanttPlugin. Seems to work well, anyway, it looks already good on my test bench with the small test project A-B-C-D. I'm going to test it on the big real-life project tommorrow. Cool that weekends are considered also.

As noticed in 18, my example scenario still ends today and starts in the past. The milestone has not date set. I think a solution in the case of no milestone date set would be to add a time shift to all tickets which is equal to today minus earliest computed ticket date. This is of quite great importance here, since we schedule a project by ticket hierarchy but without setting a milestone date yet. Simply, since that milestone date depends on from what the ticket scheduling results to. We want to have a look to which date the Gantt chart will lead us and take it as hint for setting the milestone date then. But as mentioned before, this may be another ticket. It's not quite related to this dependency problem of this #9566.

### comment:38 in reply to:  37 ; follow-up:  39 Changed 6 years ago by falkb

on the big real-life project tommorrow

Yeah, dependencies look good here too :-)

As noticed in 18, my example scenario still ends today and starts in the past. The milestone has not date set.

As a test, I switched to mode schedule=asap. Then the good news is the whole thing starts the computation from date 'today'. Though the milestone is put on 'today', therefore not appended to the bottom of the list but inserted quite early, and that lets the chart look a bit strange:

First in 37, I thought that's a story for another ticket, but I think the milestone must be treated like something like a ticket as well. That means the rule should be a milestone without set date (internally) is the successor of all its assigned tickets and therefore must be displayed as last date point in the chart.

### Changed 6 years ago by falkb

milestone inserted too early

### comment:39 in reply to:  38 ; follow-up:  40 Changed 6 years ago by Chris Nelson

.... That means the rule should be a milestone without set date (internally) is the successor of all its assigned tickets and therefore must be displayed as last date point in the chart.

I agree. Which is why I have:

                # Any ticket with this as a milestone and no
# successors has the milestone as a successor
if self.isCfg(['pred', 'succ']):
pred = []
for t in tickets:
if not t['children'] and \
t['milestone'] == row[0] and \
self.successors(t) == []:
if self.isField('succ'):
t[self.fields[self.sources['succ']]] = \
[ str(id) ]
else:
t['succ'] = [ str(id) ]
pred.append(str(t['id']))
if self.isField('pred'):
milestoneTicket[self.fields[self.sources['pred']]] = \
pred
else:
milestoneTicket['pred'] = pred


but when I looked at that just now, I found it is preceded by:

                # If there's no due date, default to today at close of business
if self.isCfg('finish'):
ts = row[1] or \
(datetime.now(utc) +
timedelta(hours=options['hoursPerDay']))
milestoneTicket[self.fields['finish']] = \
format_date(ts, self.dbDateFormat)

# jsGantt ignores start for a milestone but we use it
# for scheduling.
if self.isCfg('start'):
milestoneTicket[self.fields['start']] = \
milestoneTicket[self.fields['finish']]


Which sets a finish date we don't. It may be as simple as removing the code that sets the milestone finish and let the scheduler fill it in after computing dependencies. Can you try that? It would take a while for me to set up a test.

### comment:40 in reply to:  39 ; follow-up:  41 Changed 6 years ago by falkb

... It may be as simple as removing the code that sets the milestone finish

Well, just a snapshot:

If I comment out lines 565 and 566 to remove the setting of milestone finish I get:

...
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 717, in postQuery
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 572, in _add_milestones
milestoneTicket[self.fields['finish']]
KeyError: u'userfinish'


If I additionally comment out lines 570-572 to also remove the setting of milestone start I get:

...
self.pm.computeSchedule(options, self.tickets)
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 732, in computeSchedule
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 1207, in scheduleTasks
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 1065, in _schedule_task_asap
if self.pm.isSet(t, 'start'):
File "build\bdist.win32\egg\tracjsgantt\tracpm.py", line 216, in isSet
and len(ticket[self.fields[field]]) != 0:
KeyError: u'userstart'


### comment:41 in reply to:  40 Changed 6 years ago by Chris Nelson

... It may be as simple as removing the code that sets the milestone finish

Well, just a snapshot:

If I comment out lines 565 and 566 to remove the setting of milestone finish I get: ...

Thanks. I hoped it would be easy. I'll try to look into this today.

### comment:42 follow-up:  43 Changed 6 years ago by Chris Nelson

(In [11153]) Don't force a due date on unscheduled milestones. Refs #9566.

An unscheduled milestone no longer defaults to being due today but gets its date from the scheduler.

### comment:43 in reply to:  42 ; follow-up:  44 Changed 6 years ago by falkb

(In [11153]) Don't force a due date on unscheduled milestones. Refs #9566.

An unscheduled milestone no longer defaults to being due today but gets its date from the scheduler.

Not bad, but not perfect.

My milestone behaviour test is like this:

• ticket duration range some weeks
• 2 milestones
• milestone1 with date in 3 days
• milestone2 without date
• Test of schedule=alap:
 milestone expected seen 1 between the tickets on its certain date wrong, is at the bottom below all tickets, set date overruled by date after all other tickets 2 at the bottom below all tickets correct, as expected
• Test of schedule=asap:
 milestone expected seen 1 between the tickets on its certain date correct, as expected 2 at the bottom below all tickets wrong, is at the top before all tickets

### comment:44 in reply to:  43 ; follow-up:  45 Changed 6 years ago by Chris Nelson

(In [11153]) Don't force a due date on unscheduled milestones. Refs #9566.

An unscheduled milestone no longer defaults to being due today but gets its date from the scheduler.

Not bad, but not perfect.

My milestone behaviour test is like this:

• ticket duration range some weeks
• 2 milestones
• milestone1 with date in 3 days
• milestone2 without date
• Test of schedule=alap:
 milestone expected seen 1 between the tickets on its certain date wrong, is at the bottom below all tickets, set date overruled by date after all other tickets 2 at the bottom below all tickets correct, as expected
• Test of schedule=asap:
 milestone expected seen 1 between the tickets on its certain date correct, as expected 2 at the bottom below all tickets wrong, is at the top before all tickets

A screen shot would help.

### comment:45 in reply to:  44 Changed 6 years ago by falkb

A screen shot would help.

Here we go:

• milestone1 with set date
• milestone without date
• Test of schedule=alap:
 milestone expected seen 1 between the tickets on its certain date wrong, is at the bottom below all tickets, set date overruled by date after all other tickets 2 at the bottom below all tickets correct, as expected

• Test of schedule=asap:
 milestone expected seen 1 between the tickets on its certain date correct, as expected 2 at the bottom below all tickets wrong, is at the top before all tickets

### comment:46 follow-up:  48 Changed 6 years ago by falkb

Hmm... uploading images doesn't work anymore. You can find them also here: alap image and asap image

(Due 14-days timeout, you can locally attach them to this ticket after someone has repaired the image handling on the server)

### comment:47 follow-up:  49 Changed 6 years ago by osimons

I've deleted the images. Seeing '#' is the fragment identifier in URLs, I'm not surprised that that this old Trac has trouble with using it in filenames - makes it hard to access them when the URL isn't encoded correctly.

BTW, try to upload them to http://trac.edgewall.org/demo-0.12 or similar to see if the issue is fixed in current Trac.

### comment:48 in reply to:  46 Changed 6 years ago by Chris Nelson

Hmm... uploading images doesn't work anymore. You can find them also here: alap image and asap image

(Due 14-days timeout, you can locally attach them to this ticket after someone has repaired the image handling on the server)

milestone1 appears to have no dependencies and to show up on 1/26 in both schedules.

It does seem that milestone2 should be below the tasks it depends on in the ASAP schedule.

### Changed 6 years ago by falkb

illustrating 45, schedule=alap

### Changed 6 years ago by falkb

illustrating 45, schedule=asap

### comment:49 in reply to:  47 Changed 6 years ago by falkb

'#' is the fragment identifier in URLs

Argh... my fault! Sorry for the trouble. Could you do me a favour and rename the image names used in the macros of comment:45, please? All related comments can be be deleted, too. TIA

### comment:50 Changed 6 years ago by falkb

now comment 45 again with fixed images:

A screen shot would help.

Here we go:

• milestone1 with set date 1/26
• milestone without date
• Test of schedule=alap:
 milestone expected seen 1 between the tickets on its certain date wrong, is at the bottom below all tickets, set date overruled by date after all other tickets 2 at the bottom below all tickets correct, as expected

You can see, because of set date 1/26, milestone1 is wrong and should actually be between the tickets on its certain date.

• Test of schedule=asap:
 milestone expected seen 1 between the tickets on its certain date correct, as expected 2 at the bottom below all tickets wrong, is at the top before all tickets

You can see, because of no set date, milestone2 is at wrong position and should be at the botton below all tickets at the end.

### comment:51 follow-up:  52 Changed 6 years ago by falkb

Both images are not full screenshots but just puzzle pieces of the whole chart, and the ticket texts are obliterated since it's from a real project chart. The chart contains the range of two milestones where just milestone2 has no date because that should more or less be set from what the chart computes.

### comment:52 in reply to:  51 ; follow-ups:  53  54  60 Changed 6 years ago by Chris Nelson

Both images are not full screenshots but just puzzle pieces of the whole chart, and the ticket texts are obliterated since it's from a real project chart. The chart contains the range of two milestones where just milestone2 has no date because that should more or less be set from what the chart computes.

I understand that you're showing me just a piece of the whole chart but...

• ALAP
• MS1 has an explicit date of 1/26 and shows up there
• MS2 is scheduled today, 1/17 (which you could argue is wrong, but it's what I expectg)
• Tasks are sorted by date so (roughly) later tasks are lower in the list
• MS1 is later than MS2 so it is lower.

What's wrong with that?

• ASAP
• MS1 has an explicit date of 1/26 and shows up late in the week of 1/22, this looks right to me
• MS2 shows up today which does seem wrong to me, it should follow its latest prececessor, perhaps 2118. (I believe that it shows up above the tasks because of correct date sorting after incorrect scheduling)

I'll try to set up your data as an ASAP test case soon.

### comment:53 in reply to:  52 ; follow-up:  55 Changed 6 years ago by Chris Nelson

...

• ASAP
• MS1 has an explicit date of 1/26 and shows up late in the week of 1/22, this looks right to me
• MS2 shows up today which does seem wrong to me, it should follow its latest prececessor, perhaps 2118. (I believe that it shows up above the tasks because of correct date sorting after incorrect scheduling)

Is this after the recent patch that took off the default of today for unscheduled milestones?

### comment:54 in reply to:  52 ; follow-up:  56 Changed 6 years ago by falkb

Both images are not full screenshots but just puzzle pieces of the whole chart, and the ticket texts are obliterated since it's from a real project chart. The chart contains the range of two milestones where just milestone2 has no date because that should more or less be set from what the chart computes.

I understand that you're showing me just a piece of the whole chart but...

• ALAP
• MS2 is scheduled today, 1/17 (which you could argue is wrong, but it's what I expectg)

What's wrong with that?

You agreed in 39 that a milestone without set date (internally) is the successor of all its assigned tickets. That's why milestone2 cannot be scheduled today.

• ASAP
• MS1 has an explicit date of 1/26 and shows up late in the week of 1/22, this looks right to me
• MS2 shows up today which does seem wrong to me, it should follow its latest prececessor, perhaps 2118. (I believe that it shows up above the tasks because of correct date sorting after incorrect scheduling)

Look at my two tables in 50 with expected and seen behaviour of the two milestones. That milestone2 should be scheduled as last one because of the rule already mentioned above.

### comment:55 in reply to:  53 ; follow-up:  57 Changed 6 years ago by falkb

Is this after the recent patch that took off the default of today for unscheduled milestones?

Do you mean the suggested code removing in 39? That didn't work, so I'm on the latest SVN version without local patches.

### comment:56 in reply to:  54 ; follow-ups:  59  61 Changed 6 years ago by Chris Nelson

Both images are not full screenshots but just puzzle pieces of the whole chart, and the ticket texts are obliterated since it's from a real project chart. The chart contains the range of two milestones where just milestone2 has no date because that should more or less be set from what the chart computes.

I understand that you're showing me just a piece of the whole chart but...

• ALAP
• MS2 is scheduled today, 1/17 (which you could argue is wrong, but it's what I expectg)

What's wrong with that?

You agreed in 39 that a milestone without set date (internally) is the successor of all its assigned tickets. That's why milestone2 cannot be scheduled today.

Milestone2 *is* shown as a successor to all of its tickets. I understand that anchoring an ALAP schedule without explicit dates so it ends today is questionable but given that is the current algorith, MS2 shows up in the correct position relative to its tickets.

• ASAP
• MS1 has an explicit date of 1/26 and shows up late in the week of 1/22, this looks right to me
• MS2 shows up today which does seem wrong to me, it should follow its latest prececessor, perhaps 2118. (I believe that it shows up above the tasks because of correct date sorting after incorrect scheduling)

Look at my two tables in 50 with expected and seen behaviour of the two milestones. That milestone2 should be scheduled as last one because of the rule already mentioned above.

I'm sorry if I'm dense today but what rule? MS1 shows up on its due date. MS2 is clearly on the wrong date.

I see two new tickets here:

• In ALAP scheduling, today is not a valid end date if no dates are assigned
• In ASAP scheduling, milestones don't show up after their tickets, everything seems to start today.

### comment:57 in reply to:  55 ; follow-up:  58 Changed 6 years ago by Chris Nelson

Is this after the recent patch that took off the default of today for unscheduled milestones?

Do you mean the suggested code removing in 39? That didn't work, so I'm on the latest SVN version without local patches.

My suggestion was flawed/incomplete but I finished it in 42. That's the change I'm talking about.

### comment:58 in reply to:  57 Changed 6 years ago by falkb

My suggestion was flawed/incomplete but I finished it in 42. That's the change I'm talking about.

I use the latest of the SVN trunk

### comment:59 in reply to:  56 Changed 6 years ago by falkb

I'm sorry if I'm dense today but what rule?

I'm talking about this rule: a milestone without set date (internally) is the successor of all its assigned tickets

MS1 shows up on its due date.

 milestone expected seen 1 between the tickets on its certain date correct, as expected

MS2 is clearly on the wrong date.

 milestone expected seen 2 at the bottom below all tickets wrong, is at the top before all tickets

=> I'm glad that, for the case of ASAP, we see the same problem. I used a table, you said the same in sentences.

### comment:60 in reply to:  52 Changed 6 years ago by falkb

...

For ALAP: Let me put it in other words. 54 and 56 were totally confusing. :)

Here my ALAP table again:

 milestone expected seen 1 between the tickets on its certain date wrong, is at the bottom below all tickets, set date overruled by date after all other tickets 2 at the bottom below all tickets correct, as expected
• ALAP
• MS1 has an explicit date of 1/26 and shows up there

No, it doesn't show up there on 1/26. The date is 1/26 but shows up many weeks later after all other tickets, and that's why it's at the botton of the table, and such behaviour is wrong. As written in my table, I've seen the set date of MS1 is overruled by a date which is after all other tickets. I expect MS1 to show up between the tickets on its certain date on 1/26.

• MS2 is scheduled today, 1/17 (which you could argue is wrong, but it's what I expectg)

Right, MS2 is correct as the table says as well in column seen, line of milestone 2.

• Tasks are sorted by date so (roughly) later tasks are lower in the list

Right, but MS1 is the lowest although it should be one of the earliest on 1/26. Look here again and see it long after its proper date:

Though, you are right when you write at the end of 56: "In ALAP scheduling, today is not a valid end date if no dates are assigned"

### comment:61 in reply to:  56 Changed 6 years ago by falkb

I see two new tickets here:

• In ALAP scheduling, today is not a valid end date if no dates are assigned
• In ASAP scheduling, milestones don't show up after their tickets, everything seems to start today.

Right, seems it's been a hard birth, either here in #9566 or two new ones. P.S.: Clear explanations are difficult to phrase, last but not least since English is not my mother tongue. :)

### comment:62 Changed 6 years ago by Chris Nelson

Resolution: → fixed assigned → closed

The original subject of this ticket has been successfully addressed.

### comment:63 follow-up:  64 Changed 6 years ago by Chris Nelson

(In [11159]) Optimize dependency propagation to children. Refs #9566.

In my 6-ticket test case, this reduces the number of dependencies added from 8 to 3. In general, I think that the potential arcs in a graph are the number of nodes squared so in real-world data sets, this improvement is likely even bigger.

### comment:64 in reply to:  63 Changed 6 years ago by anonymous

I see two new tickets here:

• In ALAP scheduling, today is not a valid end date if no dates are assigned

continued on #9705

• In ASAP scheduling, milestones don't show up after their tickets, everything seems to start today.

continued on #9704

(In [11159]) Optimize dependency propagation to children. Refs #9566. ... so in real-world data sets, this improvement is likely even bigger.

Very good. I already noticed when resizing the browser window with a chart of about 100 tickets that the slowlyness was sensible on IE before (FF is much faster). But now with your commit it's acceptably fast. I already thought about bothering with a new ticket for that but [11159] refrains me from doing so... :)

### comment:65 Changed 6 years ago by Chris Nelson

(In [11402]) Try to propagate dependencies to all children. Refs #9566.

This actually seems to get back to the original implementation. I broke it trying to optimized.

The logic now and originally is:

for each child
if the child doesn't depend on any cousins
copy dependencies down
recurse to process grandchildren


The optimized, broken, intermediate version did:

if there are dependencies
for each child
copy dependencies down
recurse to process grandchildren


If any level of the tree had no dependencies, propagation was interrupted. If a "root" ticket had no dependencies, all of its descendants were ignored.

### comment:66 Changed 6 years ago by falkb

[11402] tested with success

### Modify Ticket

Change Properties