XML

kent logo

CO631 Anonymous Questions and Answers Keyword Index

This page provides a keyword index to questions and answers. Clicking on a keyword will take you to a page containing all questions and answers for that keyword, grouped by year.

To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

Keyword reference for q7

2005

Question 9 (2005):

Submission reference: IN733

Hey, just wondering if the bonus question system for the exam will be in place this year again? What I had heard about the system was that if we do all questions in the exam, we would be awarded full credit for the best 3 questions and half credit for the remaining extra question. Thanks for your time.

Answer 9:

No. Last year's rubric was deemed too complicated (although no student or staff had any problem with it!).

All rubrics for this year's papers are published here. For Co631:

    There are FOUR questions.
    Candidates should answer THREE questions,
    the ONE question from Section A and TWO from Section B.

If your answer all THREE from Section B, one of the answers will not count. Sorry -- you must follow the rubric.

Keywords: q7


Question 8 (2005):

Submission reference: IN638

With the random number generator are you supposed to create a new process to create the random number or does it go within an existing process. If this is the case do you have to have 2 random generators for thinking and eating. If the only way to get better marks for the assessment is to use this, why didn't we have it explained in lectures?...Thank you for your help

Answer 8:

The "random" thing is just a FUNCTION, so you can call it inline or wrap it up in a process; I prefer inline calls. This may not be needed for the philosophers assessment set this year, however, there's plenty of documentation on it available, it's not hard to use, and it'll produce a more convincing animation. Just because it's not required doesn't mean that you can't do/use it!

Keywords: q7


Question 6 (2005):

Submission reference: IN629

Hi, I was just wondering what kind of delays should we put in between the philosophers thinking and eating. If we set them to eat for longer than think, then you'll see the security flag up as a 5th tries to sit, however if you set them to think for longer then you'll very rarely see the security go up, if at all. What should the time delays roughly be?

Answer 6:

The delays should be random. See the other questions under the random keyword for details on how to use it.

However, you are right that the eating times should be a bit longer, mostly, than the thinking times ... to get a chance to see a hungry philosopher who is blocked by security.. Suggest making eating times random between 6 and 15 seconds, with the thinking times random between 2 and 8 seconds. If the action still seems a bit slow, reduce by a factor of 10 - experiment!

Keywords: q7 , random

2004

Question 148 (2004):

Just curious if you will/have selected any more dining philosopher solutions to add to the raptor answers collection ?

Answer 148:

Possibly -- I've already put one into the KRoC/Linux distribution's set of dining philosophers, but this can't go on raptor because it uses some of the occam-pi extensions (not supported by the version of KRoC installed on raptor). We might put some more in, and put on raptor (if compatible).

Keywords: q7 , model-answers


Question 122 (2004):

Hi, I've completed the q7 coursework but I would like to ask a question before I submit it. I found no need for the "PROC secure.college", so I removed it and did all the necessary wiring in "PROC q7". The animation still works and I feel I can understand my code better this way. Will I be marked down for the removal of "secure.college" ?

Answer 122:

Yes, you will lose marks. There is a reason for having "secure.college" - namely structure! Discarding it leaves its innards and the "display" at the same level of network ... which is (a) more complicated and (b) illogical. Please tidy them back into a "secure.college" wrapping.

Keywords: q7


Question 121 (2004):

Continued from Question 120 (2004)... I'm actually working with a 2D array, although I don't think that makes any difference ? I'm not getting an error, it's a little strange but it appears to remove the byte, for example with:

    log[0] := "Philxxxis eating "
    log[0][5] := (BYTE n)

after this operation, "log[0]" seems to contain "Philxxis eating ". Any ideas ? I'm feeling slightly baffled.

Answer 121:

The reason this is probably happening is because "BYTE n" is not a printable character. Casting an INT to a BYTE does not produce the character representation of the number in base-10 (decimal) -- it produces the ASCII character with the value of the integer. If you want to print out a number as its (decimal) character representation, use "out.int".

Keywords: q7


Question 120 (2004):

In occam, if I've got a BYTE array, I would have thought I could do something like this: (where "i" is an INT)

    array[5] := BYTE i

but it doesn't appear to work, can you explain why that is, when something such as this works perfectly fine: (where "b" is a BYTE).

    array[5] := b

Answer 120:

That should work fine, and does for me.. What error (exactly) are you getting ? Something else must be wrong..

Keywords: q7 , arrays

Referrers: Question 121 (2004)


Question 119 (2004):

Oh dear oh dear - q7-bodden-2003: it just crashed on me after running for a while! Shocking.

  KROC: Fatal error / STOP executed (signal 4)
  KROC: Fatal error code 1, core dumped
  Abort

Aren't these supposed to be 'model' answers? ^_^

Answer 119:

Humm ... I guess you mean the a7-bodden-2003 program ... there isn't a q7-bodden-2003 one?!! [Actually, it's simple naming typos like these that cause masses of software crashes, :(]

But, seriously, a7 is the model demo executable. All others are to give you ideas/challenges. We haven't verified them completely. Thanks for telling us that that one breaks. We will fix ...

Keywords: q7


Question 118 (2004):

Do you think anyone would be offended if someone were to name their philosophers after occam seminar leaders ;)

Answer 118:

No ...

Keywords: q7


Question 117 (2004):

Hi there, can you give some clues of how to get the forks working in Q7. Everything I am trying isn't working :-(

Answer 117:

The forks already work by default -- adding the reports shouldn't break them! The best idea would be to mail your seminar leader with a copy of the code, who can then advise on what the problem is.

Keywords: q7


Question 116 (2004):

Is A7 the minimum you expect from us for Q7 ?

Answer 116:

It's minimal in the sense that if you implement something that produces similar output you can get 100%. But that's a generous estimate; some marks are inevitably lost for untidy coding, errors, etc.

Keywords: q7


Question 115 (2004):

When I try to run my q7 answer on my Linux box (Mandrake 10.1) I get this error:

    KRoC: unable to find clock file (.kroc_clock or /etc/kroc_clock)

What does it mean and what can i do to fix it ?

Answer 115:

It's because you're missing the KRoC clock file. When you installed the software it prints out a message saying that you must copy "~/.kroc_clock" to the current-directory or to "/etc/". This file just contains your CPU speed in MHz (as read from "/proc/cpuinfo"). Newer versions of KRoC/Linux (1.3.4-pre4 and above I think) will automatically read the speed out of "/proc/cpuinfo" if a clock file isn't found.

Keywords: q7 , linux


Question 114 (2004):

How do we submit our dining philosopher's assignment?

Answer 114:

Copying from the newsgroup announcement ...

Your assessment, "A4 DINING PHILOSOPHERS ANIMATION", is due on Monday in week 18 - i.e. Monday, 14th. February, 2005.

This time, we want to compile and run your programs! Submission directories are open at:

  \\raptor\files\proj\co516\q7\        (from Windows)

or:

  /usr/local/proj/co516/q7/            (from Unix/raptor)

Please copy your source code (.occ) file(s) there. Please do *NOT* copy executables. You only have access to <your-login-name> directory.

If your solution follows the standard model (i.e. an array of channels connecting the college process and the display process, with the display also connected to the screen channel), you do *NOT* need to include a network diagram.

If your solution has a non-standard network, please include a network diagram with your submission. This can be as a .pdf, .ps, .ppt or .doc file. For anything else, you must submit hard copy to CAS reception together with a cover sheet. A neat hand-drawn diagram is very acceptable through that route.

The submission directories will close at midnight between Monday/Tuesday - i.e. at 00:00 on Tuesday, 15th. February.

Keywords: q7


Question 113 (2004):

Hello. I saw your answer to Question 109 (2003) about the colours in text and was wondering where and how to find out the codes for other colours. Thanks.

Answer 113:

Well, the answer to the question you referenced says to do a quick Google search. I just did and it came up with this link which, when combined with Question 109 (2003), tells all, :).

Keywords: q7


Question 112 (2004):

Why is this bit of code gvining the error: Parallel outputs on channel out, when the channels down and up are used in security as well as philosopher?

   [Code snipped]

Answer 112:

As said many times before, we can't debug specific code on these pages!

However, the compiler is generating a correct error message - it usually does. Your network has mutliple processes writing to the same out channels - the up and down channels are irrelevant here.. When you've fixed that, you might want to put those out channels in the parameter list for secure.college - having them as local channels mean they don't connect to anything in the world outside the college ... such as a display process ...

Keywords: q7


Question 111 (2004):

Is it possible we can actually see the implementation of the PROCs, like: "erase.screen()", "erase.bol()" and others in the utils file ?

Answer 111:

Yes, just look at the source code! See Question 63 (2003) for an indication of where it is.

Keywords: q7 , course-library


Question 110 (2004):

Is this the correct piece of code for waiting a random time ?

    SEQ          
      seed := seed + id
      i, seed := random(num, seed)
      tim ? t
      tim ? AFTER t PLUS i

Answer 110:

More or less, yes. Make sure you initialise "seed" appropriately though -- the code above initialises it based on itself (if undefined, it'll stay undefined). As covered in the seminars, a quick way to get an initial seed value is:

    tim ? seed
    seed := (seed >> 2) + 1   -- maybe also add in the `id'

Remember also that your seed should be explicitly initialised like this just once -- before loop entry. Within the loop, cycling through the philosopher's life, the seed value gets updated as you use the random function. The sequence of seed values takes you through the "random" numbers. If you re-initialise the seed every time round the loop, the computed randomness will be lost.

Keywords: q7 , timers


Question 109 (2004):

How many more channels need to be added to the PROC header of the philosopher? When I add an output channel to my "fork", "philosopher" and "security" PROCs, I get an error in the "secure.college" PROC stating parallel outputs on one channel. How do I get around this?

Answer 109:

Form the code from the diagram of it -- you'll see that there is only one additional (report) channel coming out of a philosopher, so that's all that should be added to its header. The error relating to parallel output is in "secure.college", so that is where the error lies -- not in "philosopher", etc. A key rule is you can't do parallel outputs to the same channel. So, we need an array of channels, one for each of the reporting processes inside "secure.college". The "display" process takes the other (reading) end of that array of channels. How to do this has been covered fairly extensively in the seminars. If you're already using an array of channels, check the indices you're using -- one or more must be wrong if the compiler is giving you this error (you can expand the replicators by hand to see where the error lies).

Keywords: q7


Question 108 (2004):

I'm thinking of changing my protocol from:

    PROTOCOL REPORT
      CASE
        thinking
        hungry
        ...
    :

to:

    PROTOCOL REPORT
      CASE
        thinking; INT
        hungry: INT
        ...
    :

to tell me which philisopher is hungry, thinking, etc. Is this a wise move or is there another way I can find this out in the "display" process ? Currently I'm ALTing over the channels to see if they're thinking, hungry, etc.

Currently if a philisopher is thinking it prints (philosopher is thinking) with no knowledge of who is thinking.

Answer 108:

Yes, this probably is a wise move. The only other way you can get that information is by having the "display" process knowledgeable about its wiring. I.e., in the array of "REPORT" channels, which channel is connected to which philosopher, etc. This is not entirely desirable, however, since re-wiring such a network would break the "display" process.

Keywords: q7 , protocol


Question 107 (2004):

This is used for the animation:

    SEQ
      clear.states (4 + (4 * n), out)
      ...

but when I try to use "clear.states" I get an error! help.

Answer 107:

Saying what error you get might be useful.. But "clear.states" must be something you've defined yourself -- it's not provided by any library. The errors generated by the compiler are generally meaningful and useful, and should be telling you what the problem is.

Keywords: q7


Question 106 (2004):

Could you explain "SHARED" channels again and maybe give an example ? From the class they seem like a cleaver idea but now when it comes to coding them I am a little lost.

Answer 106:

There are two ways to do shared-channels in occam, and which one you choose will depend on whether you're coding on Linux or Solaris.

KRoC/Linux has built-in support for shared channels, called "anonymous channel types" in the form most useful for Q7. You can find a fairly terse example of these here.

Shared channels on the KRoC installed on raptor must be done manually -- by turning off compiler usage-checks and using "SEMAPHORE"s to provide mutual exclusion.

For comparison and reference, below are two equivalent versions of a simple test program that use shared channels:

    #INCLUDE "semaphore.inc"
    #USE "course.lib"

    PROC hello (SEMAPHORE sem, CHAN OF BYTE out, VAL INT id)
      SEQ
        claim.semaphore (sem)
        --{{{  output stuff
        out.string ("hello world from ", 0, out)
        out.int (id, 0, out)
        out.string ("*n", 0, out)
        --}}}  
        release.semaphore (sem)
    :

    PROC main (CHAN OF BYTE kyb, scr, err)
      #PRAGMA SHARED scr
      SEMAPHORE sem:
      #PRAGMA SHARED sem
      SEQ
        initialise.semaphore (sem, 1)
        PAR i = 0 FOR 10
          hello (sem, scr, i)
    :

and:

    #USE "course.lib"

    PROC hello (SHARED CHAN BYTE out!, VAL INT id)
      CLAIM out!
        SEQ
          --{{{  output stuff
          out.string ("hello world from ", 0, out!)
          out.int (id, 0, out!)
          out.string ("*n", 0, out!)
          --}}}  
    :

    PROC main (SHARED CHAN BYTE scr!)
      PAR i = 0 FOR 10
        hello (scr, i)
    :

Keywords: q7 , shared-channel


Question 104 (2004):

I have a quick question relating to my 'animation' - could you give any tips/ideas for nice(r) way of making the philosophers move about the screen without hard coding in the locations of every movement?

In my more 'advanced' animation (which has been a challenge to say the least) I have had a lot of hassle using a hard coded method. The code just to move a philosopher to the table (and it's currently not very smooth) is around 300 lines. Ouch.

I am sure there is a better way of doing things but I have racked my brains and I can't think of anything :(. The only other idea was to create a "large" VAL [][5][2]BYTE array that stored all the locations, and for each movement the required value is pulled out the array. That doesn't seem much nicer though; occam doesn't seem to allow you to span this sort of thing over multiple lines either.

Any sort of help would be greatly appreciated, however small!

Answer 104:

If ever you find yourself writing long sequences of repetitive code, where the differences are primarily in number values, you are doing something wrong, ugly and inefficient! So, your 300 lines of code is not a good idea.

Your 'better way' is much better, although it can be improved (see towards the end of this answer). Your VAL [][5][2]BYTE is, presumably, a 2-dimensional array of coordinates (i.e. [2]BYTEs), with the [5] index being for the philosophers and the unsized outermost dimension (i.e. []) being for the number of coordinates (i.e. the length of the path). That might make slightly more sense (and convenience for programming) with the two outer dimensions swapped around -- i.e. VAL [5][][2]BYTE.

occam does allow long lines to be broken across multiple lines ... but maybe I never told you! You can break a long line after commas, operators and the keyword IS. For example, the very long one-line declaration:

  VAL [n.phils][][2]BYTE path IS [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]], [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]], [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]], [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]], [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

can be much more readibly laid out:

  VAL [n.phils][][2]BYTE path IS
    [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]],
     [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]],
     [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]],
     [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]],
     [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

The rule about indentation for continuation lines is that any indentation at least as great as the initial line is allowed. So, the following, rather stupid, layout is also possible:

  VAL [n.phils][][2]BYTE path IS
    [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]],
           [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]],
  [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]],
   [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]],
         [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

but we wouldn't, of course, ever do that! Another use of breaking lines after commas we have seen lots of times -- in PROC headers with long parameter lists:

  PROC thing (CHAN OF INT in0, in1,
	      CHAN OF BYTE keyboard, screen, error,
	      VAL INT id, interval,
	      [][]REAL64 data)

instead of:

  PROC thing (CHAN OF INT in0, in1, CHAN OF BYTE keyboard, screen, error, VAL INT id, interval, [][]REAL64 data)

Breaking lines after operators helps keep large expressions neat -- for example:

    first := (first - second) + ( ((-first) + (third - second)) * (rotational.torque - (ratio/2)) )

could be written:

    first := (first - second) +
	       ( ((-first) + (third - second)) *
		 (rotational.torque - (ratio/2)) )

which might help a little.

Getting back to improving your path description for a wandering philosopher ... rather than declare a table of absolute coordinates for each path position, consider a table of relative movements. For example:

  VAL [n.phils][][2]BYTE path IS
    [[[left, 3], [up, 5], [right, 2], [up, 4], [left, 1], [down, 2]],
     [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], [down, 3]],
     [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]],
     [[up, 5], [left, 5], [down, 2], [up, 2], [down, 1], [up, 3]],
     [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], [left, 6]]]:

where your movement code interprets [left, 3] as "move left 3 places" etc. Predeclared, of course, would need to be something like:

  VAL BYTE left IS 0:
  VAL BYTE right IS 1:
  VAL BYTE up IS 2:
  VAL BYTE down IS 3:

Elsewhere would be needed a table of absolute start coordinates for each path movement.

That just leaves the problem that all the above path lengths have to be the same length? With the modern occam-pi language, that's not a problem ... we can use dynamically sized mobile arrays. For classical occam, you could pad out short paths with some dummy movement elements - e.g. STAY where:

  VAL BYTE stay IS 255:

  VAL [2]BYTE STAY IS [stay, 0]:

  VAL [n.phils][][2]BYTE path IS
    [[[left, 3], [up, 5], [right, 2], [up, 4], STAY, STAY],
     [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], STAY],
     [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]],
     [[up, 5], [left, 5], STAY, STAY, STAY, STAY],
     [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], STAY]]:

Keywords: q7 , animation , long-lines


Question 103 (2004):

How do I output the value of "n.sat.down" to the screen ? Is the only way to add an "out" channel the PROC header and do an "out.int" on it ?

Answer 103:

If "n.sat.down" is a tag in a variant protocol, it doesn't have any meaningful value. Some meaningful data might be communicated as part of the protocol, however. You mention adding an "out" channel, but to what PROC in particular ?

To avoid complication, the correct place to handle the output of this information is in your "display" process. Wiring it up to the "security" process (by default the only process that knows how many philosophers are sat down) should be fairly straight-forward.

Keywords: q7 , output


Question 102 (2004):

Is it possible to specify more than one condition in an "IF" process ? For example:

    IF
      x = 0 AND y = 0
        -- do something

If so which operators should be used ? When I compile something similar to the above I get an error saying:

    Expected new line, found AND

Answer 102:

This error occurs because you need explicit bracketing (occam has no operator precedence), even though the alternatives don't make much sense in this case. The correct way to write that would be:

    IF
      (x = 0) AND (y = 0)
        -- do something

Keywords: q7 , operators


Question 101 (2004):

Do we need to use occam that is going to work on raptor or can we make use of the additions in the KRoC/Linux version. For example I'm considering using the STEP stride part for the replicator.

Next when using replicators, why can't I pass "i" into the "cursor.x.y()" PROC in this code ?

    PAR i = 8 FOR 5 STEP 2
      SEQ
        cursor.x.y(23,i,out)
        -- print stuff

Where "i" is the line number. The error is a type mismatch for parameter 2 in "cursor.x.y()". Surely "i" is an integer and should be accepted ?

Any help appreciated...

Answer 101:

For KRoC/Linux extensions (rather, occam-pi extensions), yes, using those is fine. We'll most likely be testing your code on such a machine.

The reason you can't pass "i" as a parameter is because "cursor.x.y" takes "VAL BYTE" parameters (not "VAL INT"). The solution for such things is to cast the parameter to the appropriate type:

    cursor.x.y (23, BYTE i, out)

Given the code you've got above, it should generate another error also (related to parallel usage), but that should be slightly more obvious.

Keywords: q7 , type-cast


Question 99 (2004):

Why in "PROC philsopher (...)", do you have:

    PAR                -- pick up
      left ! TRUE      -- forks
      right ! TRUE

    ...  eat

    PAR                -- put down
      left ! TRUE      -- forks
      right ! TRUE

i.e. why is the code the same for pick up and putting down the forks ?

Answer 99:

The reason is simply that it requires less channels. Extra channels could be added for the putting-fork-down events, but it's better if we can re-use the existing channels (less coding and less plumbing on the network diagram). The same reasoning applies to the fork process -- adding extra channels is possible, but unnecessary.

The direction of communication along the left and right channels is important to the fork process. That has to choose (i.e. ALT) between competing signals from its adjacent philosopher processes, who might be trying to pick it up. That signal is represented by a channel communication. We can only ALT between input communications, so the forks must input and the philosophers must output. This is for picking up the forks.

For putting down the forks, neither side needs to ALT ... so the direction of the communication, signalling this event, doesn't matter. So, the fork could output to the philosopher who picked it up (and be blocked until that philosopher did a corresponding input to indicate that it was putting down the fork). But, then, we would need another channel (a putting-down-channel) between each philosopher and fork - since channels may be used in one direction only and we are forced to use the existing ones in the other direction. So, the simplest thing is to reuse the existing channels and get the fork to input from it (and be blocked until the philospher holding it does an output to indicate that it was putting down the fork) ... which is what happens.

Note that we do use different channels between each philosopher and the security guard to represent the let-me-in-to-the-dining-room and let-me-out signals. The security has to ALT between all of these, so the direction of communication has to be from the philosophers to security. The security has to ALT both for the let-me-in and let-me-out signals, unlike the fork (which only has to ALT for the pick-up signals). But the security has also to refuse further let-me-in signals -- if four are already in -- whilst allowing let-me-outs! Doing that trick with only one channel used for both let-me-in and let-me-out signals is hard. So, we used separate channels.

Keywords: q7


Question 96 (2004):

Do we put the "VAL INT id" call inside the "PROC" header for philosopher and fork, or is this done in the main body of the "PROC" ? I think it is the former, but I'm not sure how to replicate this in "secure.college".

Answer 96:

Be careful of your terminology -- "VAL INT id" would either be a parameter or abbreviation (that latter which you're unlikely to be using). It's not a "call" of any kind.

You are correct in thinking it should be in the PROC header for the philosopher, but what the PROC gets is a value (the "VAL" bit), not a variable. The replication in "secure.college" is already done for you -- you just need to "plug-in" the desired value (that should be fairly obvious if you look around, or compare the code with the network diagram for it). Also, looking at previous questions relating to q7 (particularly for previous years) will tell you the answer.

Keywords: q7


Question 95 (2004):

There seems to be some conflicting deadlines for Q7 ? On the Student Portal it says:

CO516
 Parallel and Imperative Programming
 A4 DINING PHILOSOPHERS ANIMATION
 Mon, Wk 18 
 Tue, Wk 3 
 phw
 Mon, Wk 21 
 Reception

on the co516 webpage it says:

ASSESS 4 A4 DINING PHILOSOPHERS ANIMATION 60 32 3 Tuesday 17 Thursday

and my seminar leader says the 14th Feb is the deadline. Which of the above is the correct deadline?

Answer 95:

Monday of week 18 (14th February) is the actual deadline, as we have been telling you in the seminar groups. So it's the webpage that's wrong. The data that appears under "assessments", etc. is not current -- we're not allowed to pull data from the live student database so stuff there will always lag behind the real student database.

Keywords: q7


Question 89 (2004):

Have we covered enough material to start the dining philosophers this holidays ?

Also are there any useful areas we can start to look at for revision (in terms of website with practice questions on what we've covered so far?)

Answer 89:

The dining philosophers have been covered in the lecture, so yes, you could in theory make a start on this. But we'll be looking at this in more detail (e.g. ways of doing animations, etc.) in the seminars next year.

For revision material: the course notes (including the various papers on occam); Fred's occam tutorial; and past exam questions. But these are all obvious..! You should be able to decide for yourself whether something in a (past exam) question has been covered or not. Your own lecture notes may also be useful to this end.

Keywords: q7

2003

Question 117 (2003):

Whenever I report the number of philosphers sat down, it seems to just report 4 all of the time,

    [snip code]

Answer 117:

This code looks fine. It's most likely an error with the timing/delays in your animation. Without adequate `thinking' delays, the philosophers will always be trying to eat.

Keywords: q7


Question 116 (2003):

On the line 'forkStat[0] == 0' I get the following error message. What does it mean ?

    :          IF
 122:            forkStat[0] == 0
    :              SEQ

Error-oc-q7.occ(122)- Operands have different types for operator "=="

Answer 116:

The error is exactly as reported: the operands for `==' are of different types.

Firstly, comparison in occam is just `=' (this is not Java!). At a guess, `forkStat' is an array of channels, and `forkStat[0]' a single channel. You can't compare a channel with anything -- it doesn't have a value. What you need to do (if this is indeed a channel), is input the value first:

    INT x:
    SEQ
      forkStat[0] ? x
      IF
        x = 0
          ...

It's hard to tell for certain without seeing more of your code (whole `display' process, for example).

When you've got multiple input channels, and want to receive a value from any of them, use an ALT (or replicated ALT if suitable).

Keywords: q7


Question 115 (2003):

I get an error message saying that the `fork' is incorrectly indented, but I don't know why:

    PAR i = 0 FOR 5
      philosopher (...)
      fork (...)

Answer 115:

You've removed the `PAR' inside the replicated `PAR'. A replicated PAR only replicated one process -- you're trying to give two, hence the indentation error.

The correct way to write this (as in the original `secure.college') is:

    PAR i = 0 FOR 5
      PAR
        philosopher (...)
        for (...)

Keywords: q7


Question 114 (2003):

Hi,

I dont quite understand when we should use `flush(out)'. Should this be after every time we make a statement like:

    out.string ("Philosopher ", 0, out)

or after each set of changes such like:

    out.string ("Fork ", 0, out)
    out.int (n + 1, 0, out)
    flush (out)

Answer 114:

After each set of changes. See the answer to Question 91 (2000).

Keywords: q7 , flush


Question 113 (2003):

Hi,

Until recently I had my dining philosophers program running fine with scrolling text output, now I have added the table style animation it runs very slowly and sometimes there is a visible pause as it outputs a word. Are there any obvious things that could be causing this?

I an doing the animations like this:

    SEQ
      clear.states (4 + (4 * n), out)
      cursor.x.y (32, BYTE (4 + (4 * n)), out)
      out.string ("Sitting", 0, out) 
      flush (out)

Thank you.

Answer 113:

Nothing looks wrong with the code you posted. If you're running it over a network (e.g. on raptor logged in from home), that could be the reason. It might also be raptor being slow (with everyone else doing their dining philosophers on it).

Keywords: q7 , animation


Question 112 (2003):

Hi,

I have a problem with parellel outputs when I make the `fork's report their states. I have one channel coming out of `secure.college' and the compiler says I am making parallel outputs on this channel. Both the forks and philosophers report down this channel. i.e.:

in `secure.college':

    PAR
      philosopher (..., actionsOut[i], ...)
      fork (..., actionsOut[i], ...)

where `actionsOut' is the channel out of `secure.college'.

Is the only way to do this to have two channels out of `secure.college'. i.e.:

    PAR
      philosopher (..., actionsPhil[i], ...)
      fork (..., actionsFork[i], ...)

Or is there a better way, as doing it this way will mean the multiplexer has to be much more complicated.

Thanks.

P.S. is there a rough number of microseconds you expect the delay in the philosophers to be or is this en tirely down to our discretion? thanks.

Answer 112:

`actionsOut' is an array of channels, not a single channel. When the replicated PAR expands, each philosopher gets a separate channel (elements of the `actionsOut' array).

For example:

    PROC foo ([]CHAN INT out!)
      PAR i = 0 FOR 5
        bar (out[i]!)
    :

Is equivalent to writing:

    PROC foo ([]CHAN INT out!)
      PAR
        bar (out[0]!)
        bar (out[1]!)
        bar (out[2]!)
        bar (out[3]!)
        bar (out[4]!)
    :

When the PAR replicator in your first fragment of `secure.college', you end up using the same channel for a parallel `fork' and `philosopher'.

Adding an extra array of channels is one solution, but as you point out, multiplexing this is messier. A better solution is to use channels in the same array, but in a way that avoids `collisions'. This can be done by changing the array subscript expression for either the `philosopher' or the `fork'. E.g.:

    PAR
      philosopher (..., actionsOut[i], ...)
      fork (..., actionsOut[i+5], ...)

If you expand the PAR replicator, none of the resulting indexes are the same (so no parallel outputs).

In response to your last point, no, not really. The delay must be random, of course (using the random function). As rough guide, somewhere between 2 and 3 seconds, perhaps longer for the `eating' delay. Ultimately, you should find a suitable range, such that the animation runs `smoothly' (not too fast and not too slow).

Keywords: q7


Question 106 (2003):

On question 7, my philosophers pick up the forks fine but sometimes they tend to just pick up one fork and can eat and sometimes have 2 forks. I am using 3 multiplexers in total one for the philosophers, one for the forks and another to plex them two and also the security guard. I wonder if this could be affecting the output?

Answer 106:

When a philosopher is eating, they should have both forks (on the display). There are three `messages' involved in this: left-fork picked up, right-fork picked up, and philosopher eating. Due to the way the system is `wired-up', the `display' process may receive these in any order. There is a chance that the ordering will be: philosopher-eating, left-fork then right-fork. Thus, it is important to ensure that display updates involving the philosopher do not intefere with display updates involving the forks -- accidently erasing previously outputted text, for example.

What you describe sounds like an artifact of the plumbing of your system - because you have 2 levels of multiplexing of report messages to your display process. Fortunately, this is fairly easy to correct!

When a philosopher or fork or the security guard outputs a report, if that report goes directly to the display process we know that that display process will update the screen (and FLUSH!) before dealing with the next report. However, if a fork (or philosopher) report goes first to a special fork (or philosopher) multiplexing process which then forwards it on to the actual display process, all the fork (or philosopher) knows - after outputting its report - is that that first level mulitplexor has got it, not that the display process has received it! The fork process may then interact with a philosopher (who is putting the fork back on the table) before the display process has shown the fork in the hand of that philospher. It is possible for the display process to animate the philospher moving to the eating position and then to the thinking position before it animates any fork movement, :(.

The simple fix is to get the philosopher or fork process to wait for confirmation from the multiplexor process to which it is connected that that multiplexor has indeed forwarded it to the display process - before the philosopher or fork process moves on. How to do this is described in the answer to Question 76 (2003).

Keywords: q7


Question 98 (2003):

How do we submit q7 ? Do we just hand in the hard copy at the octagon or do we need to submit this electonically as well?

Answer 98:

The submission of the code will be electronic (so we can test/run your programs). You'll also need to submit a network diagram (on paper) to the CAS office. Keep an eye on the CS2 newsgroup for submission details (will be posted nearer the deadline).

Added later: submission directories have now been set up for you on raptor:

  /usr/local/proj/co516/q7-2004/your-login-name/      (Unix view)
  \\raptor\files\proj\co516\q7-2004\your-login-name\  (Windows view)
Please copy only your source code file(s) into there - usually this will just be one file called q7.occ. You can do this as often as you like up till the deadline - midnight, Thursday, 12th. February (that's the midnight between Thursday and Friday).

You must also submit a paper copy of all relevant network diagrams for your solution. These must correspond to your code submitted electronically, with all channels labelled with the names used in your code. Don't forget to indicate directions of channel flow. This copy may be machine produced or neatly drawn by hand. This part of the submission must be to the CAS office, with a cover sheet (copies of which will be in the Co516 pigeon hole, near CAS Reception), BEFORE they close at 4pm on that Thursday.

Keywords: q7


Question 97 (2003):

I have an input channel into `secure.college()' of type INT which will contain the ID for each philosopher and fork. This channel will be connected to both the philospher and fork PROCs. How do I make sure that I get a number that is one greater than the previous down the channel so that each philosopher has a unique ID?

Answer 97:

If you try and write code as you suggest above, the compiler will simply reject it (on a parallel (mis)usage error). Assigning IDs this way is hard. One question you should ask yourself is: ``do I really need to convey this information to the philosophers/forks using a channel communication ?''. The answer to that is: no. A `VAL INT id' parameter (for philosophers and forks) would be much simpler, and much clearer.

Keywords: q7


Question 96 (2003):

I'm trying to do a fair-ALT, but there are 11 channels to ALT over and thats a lot of of code! I was wondering is there a way of looping around FOR statements? What I mean is if the first time you write, say,

    ALT i = 0 FOR 5

is there anyway so that the second time I can write

    ALT i = 1 FOR 5

but have it so the 5th iteration loops back to channel 0 (i.e. the one I started on the first time). Sorry if thats unclear.

Answer 96:

I'm not sure what you're asking here -- at a guess you're confused as to the operation of a replicated-ALT. One key idea is that it is a replicator, not a loop as such. Writing:

    ALT i = 0 FOR 5
      in[i] ? x
        P(x)

is equivalent to:

    ALT
      in[0] ? x
        P(x)
      in[1] ? x
        P(x)
      in[2] ? x
        P(x)
      in[3] ? x
        P(x)
      in[4] ? x
        P(x)

For more information, look in the course notes that describe the ALT, around slide 5-29. The code for a fair-ALT is also given explicitly on slide 10-23, as you have been told many times! Also check out other related anonymous questions, particularly those on alternation and the fair-alt.

Keywords: fair-alt , q7


Question 93 (2003):

I seem to have some problems with the security. If 4 philosophers are sitting, it reports that 3 philosophers are sitting until another philosopher moves: at that point it says that 4 philosophers are sitting. This is my code for the philosopher and security:

    [snip code]

Answer 93:

Usual things about not posting huge chunks of code to the anonymous Q+A page. This sort of question should be directed to your seminar leader.

However; the code you posted looks fine. Check that your `display' process flushes the output when that information is updated. The problem you describe sounds like a classic symptom of this.

Keywords: q7


Question 92 (2003):

Are there any example source files of animation; I attended the seminar, but am having problems with even starting to animate.

Answer 92:

There were four seminars you should have attended ...

You could look at `test_utils.occ' in:

    /usr/local/courses/co516/examples

on Raptor. Or `examples/sort_pump.occ', but that uses `goto.x.y', which is now deprecated, rather than `cursor.x.y' (the two are essentially similar, however).

Essentially, text-animation is a repeating process of: move cursor, then output something. This can be seen most obviously in the `a7' model answer.

Source code for other animations can be found on Fred's occam page. These range from trivial to rather complex.

Keywords: animation , q7


Question 91 (2003):

I'm confused on how to get the forks to move correctly. Is it a better idea to have to separate tags for left and right forks (``left.fork'', ``right.fork'') or to just have one (e.g. ``fork; INT'') ?

Answer 91:

You need to mention what the `INT' is for, really. If it's the `id' of a fork, then that's one bit of information, but left/right is separate. Fork `i', for example, can be picked up or put down, by the philosopher on the left or right. The question is: do you need all this information from the fork, or just some of it, to do the animation ? -- watching the `a7' model answer should tell you this.

Keywords: q7


Question 88 (2003):

I have some mystery regarding Q7 I'd like to clear up. As I understand it the college must communicate its status to the display process via a number of channels. I think the only thing the display process needs to know is the status of each philosopher; the status of security and the forks can be deduced if we know what the philosophers are doing.

As it stands the college is self contained and there is no obvious way to report, at any given time, its status to another process. One solution I can see is to replicate all communications between the processes in college, and route them to the display process. The display process would maintain its own picture of the college, which it updates according to the inputs on its channels. This seems rather complicated.

Alternately the display process could again recieve a copy of all internal college communications, but conforming to a protocol such that it can update its picture of the college without other information about its status. For example, when a philosopher wishes to sit down, instead of outputting a boolean he outputs a specific message the display process knows to mean "waiting to sit down" and can update its picture accordingly. This is assuming that the animation is not drawn frame at a time, but continuously updated as information comes in.

In these cases what does display need to communicate with in order to get a complete picture ? Security can tell it who is wanting to sit down and stand up, but it also needs to know the fork status. Presumably this will be the job of either forks or philosopher.

I have trawled the anonymous questions of old, none of the answers to which have baffled me, but I still cannot get this fundamental.

Answer 88:

All the questions you have asked have been discussed in your seminar groups for the last 4 weeks. These Q&A pages are in no way a substitute for attending those seminars. Your question suggests ideas that are either illegal (with respect to occam semantics) or far too complex. Simple solutions have been presented in the seminars.

Having said this, I will attempt to answer your questions. However, those who know how to do this problem should skip these answers, as correcting the confusion in your questions may confuse others unnecessarily.

In response to your first paragraph, yes, the state of the forks can be deduced from the philosopher, but it's easier to have the forks report their state. It also makes more sense; the state of a fork should be reported by the fork, not by something else.

You are sort of correct in your second paragraph, although I'm not sure what you mean by `replicate all communications'. Thankfully, setting up this extra `wiring' is not complicated in occam. However, the `display' process does not need to maintain the `state' of the college (see the next paragraph). The extra wiring can be handled using an array of channels; the `display' process gets the inputting ends as a `bundle' (array), whilst the outputting ends are distributed amongst the other processes. This will require some modifications to the `secure.college' process.

The third paragraph is essentially what we're expecting you to do for this assignment. The `philosopher', `fork' and `security' processes report their actions to the display as they happen. The display process just inputs these messages and draws on the screen accordingly. The animation should indeed be updated on-the-fly; it should not be done frame-by-frame. The only disadvantage is that the display cannot be completely redrawn (i.e. if it got corrupted, somehow). This isn't a problem for this assignment, however.

The various messages are best handled using a tagged protocol. The previous assignment, q6.occ, used a tagged protocol. The various `messages' have been discussed in the seminar groups. The q7.occ file gives some indication of what is required:

    Your task is to animate this demonstration.  Links will need to
    be made from the college to its external environment, through
    which the philsophers (and, maybe, the forks and the security guard)
    report their state.  These links are gathered by a fair-ALTing server
    that drives a screen display in response to incoming information
    from the college.  Thinking and eating by the philosphers should
    be modelled by random (but finite!) delays.  The animated display
    should reflect the round table in the dining room ...

Running the example solutions (on raptor, see Question 80 (2003)) should give you an indication of what is required -- i.e. what is being displayed (and therefore reported) there ? (`a7' is the example minimum-but-full-marks solution; the other example solutions are more animated).

Reporting by each process should be restricted to its own `state'. I.e., the security process should not report that philosophers are trying to stand up or sit down. This is actually very hard.. The only state the security process maintains is how many philosophers are actually sat down -- it should report this. When a philosopher stands up or sits down, that should be reported by the philosopher -- not anything else. It is both more logical and simpler to have things this way, since it keeps the logic of each process `intact'. E.g. I might take your philosopher, fork, security and display processes, completely re-wire the nextwork (within reason), and still expect it to work. Having the correct functioning of processes depend on their external wiring is not really a good idea.. (such processes must conform to the protocol that they conceputally agreed on, however).

I hope this clears things up a bit. If you still have queries, or want some points explained in more detail, I'd suggest emailing or visiting your seminar-leader or other member of the course team (we all have a desk somewhere on campus).

Keywords: q7 , animation


Question 87 (2003):

Hi, what datatype does `cursor.x.y' take as im getting errors about wrong parameters.

Answer 87:

The `x' and `y' parameters are BYTEs. The PROC header for `cursor.x.y' is:

    PROC cursor.x.y (VAL BYTE x, y, CHAN BYTE out!)

See the answer to Question 7 (2000) for information on how to do a type-cast in occam.

Keywords: q7


Question 83 (2003):

I am stuck trying to do the implementation of philosopher, I know that we should try and use a random time, but at the moment I am just trying to implement it with a static time, say 5 secs.

    [snip code]

Thats what ive done so far, and dont really know how to do the think and hungry stuff.

Thanks for any help

Answer 83:

We've mentioned this before, but posting large chunks of code to the anon Q+A page and simply asking what's wrong isn't particularly useful -- the anon Q+A is a group forum, not an individual forum. You question would have been better directed to your seminar leader.

The code you pasted is largely the default `philosopher' code, with some minor additions.

If you want to know about the `random' function or timeouts, see the keyword index entries for timers and random. Reading through the questions and answers for past questions (particularly relating to q7) should hopefully answer any questions you might have. Alternatively, talk to your seminar leader (preferably during the seminar).

Keywords: q7


Question 80 (2003):

Can we still get full marks on q7 if we just do a basic line by line 'animation' of what is going on ?

Answer 80:

If you have just a scrolling output of events, the answer is no. The minimum solution (that can get full marks) is a table-driven animation, shown by the `a7' example answer. This can be found on raptor in the `/usr/local/courses/co516/answers/' directory.

Keywords: q7

Referrers: Question 88 (2003)


Question 79 (2003):

Having problems with q7. In our seminar we were told to use:

    i, seed := random (n, seed)

to create a random number. Can you explain what each of the elements are, also can you give a basic example.

This part of the Philosopher proc is going to be a base for all 5 philosophers, but there is the problem of each having the same random number for each one. Do we need to have a different value of `n' and `seed' each time the PROC is run? Or is this dealt with by the random function ?

Answer 79:

The `seed' is there to initialise the random number generator. More specifically, it is the internal state of the `random' function -- functions cannot retain their own state.

Before you call `random' for the first time, you need to initialise `seed' to a number between 1, and the maximum positive integer minus one. When you call `random' for a second time, use the new `seed' returned by the first call, and so on.

Yes, you need a different starting seed for each philosopher (hint: each philosopher has a different `id').

`n' is the range of the random number generated. i.e. `random' will return a random value between 0 and (n-1); in your example, assigned to `i'.

Keywords: random , q7


Question 78 (2003):

I'm quite confused on how I can assign each philosopher an identity. I've modified the header of the PROC philosopher in the following way:

    PROC philosopher(CHAN OF INT id, CHAN OF BOOL left, right,down, up, CHAN OF MESSAGE report)

This means that the display PROC has 16 input channels. I'm not sure this is the right way of doing it.

Answer 78:

Assigning IDs to the philosophers is better done by simply using a ``VAL INT'', passed to each philosopher from the PAR replicator that sets the network up.

Communicating the ID to each philosopher (using the `id' channel you added) is certainly possible, but definitely not the simplest way.

Keywords: par , q7


Question 76 (2003):

Hi, I'm just experimenting with my animation for q7 and I've come across an annoying problem with protocols in occam. My problem is that each channel seems to have a buffer. This creates a problem in protocol channels because there is no FLUSH like with the screen output. This means I have forks multiplying all over the place and philosiphers jumping around in mad bursts, despite huge delays tha are supposed to be in their movement. Is there any way of creating the effect of FLUSH on a protocol channel?

Answer 76:

Channels have no buffers - no matter what their protocol. So you have to explain/analyse your problem a bit more. Once a channel output has completed, the other side has definitely taken it. Your channel output does not complete because the channel has buffered your message in some way.

If what you want is for the outputting process *not* to continue until the inputting process has completed some response to its input, you need to program that - e.g.:

    PROTOCOL THING
      CASE
        data; ...                  -- the message types
	other; ...                 -- other message types
	...
        complete                   -- only accepted once response is complete

Then the sending process:

    SEQ
      ...  stuff
      c ! data; ...
      c ! complete                 -- wait for response (e.g. animation) to complete
      ...  more stuff

and the receiving process:

    c ? CASE
      data; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE
	    complete               -- let sender know all is done
	      SKIP
      other; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE
	    complete               -- let sender know all is done
	      SKIP

Note: here is a little bit more of occam! If a CASE input only deals with one case (as in the above), it can be shortened to a one-liner:

    c ? CASE
      data; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE complete        -- let sender know all is done
	  SKIP
      other; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE complete        -- let sender know all is done
	  SKIP

If the response to that one case is SKIP, that response can, of course, be now omitted:

    c ? CASE
      data; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE complete        -- let sender know all is done
      something.else; ...
        SEQ
          ...  response (e.g. animation)
          c ? CASE complete        -- let sender know all is done

Hope that helps! [Note: you only need to engage in such trickery if you have more than one process doing animation. If you have just the one and it does some animation in response to a received message, then that animation will complete before it processes the next message and does the next animation. This is all that's needed to do the minimum form of animation required for full marks - as shown by the executable model answer (answers/a7). However, to get parallel animation - see some of the other example answers - you will naturally need parallel processes and tricks as outlined above.]

Keywords: q7

Referrers: Question 106 (2003)


Question 75 (2003):

When will we have all of the information presented in lectures to be able to do q7? Thanks.

Answer 75:

You have had all the technical knowledge needed for q7 since around week 10 last term. Precise details of what is required by way of animation to get full marks, together with fairly detailed suggestions as to how that may be implemented, is being presented and discussed in the seminar groups (weeks 13-15). Attendance at seminar groups is, of course, compulsory ...

Keywords: q7

2002

Question 37 (2002):

Could you please explain a little more how you would go about implementing the random time delay? I have read through the previous questions on it but I'm still a little lost. Is the time delay between philosophers doing different actions or in the display process?

Answer 37:

It's in the philosopher processes - not the display.

The question says:

Thinking and eating by the philosophers should be modelled by random (but finite!) delays

In the "philosopher" process there are two folds:

  <!--{{{  think-->
  SKIP
  <!--}}}-->

and:

  <!--{{{  eat-->
  SKIP
  <!--}}}-->

You should replace the SKIPs by random delays.

Keywords: q7 , random , timers


Question 36 (2002):

Do we need to design the philosopher system to end "gracefully" like in previous assignments?

Answer 36:

No.

Keywords: q7 , graceful-termination


Question 33 (2002):

Hi, it has been strongly suggested by our seminar leader that we use protocols for the state report channels to the display process. The reports disclose the any change is state from the philosphers, forks and the security guard. Obviously you need to fair multiplex all the philosphers together and all the forks??? However, how can you multiplex three different protocols together??? You can't can you? If not, then I guess we write some display process with three input channels one for each protocol, and work that way.

Answer 33:

Fair mulitplex the philospher reports down to one channel. Same for the forks. That leaves 3 channels, with different protocols, coming to the display process - say a, b and c. To fair-alt those:

  WHILE TRUE
    SEQ
      PRI ALT
        a ? ...
          ...  react to the a mess
        b ? ...
          ...  react to the b mess
        c ? ...
          ...  react to the c mess
      PRI ALT
        b ? ...
          ...  react to the b mess
        c ? ...
          ...  react to the c mess
        a ? ...
          ...  react to the a mess
      PRI ALT
        c ? ...
          ...  react to the c mess
        a ? ...
          ...  react to the a mess
        b ? ...
          ...  react to the b mess

Bit repetitive writing the reaction codes thrice ... so make a PROC for each reaction ... just invoke that PROC thrice.

However, simpler-but-more-dangerous is just to have one protocol that all philosophers, forks and the security guard to use - that's 11 channels, all with the same super-protocol, coming out of the college. Plug those into the display and simply fair-alt that!

It's unsafe to use one protocol for all reports - since a fork, for example, could send a philosopher report by mistake! This is the sort of thing that can happen somewhere down the life-cycle of a product during maintenance. However, for this exercise, you will not lose marks for doing so ... so long as, of course, you don't make any mistakes that this approach allows!

Keywords: q7 , fair-alt


Question 31 (2002):

I would like to use colour in my solution to Q7. The PROC fg.col in shared_screen.occ looks useful ... however, I am unable to use the shared_screen.occ code. I have the following lines at the top of my source code:

  #INCLUDE "shared_screen.occ"
  #USE "shared_screen.inc"

Many errors are generated relating to this, such as:

  Error-oc-shared_screen.occ(337)- pc subscripted too many times
  Serious-oc- Too many errors, maximum is 100.

What am I doing wrong?

Answer 31:

Sorry - we hadn't told you how to use this package. It's not part of the basic "course" library! Before explaining how to access, let me stress that noone needs to find out about and use this stuff - it's only there to provide a rich set of drawing mechanisms for those who want to do some really fancy animation. Even then, you don't have to use it ... but you will end up inventing something similar.

Something anyone could have done is simply copy those two files:

  libsrc/shared_screen.inc
  libsrc/shared_screen.occ

into the start of your own q7.occ file. Then, your own code could simply use anything defined in them. Note that the order is important - the shared_screen.inc must go before the shared_screen.occ file (which uses protocols and data types defined in shared_screen.inc).

Better would be to copy those files into the same directory as your q7.occ file and start your file with:

  #INCLUDE "shared_screen.inc"
  #INCLUDE "shared_screen.occ"

Again, note the ordering! These directives simply tell the compiler to pull in those files at the point of those #INCLUDEs.

Best is not to copy those files at all and use the library. All you haven't been told is the name of the library - which is "ss". Currently, only PROCs and FUNCTIONS are saveable in kroc libraries, which means that constants, data types, prototcols (etc.) have to be pulled in as #INCLUDEs. Anyway, to do this, your file needs to start with:

  #INCLUDE "ss.inc"
  #USE "ss.lib"

These can be followed, or preceeded, by other library accesses - e.g.

  #INCLUDE "consts.inc"       -- standard course library constants
  #USE "course.lib"           -- standard course library

We're not quite done. When compiling, the occam compiler (invoked by the kroc shell script) will find the relevant files. [Note: those working with the Linux kroc need to ensure their OCSEARCH environment variable is set up correctly.] When doing final linking (also invoked by the kroc shell script), we have to tell the linker where to find the library code. In fact, the kroc script uses the standard gcc (Gnu C Compiler) to do this linking - i.e. something different from OCSEARCH happens. Anyway, the compile command needed is:

  kroc q7.occ -lss

Linux users have always had to do something like this to link in the course library (which the kroc script on Solaris machines has been set up to do automatically). So, on Linux, if you want both libraries linked in to your executable, the command is:

  kroc q7.occ -lss -lcourse

Enjoy!

Keywords: q7 , colour , animation


Question 30 (2002):

How many lines of code, rougly, is your solution to q7-dining philosophers?

Answer 30:

The source code for the model answer executable, answers/a7, has 382 lines. These include all the lines in your starter file, exercises/q7.occ, which has 106 lines. So, it can be done with just 276 new lines ...

Keywords: q7


Question 29 (2002):

The random function says that it needs an integer at least 1. At the moment my seed is:

  id + modified.time

I know that my id can equal zero. You said that time could be negative, so I assume that it can equal zero as well. At the moment my modified time is:

  t /\ #7FFFFFFC

I have a vague understanding ofhow this works, but it looks to me that my modified.time can equal zero aswell, making it possible to break the random function. Do I need to change the bitvalue that I /\ with t?

Answer 29:

Your id and the timer value could both be zero - the latter could be negative as well! So, your concerns about the ideas above are valid. Check out the answer to Question 69 (2000), especially David Wood's suggestion at the end.

On a general point, you are strongly advised to browse through the anonymous questions and answers from previous years. On animating the Dining Philosophers, there was much discussion and plenty of good advice. For example, look at Question 68 (2000) ... and lots of others.

Keywords: random , q7

2001

Question 27 (2001):

I am having trouble modifing the fork process in the dining philosopher's question. What I want to do is basically have a fair ALTing process going over the two input lines, left and right.

I have already implemented a fair ALTing process in my animate process, but the difference there was that all the input lines were called the same name -- i.e. state[0], state[1] etc., so implementing it there was easy from the definition given in the notes. The problem with the fork process is that the input lines have two distinct names, and so the definition of fair ALTing does not translate as obviously.

What I have tried to do is give them the same name, so in the fork header I have put '[]CHAN OF BOOL in', but I could not get it to work this way after many attempts. My question is: is this the correct way to be going about altering fork?

Answer 27:

There are two ways. One is to create a channel array abbreviation for the two scaler channels - i.e.

  [2]CHAN OF BOOL c IS [left, right]:

Normal anti-aliasing rules now apply - you can't use the names left and right anymore (because you have the new names, c[0] and c[1], for them). But you now have an array of channels and the usual fair ALTing coding (see slide 10-23) can now be applied.

Second way: don't be clever and just write:

  WHILE TRUE
    SEQ
      PRI ALT              -- first give left priority
        left ? ..
          ..
        right ? ..
          ..
      PRI ALT              -- then give right priority
        right ? ..
          ..
        left ? ..
          ..

Keywords: q7 , fair-alt


Question 26 (2001):

Do we really need the q7 process, because I place my display process in the secure.college process?

Answer 26:

It's the q7 process that has the screen channel, along with the other compulsory channels in its parameter list that are needed for the starting process of the (kroc) occam executable. If you give that parameter signature to your secure.college and make that process the last one in your source code, then that will work fine. But that has bundled up your display process inside your college.

I would prefer the college logic to be independent of its display. That way, we can change the display logic (e.g. to drive some graphics window) without having to touch the college.

Keywords: q7


Question 25 (2001):

For the dining philosophers, I have created my own display process as required. However, I am not sure how to link all the processes together in a network under the q7 process. Any help??

Answer 25:

This is a bit too general a question to answer -- need your source code to point to what you're doing wrong.

All I can offer is this. The q7 process has the screen channel -- plug that into your display along with the (newly declared) report channels, whose other ends are attached to your modified secure.college. Hope that helps.

Keywords: q7


Question 24 (2001):

This is more of an anonymous observation really. I'm sitting here looking at q7.occ and, to be honest, I haven't got the first clue on how to start this assesment. I've been to the lectures and the classes, but me along with quite a few others who I have been talking to over the weekend have got no idea. I appreciate that yes some people have managed to do it, but the others are struggling.

Plus also after talking with my friends we all realised that nobody says anything in the classes apart form a select few which makes for an uncomfortable atmosphere when the postgrad is standing in front of a bunch of students who don't say anything for an hour. Perhaps it would have been better to concentrate more on the dining philosophers assessment in classes? I haven't got many notes on it at all.

Answer 24:

The assessment was set last November, when you had enough technical information to solve it. The occam variant PROTOCOL makes the solution neater and that was introduced by the end of last term. The first two seminar classes this term were devoted to explaining the assessment and talking through the recomended way to solve it. If you 'haven't got many notes on it at all', that is not our fault. That assistance was provided six weeks ago and the assessment could have been completely finished at that time. Last weekend is a bit late to start on this work and complain that you do not know what to do.

Fully participating in seminars is crucial to getting the best out of them. We try to get everyone involved to our best ability and sometimes do not succeed. Sometimes this is our fault. However, if a student has done no preparation for the seminar (e.g. has not worked on the exercises being discussed in between seminars), then that student will find it difficult to contribute to the seminar and will feel uncomfortable.

Keywords: q7


Question 22 (2001):

On slide 6-70 of the occam notes you say:

Modify the fork process so that it guarantees service on each input - even if the other one is perpetually busy. No philospher must starve because of greedy colleagues!

My question is what service should it guarantee on each input? What do you mean by service?

Answer 22:

From a low-level point of view, service in occam always means accepting a channel input. High-level viewpoints depend on the high-level semantics of the process being considered.

In this case, the service performed by a fork is being-picked-up. What needs to be guaranteed is that, if philosopher 3 is sitting next to a continuously ravenous philosopher 2, philosopher 2 doesn't always get the fork. With the given code, there is no such guarantee. Phil 2 could be eating when phil 3 arrives at the table and reaches for the fork it shares with phil 2 and blocks. Eventually, phil2 finishes eating and puts down that fork ... only to become immediately hungry (zero thinking time!) and race back to the table and reach for the fork again. If that happens before the fork process has looped back to the start of its loop, the fork will see both phils trying to pick it up. With a plain ALT, it might let phil 2 pick it up. This could continue for ever!

To eliminate, the fork must fair ALT over those input channels it is servicing.

Keywords: q7


Question 21 (2001):

The function:

  random (maxvalue, seed)

returns an (INT, INT) value. How can I assign the first INT in the pair to one variable, and the second to another? I have tried:

  INT number, seed:
  SEQ
    ...
    (number, seed) := random (maxvalue, seed)

But I imagined it would cause an error ... and it did.

Answer 21:

If you look at the syntax of the function declaration:

  INT, INT FUNCTION random (VAL INT upto, seed)

you will see that it returns an INT, INT - i.e. no brackets! The correct syntax, therefore, is:

    number, seed := random (maxvalue, seed)

For further information on this function, see Question 77 (2000). For general questions about animating the Dining Philosphers' problem, see last year's Question 66 (2000) onwards.

Keywords: q7 , random

2000

Question 92 (2000):

I am doing my own implementation of the q7 (i.e not using any of the methods part written). I won't be docked marks because of this (presuming that my implementation is correct)?

Answer 92:

No - that's perfectly in order.

Keywords: q7


Question 89 (2000):

When drawing the network diagram, do we have to show it as all the philosophers sitting round the table, with the all forks and all the channels - i.e. from the college perspective? Or do we have to draw it as the code we have written - i.e. 1 philosopher, 1 fork, security guard and display taking in channels from those 3 objects?

Answer 89:

For each process implemented as a network of processes, you must draw that network showing all connections - i.e. all internal processes, how they are wired together and/or wired to the outside world. If your network topology for the college reflects the college geopgraphy (e.g. philosophers and forks arranged round a table), that's a nice bonus but not essential.

There will be at least two layers of network to draw - the (secure) college network and the q7 network, consisting of the college and display processes. Each network should be drawn separately - do not try to combine two layers of network on one diagram. Ideally, you should also draw individual process icons for each process (e.g. philosopher, fork, security guard, secure college and display) that shows the shape you are using for that process and its external wires (labelled with the relevant formal parameter names used in your code). All wires should be arrowed to show the direction of data flow and labelled with the channel names used in your program. All processes should be labelled with the process names used in your program (plus any non-channel formal parameters).

Keywords: q7 , diagrams


Question 87 (2000):

The following code:

  PROC displaying ([]CHAN OF DISPLAY d, ...)
    WHILE TRUE
      ALT i = 0 FOR 6
        d[i] ? CASE
          thinking
            out.string ("Philosopher is thinking", 25, out)
          hungry
            out.string ("Philosopher is hungry", 25, out)
          ...  etc.

keeps giving me the error:

    Not enough items in i/o list.

Why does it do that?

Answer 87:

Because there are not enough items in your i/o list. Your DISPLAY protocol must contain variants that contain something other than just a tag name - maybe:

  PROTOCOL DISPLAY
    CASE
      thinking; INT
      hungry; INT
      ...  etc.
  :

In which case, your CASE input must provide the necessary variables for the relevant variant lines. For example:

        d[i] ? CASE
          INT id:
          thinking; id
            ...  make the report
          INT id:
          hungry; id
            ...  make the report
          ...  etc.

Keywords: q7 , protocol


Question 86 (2000):

In a replicated ALT over an array of channels, how do you include a SKIP process to deal with when none of the channels is sending data? For example:

    forks[f] ? CASE
      upfork
        SEQ
          ...  display an fork in the up position
      downfork
        SEQ
          ...  display an fork in the down position
      -- needs a SKIP if none of the forks positions have changed...

I think my program is deadlocking because it keeps waiting for forks to report when none of them have changed position.

Answer 86:

You should not need such a SKIP guard. The best thing for your display process to do when nothing is being reporting is nothing, which is what will happen if you just listen to all the report channels with a replicated ALT. If your program is deadlocking, it is for another reason - such as your college processes (philosophers, forks and security guard) outputting to parameter channels that are not correctly wired to the input channels of your display process.

If you really need to poll all those report channels (and you don't - honest), you could write something like this:

    WHILE TRUE
      PRI ALT
        ALT p = 0 FOR n.phils
          phils[p] ? CASE
            ...  deal with philosopher reports
        ALT f = 0 FOR n.forks
          forks[f] ? CASE
            ...  deal with fork reports
        INT n.sat.down:
        security ? n.sat.down
          ...  deal with this report from the security guard
        TRUE & SKIP
          ...  no reports available - do something else (like SKIP :-()

Keywords: q7 , alternation


Question 85 (2000):

I have expanded my dining philosophers animation network like this:

  [5]CHAN OF PHILOSOPHER a:
  [5]CHAN OF FORK b:
  PAR
    secure.college (a, b)
    display (a, b, screen)

but the compiler is telling me:

    Aliasing error, 'screen' is a free variable.

Any thoughts?

Answer 85:

Yes. It must be the case that your display process does not name its third parameter screen, but nevertheless outputs to a channel called screen. Something like:

  PROC display ([5]CHAN OF PHILOSOPHER from.phil,
                [5]CHAN OF FORK b,
                CHAN OF BYTE out)
    ...  and in here outputs to the 'screen' channel instead of 'out'
  :

Now, this PROC compiles because screen is a globally visibly channel carrying the right protocol (BYTE). It must also be the case that that channel exists because you have declared display inside the body of your main q7 process, where screen is declared as a parameter. [If it had been declared on its own before your main q7 process, it would not have compiled - complaining instead about the unknown channel called screen, which would have been nice.]

Assuming the above, when the compiler came to the attempted instance:

    display (a, b, screen)

it would see an attempt to associate the real channel screen with the formal parameter out. But the compiler knows that your display outputs to this screen directly - so that the process would have two names for the same channel: out and screen. occam does not allow such aliases to happen - hence the error message.

Keywords: q7 , free-variable


Question 82 (2000):

I am attempting to plex together multiple channels into one. Each channel uses a tagged protocol, STATUS, that I have defined. I have found a working solution:

  PROC plex ([]CHAN OF STATUS in, CHAN OF STATUS out)
    WHILE TRUE
      ALT i = 0 FOR SIZE in
        in[i] ? CASE
          INT v:
          sitting; v
            out ! sitting; v
          thinking;
            out ! thinking
          ...  same for all the other variants

However, I am not happy with this, since I am just switching based on what's in the protocol, and just outputting it in every case. What I want to be able to do is something like:

  PROC plex ([]CHAN OF STATUS in, CHAN OF STATUS out)
    WHILE TRUE
      ALT i = 0 FOR SIZE in
        STATUS s:
        in[i] ? s
          out ! s
  :

All my attempts at this have failed, usually resulting in:

    Error-oc-myq7.occ(117)- Name STATUS is not a TYPE.

Can you point me at the right syntax for this? Thanks.

Answer 82:

Your question is a very good one. I'm afraid that occam2.1 has no syntax to express your perfectly reasonable request! This problem occurs when writing many standard components for handling variant (CASE) protocols - buffers, message routers as well as multiplexors and de-mutiplexors. The proposed, but so far unimplemented, occam3 language enabled the declaration of UNION data-types, that would mostly solve this problem. The draft occam3 language specification can be found on:

    http://wotug.ukc.ac.uk/parallel/occam/documentation/

for those interested (1.4 MBytes postscript). Summer or group project anyone?

Keywords: q7 , multiplex


Question 81 (2000):

For the Dining Philosopers Animation, can we get full or nearly full marks with a simple text output describing each state change?

Answer 81:

Around 20% of the marks are for a decent animation - where decent means at least to the standard of that given by:

    /usr/local/work/co516/answers/a7  (on raptor)

Keywords: q7


Question 80 (2000):

Thinking and eating by the philosphers should be modelled by random (but finite!) delays.

Assuming we have obtained a random number, what's the best way to implement the delay ... i.e. pause execution for a random time? Is there a wait(time) function or such like?

Answer 80:

See slide 4-40 and sections 3.4/3.5 of the "OCCAM2 CHECKLIST" paper. Spelling it out:

  TIMER tim:
  INT t:
  SEQ
    tim ? t
    tim ? AFTER t PLUS waiting.time

Keywords: q7 , timers

Referrers: Question 59 (2004)


Question 77 (2000):

Ok, I am confused. What's the deal with all the seed things? Also what's the deal with the animation? Where can I find some examples of some coding for screen display?

[I'm combining this question with the following one (PHW)]

Please could you tell me how to generate a random number in occam? I've forgotten and can't find it in the notes. Thanks.

Answer 77:

All these things have been explained in your seminar groups. I'll just point you at Question 76 (2000) for information about implementing the screen display and:

    /usr/local/work/co516/libsrc/random.occ

for information about the random number generating FUNCTION, for which you need to set up and maintain a seed variable.

Keywords: random , q7

Referrers: Question 21 (2001)


Question 76 (2000):

I think we've already been told, but where are we meant to find the documentation on all the methods we need for the display process, in order to move the cursor around the screen etc?

Answer 76:

Yes - you have been told! See, on raptor, files:

    /usr/local/work/co516/libsrc/utils.doc

which is a text file (not an MS-Word document!). The procedures you want are documented at the end of the file, following the comment (fold) line:

    ...  screen stuff (VT220 protocol)

Alternatively, you could browse the full source code:

    /usr/local/work/co516/libsrc/utils.occ

There's also a simple demo of the cursor.x.y procedure in:

    /usr/local/work/co516/examples/test_utils.occ

Keywords: q7 , display

Referrers: Question 77 (2000) , Question 78 (2000)


Question 75 (2000):

I get a compiler error when I adpated the philosopher's process to accommodate the sending of data when the philosopher does an action. It says that within a PAR scope, I cannot output to the same report channel (to the display process) in parallel branches of the PAR. Which is fair enough. But how can I get past this?

Answer 75:

One way is to put in two report channels from the philosopher and, then, either a separate multiplexor process that merges those two down to one or just take both report channels to the display process (which will get a bigger array of input channels to service).

Better, though, is to get your fork processes to have report channels to the display. Then, don't bother reporting fork acquisitions from the philosopher (which is, I guess is what you were trying to do in parallel - because the fork acquisitions occur in parallel). The forks can report where they are directly on their own report channels.

Keywords: q7 , parallel-output


Question 72 (2000):

When I recieve the appropiate case statement, I want to output a string. But what command does that?

Answer 72:

It sounds like you don't know about:

  out.string ("any old string", fieldwidth, screen.channel)

from the course library? Look at any of the examples in your examples directory on raptor - or the answers directory at:

    /usr/local/work/co516/answers/

Keywords: q7


Question 71 (2000):

When tapping the channels for the philosophers and forks, Fred recommended giving each one an id. If it were Java, I would simply assign each object an individual id when their constructor was called. Can I do something similar in occam?

Answer 71:

Yes. To set up a number, say n, of thing processes and give each instance its own id is easy. First, the PROC header for a thing must take an id parameter - for example:

  PROC thing (VAL INT id, ...)
    ...  body of thing
  :

Then, to set up the instances:

  PAR i = 0 FOR n
    thing (i, ...)

That's all.

Keywords: q7


Question 70 (2000):

Once the first draft of my q7 program is compiled and run, it produces this error:

    Philosopher 1 is thinking
    KROC: Range error / STOP executed (signal 4)
    KROC: Fatal error code 1, core dumped
    Abort (core dumped)

I don't know what this means, so I would be grateful if you could point me in the right direction ...

Answer 70:

It means your program crashed. There are several possible causes of this run-time error:

I'm afraid the message you report is all you get from the KRoC/Solaris system. If you compile this with KRoC/Linux using the command:

    kroc -d myfile.occ -lcourse

it will tell you the file name and line number of the offending line. [Note: the "-lcourse" flag above is just to link in the course library - something which is automatic with the Solaris version of the kroc command. The active ingredient of the above command is the "-d" flag.]

Keywords: q7 , range-error , stop

Referrers: Question 43 (2004) , Question 30 (2003) , Question 86 (2003) , Question 11 (2002)


Question 69 (2000):

In a post, Fred says that the maximum negative 32 bit int is -2147483648, so I have coded appropriately ...

  -- ensure seed is positive & legal
  IF
    seed = (-2147483648)       <---------ERROR!!!
      seed := 2147483647
    seed < 0
      seed := -seed
    seed = 0
      seed := 1
    TRUE
      SKIP

But I get an error on the line arrowed above which says:

          Overflow when evaluating constant expresssion

Help!! Have I done something wrong or is the info on cs2 wrong?

Answer 69:

The compiler treats -2147483648 as an expression, so it gets an error when trying to evaluate 2147483648 (which is larger than the largest INT). If it got past that, it would get another error trying to negate it.

occam has a special way of naming the largest and smallest of any of its number types. For example,

  MOSTNEG INT
  MOSTPOS INT

give you, respectively, the most negative and positive integers. Other ways we can write MOSTNEG INT are:

  #80000000
  1 << 31

But ... my colleague, David Wood, suggests you might like to consider:

  TIMER tim:
  INT seed:
  SEQ
    tim ? seed
    seed := (seed >> 2) + 1

Keywords: inverting , int , random , q7

Referrers: Question 29 (2002)


Question 68 (2000):

I've forgotten how to implement the lookup table for the screen positions for the dining philosophers. Any help would be appreciated.

Answer 68:

Your animation code should not be highly repetitive with the same logic repeated with different magic numbers - e.g. for displaying new positions of the different philosophers. Having a table of anchor coordinates for each philosopher may help. A table is simply an array of VALues (i.e. constants). For example:

  VAL [][2]BYTE phil.anchor IS [[40, 5], [70, 10], [55, 15],
                                [35, 15], [10, 10]]:

where the [][2]BYTE could have just been [][]BYTE, but being specific about the dimension of the coordinates (rather than the number of them) seems right. We could have been even more explicit and written [5][2]BYTE, but that seems too much. Any way, the compiler will fill in the sizes of any blanks in what we write after the IS.

With the above, it's nice to give names to the two indices of the [2]BYTE array coordinates - e.g.

  VAL INT X IS 0:
  VAL INT Y IS 1:

Then, if we want to move the screen cursor to the anchor point for philosopher i - and we know that that i is a valid philosopher number (i.e. 0 through 4):

    cursor.x.y (phil.anchor[i][X], phil.anchor[i][Y], screen)

or, more efficiently:

    VAL [2]BYTE phil.i IS phil.anchor[i]:
    cursor.x.y (phil.i[X], phil.i[Y], screen)

since it only checks the array index (for out-of-bounds error) and calculates the address of phil.anchor[i] once.

Keywords: q7 , cursor , table , animation

Referrers: Question 84 (2003) , Question 29 (2002)


Question 67 (2000):

How do I create a replicated protocol CASE statement for the dining philosophers. I have written:

  PROC display ([]CHAN OF MYPROTOCOL reportin, CHAN OF BYTE out)
    WHILE TRUE
      ALT i = 0 FOR 10
        INT n:
        reportin[i]? CASE
          thinking
            out.string ("Philosopher Sat Down", 50, out)
          hungry
            out.string ("Philosopher is hungry", 50, out)
          etc...
  :

But I keep getting incorrect indentation errors. Do I need any SEQ or PARs here or is the problem elsewhere?

Answer 67:

There is nothing illegal with the above code fragment, assuming that your etc... introduces another variant of MYPROTOCOL. Your local (but unused) declaration of INT n, for example, is perfectly legal just above the ALT guard. It could also be located just above (and aligned with) any of the CASE variants if that were useful.

Indentation errors are trivial to correct. Mail me your code and tell me the line number of any indentation errors reported by the compiler and I'll tell you what's wrong. If it's a general point, I'll make up the relevant (anonymous) question and post an answer to these pages.

Keywords: q7 , incorrect-indentation


Question 66 (2000):

For question 7, I am trying to draw a boarder for the dining philosophers room. I can do it with lots of cursor.x.y and out.string procedures but this seems time consuming. I thought of doing it in a replicated PAR or replicated SEQ and I wrote this code:

  #INCLUDE "consts.inc"
  #USE "course.lib"

  PROC a (CHAN OF BYTE out)
    PAR i = 1 FOR 26
      SEQ
        cursor.x.y (4, i, out)
        out.string ("#", 0, out)
  :

  PROC test (CHAN OF BYTE keyboard, screen, error)
    PAR
      a (screen)
      ...  other things
  :

But when I compile it, it says there is a type mismatch in parameter 2 of cursor.x.y. This is the y coordinate that I am changing so that the character gets printed on the line below the first one to create a column like this:

      #
      #
      #
      #
      #
      #

Why does the compiler not like the second parameter of the cursor.x.y proceedure? Doesen't it just need to be a number?

Answer 66:

The second parameter of cursor.x.y needs to be a BYTE. Replicator control variables (e.g. your i) are INTs. You need to cast it into a BYTE:

        cursor.x.y (4, BYTE i, out)

See the answer to Question 7 (2000) for information on casting between occam types.

Your PAR replicator also won't work because it implies parallel outputs to the out channel - illegal! So it has to be a SEQ replicator. In any case, unless the occam kernel supports, and is running on a multiprocessor machine, the SEQ replicator for code like this will be faster than a PAR (which will have to startup and shutdown 25 software processes).

Your code would also be slightly snappier with:

  PROC a (CHAN OF BYTE out)
    SEQ
      cursor.x.y (4, 1, out)
      SEQ i = 1 FOR 26            -- the "2" could be anything though
        SEQ
          out ! '#'               -- don't need out.string for a single char
          cursor.down (1, out)
          cursor.left (1, out)
      out ! FLUSH

Keywords: q7 , type-mismatch , type-cast , cast , cursor

Referrers: Question 21 (2001) , Question 74 (2000)

Valid CSS!

Valid XHTML 1.0!

Last modified Mon May 15 17:39:47 2006
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.