XML

kent logo

CO538 Anonymous Questions and Answers

This page lists the various questions and answers. 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.

We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.

When asking questions, please do not simply paste in your code and ask what is wrong with it, as these types of question are hard to answer in a public forum (resulting in either no answer, or an answer which will only be of use to the person asking the question). In many cases, a question about code can be formulated in general terms. For example, if you have an `IF' block that results in an `incorrect indentation' error, you might ask, ``what is the correct syntax for an occam `if' statement ?''. Questions of this form are easier to answer, and are meaningful to all.

Questions that are not suitable for these public pages (i.e. those that contain assignment-specific code), should be mailed to your seminar-leader.


Question 41:

Should we be using PLUS/MINUS or +/- for Q4?

My class supervisor told me that we should be using +/-. But when I do that, my q4 process crashes very quickly due to not being able to wrap round into negative numbers. Is this OK or should I use PLUS/MINUS and allow the program to wrap round?

Answer 41:

Please use PLUS/MINUS rather than +/-. That's what the plus process (from the course library) uses and that was chosen specifically to allow these demo programs to run forever. The Fibonacci sequence gets big very quickly - so the demo example program would crash very quickly otherwise. Of course, the numbers in the supposed-Fibonacci column are no longer from the Fibonacci sequence ... but never mind.

However, whether you use PLUS/MINUS or +/-, you will not lose marks. I've squared things with your supervisor!

Keywords: q4 , overflow


Question 42:

I am creating a PROC but need global variables for it. Where would I declare them?

  PROC rah (CHAN OF INT a, b, c, d)
    WHILE TRUE
      ...  loop body
  :

These variables and their state will need to be used throughout the PROC. Do these need to declared before the WHILE TRUE bit or is there another way?

Answer 42:

By global variables, I assume you mean variables to be used anywhere inside your rah process. These are properly known as local variables of that process. [Properly global variables are declared outside and before the declarations of all the PROCs to which they are global. In general, working with such globals is a bad thing - if you need access to global structures, pass them in through the parameter list. In the particular case of the outermost PROC declarations of a compilation unit, global variables are not allowed and will be rejected by the compiler.]

If you want local variables in rah that are global to your loop, they must be declared and initialised before the loop:

  PROC rah (CHAN OF INT a, b, c, d)
    ...  declare some variables
    SEQ
      ...  initialise those variables
      WHILE TRUE
        ...  loop body
  :

Those variables will retain their values as control flows around the loop.

If the variables are only needed within the loop body (i.e. their values do not need to be retained from one loop cycle to the next), declare them at the start of the loop body:

  PROC rah (CHAN OF INT a, b, c, d)
    WHILE TRUE
      ...  declare some variables
      SEQ
        ...  initialise those variables
        ...  loop body
  :

Keywords: variable-scope


Question 43:

What's the problem here?

  PROC invert (CHAN OF INT a, c, CHAN OF BYTE b)
    INT factor:
    SEQ
      ...  stuff
      c ! (a * factor)      -- compiler gives error here
      ...  more stuff
  :

The error message is:

  Operands have different types for operator "*".

As far as I can see they are not different types. Any ideas?

Answer 43:

But they are different types. Your a is a channel (that happens to carry integers) and your factor is a variable (that happens to hold integers). Multiplication operates over numeric data (such as may be held in variables). Multiplication is not defined on channels - you can only input/output from/to them! You probably need to input an integer from channel a into another variable first.

Keywords: compiling , type-mismatch


Question 44:

I am currently doing the pairs toggling bit of Q4. I am trying to say

  IF there is a toggle input
  THEN switched := NOT switched
  ELSE carry on excuting the rest of the code.

where toggle is an input channel and switched is a boolean variable.

Answer 44:

You are describing a poll on the toggle channel. See slide 5-37 in the notes. You may consider the use of polling absolutely essential (see the comment on slide 5-37) for your solution to this part of the question - even though it's not!

Keywords: q4 , inverting , if

Referrers: Question 47 (2000)


Question 45:

Example:

  PROC whyowhyOccam(CHAN OF whatever.....)
    BOOL b:
    SEQ
      b:=TRUE
      WHILE b
         ... Code
         IF
           occam = bad
             .. b:=false
           TRUE
             .. More code
  :

With this program, when occam does equal bad :), then b is set to false. Does this mean that the WHILE-loop wiill terminate or does something else happen? When I run it, the WHILE-loop will not terminate when occam equals bad.

Answer 45:

Your code has indentation errors and a missing SEQ ... and I'm not sure what your:

             .. b:=false

means? Might you be doing something in the dots that sets b true again? If your code really is this:

  PROC whyowhyOccam (CHAN OF whatever.....)
    BOOL b:
    ...  declarations of your variables occam and bad
    SEQ
      b := TRUE
      WHILE b
        SEQ
          ...  code that sets occam and/or bad
          IF
            occam = bad
              SEQ
                b := FALSE
                ...  something that doesn't change b
            TRUE
              ...  more code
  :

then if occam equals bad inside the loop, the loop will terminate - promise!

Keywords: loops


Question 46:

I am confused with the IF ... TRUE statement. Does TRUE act like the ELSE (where ELSE is used in Java's IF statements)? Or does occam extend its IF statement vocabulary to include ELSE as well?

Answer 46:

There is no such thing as the IF ... TRUE statement in occam. There is an IF constructor that takes a sequence of indented conditional processes. Each condiional process consists of a boolean condition followed by an indented process (which could be a single primitive statement, with or without local declarations, or some compound statement).

The rule is that the conditions in each conditional process are tested in the sequence listed. The process behind the first one that turns out to be TRUE is executed. If none turn out TRUE, this is a run-time error.

The IF has no ELSE part (to do if all the conditions fail). But we get the same thing if the last condition we write is just TRUE. See slide 4-44 and section 4.4 of the occam2 checklist.

Keywords: if

Referrers: Question 6 (2011) , Question 11 (2009)


Question 47:

I am having some trouble with part 3 of the assessment. Here's my code:

  ...  censored

What I'm trying to do is pass through a channel of INTs, multiplying them by a factor, whilst in parallel checking another channel to see if the monitor has passed a zero and, if so, changing the factor.

The problem is that KRoC won't complile the code because it won't let me read and write to a variable in parallel - which is fair enough 'cause I could see some problem arising if they both want access to it at the same time.

Is there a way to get round this, or do I need to rethink my ideas?

Answer 47:

I haven't shown the code because it's wrong in too many ways, I'm afraid, and posting it would not help anyone.

It's not KRoC that won't compile it so much as the language doesn't allow it (and, therefore, KRoC rejects it). We are simply not allowed to look at a variable in parallel with another process that's changing it. So, you do need to rethink your ideas. Check out Question 44 (2000) and its answer.

Keywords: q4 , process-networks


Question 48:

I have been trying to work out why this is not working for ages - please can you help?

  ...  complete listing of code (with no comments)

Answer 48:

I'm afraid questions for these pages have to be a bit more focussed! [You may care to check your wiring for the overall network though ...]


Question 49:

I get an error message when trying to compile the folowing:-

PROC plus.modified (CHAN OF INT in1, in2, control, out)
  WHILE TRUE
    PRI ALT
      control signal
        ...  actions when control signal is received
      plus (in1, in2, out)             -- <<< ERROR MESSAGE HERE
:

I get an error message saying expected end-of-line found when a ? was needed. What's the problem?

Answer 49:

You are creating an instance of the plus process in a position where the compiler expects another guard for your PRI ALT. There is nowhere legal you can put that line without adding an extra SEQ (or, possibly, PAR). Bear in mind that once plus starts, it never terminates - so don't ever expect to go around the loop again if you invoke it somewhere in the loop body ...

The first guard of your PRI ALT is syntactically illegal. There should be a ? in the middle of it - and where is your signal variable defined?

Finally, if your PRI ALT is really meant to have a single guard, it's a bit pointless - better simply to use a SEQ.

Keywords: q4


Question 51:

In the q6.occ file, it says that it would be good if we formatted the output into order. Do we have to do this to achieve full marks? Or is it purely optional?

Answer 51:

No - full marks can be obtained without sorting the names.

However, if you solve the problem by setting up a pipeline of cells with each one responsible for a different name, the extra code needed to sort them is trivial - use the technique illustrated by the sort pump (slides 2-21..23 and 5-17..19).

Keywords: q6

Referrers: Question 19 (2001) , Question 54 (2000)


Question 52:

I assume that q6 is supposed to read the file (nn_small.txt etc.). I have answered the question, but it still takes input from the keyboard.

It will collate all of the marks typed in using the correct standard - but to display the results I cannot just type enter, I must type a non-numeric character twice (e.g. "f f") before the results will be displayed. I am hoping this is a problem that will be fixed by the reading of the file, but I can't be sure until I can read the file.

Also, the comments added to the code make it sound like the output should be placed in a file rather than on the screen. Is this the case (and have we covered how to do this?) or is printing the results to the screen acceptable?

Answer 52:

You do not have to do anything in your occam code for this question to take input from a file or output to a file.

Your occam executable, q6, is a Unix process (in the KRoC implementations for Solaris and Linux). A Unix process takes text input from its standard input device and produces text output on its standard output device. By default, these devices are, respectively, your terminal keyboard and screen.

However, Unix allows you to specify that standard input is to be taken from a file and/or that standard output should be written to a file. To do this, we use re-direction operators - for example:

  raptor$ q6 < nn_data.txt

will run your q6 process and take standard input from the file nn_data.txt. KRoC maps Unix standard input to the compulsory keyboard input channel (the first parameter to your PROC q6). The starter code given in q6.occ reads from that channel - so all is done.

If you want to save the output in a file, don't change your program - just run:

  raptor$ q6 < nn_data.txt > results.txt

KRoC maps Unix standard output to the compulsory screen output channel (the second parameter to your PROC q6). The above command redirects that standard output to the named file.

[Note: KRoC does, of course, have a full library for file handling - but this is not included in the course library (course.lib) and is not part of the examinable course. Anyone wanting to find out more, please mail me.]

Running q6 interactively is a bit painful! What you type is not being echoed to the screen - so you won't see it. To begin with, you will see the NAME/MARK table headings that are output during initialisation of the display process. But, then, you won't see anything until you have typed in all your test data and indicated its end. For data coming from a file, the end is simply the end-of-file. For data coming from the keyboard, you indicate the end by typing the ASCII end-of-transmission character - which is CTL-D. Note that this should be typed in a legal position - i.e. following a name and mark pair - and may need a further carriage-return character to get it delivered to your occam process.

The anonymous questioner found an alternative way to end the data, which was to type in illegal data (e.g. "f f") - a name followed by something other than a mark. If that happens, the read.data process is programmed to abandon processing input and issue the poison signal (i.e. just as if the end-of-transmission or end-of-file was reached). This is documented in the description of read.data in your q6.occ file.

Redirecting standard input/output is a standard Unix capability (that you should know).

Keywords: q6 , keyboard-input

Referrers: Question 64 (2003) , Question 55 (2000)


Question 53:

For question 6, what value is poison (so that I can test for it)?

Answer 53:

You don't need to know this. poison is a tag name, part of the NAME.NUMBER protocol. It doesn't have a number representation (apart from an internal one that you can't get at) - it just has a name.

See the main cycle of the display process that's in your q6.occ starter file. That shows how to input from a channel carrying this protocol and how to distinguish a string message from a poison one. See also slide 10-21 from the course notes and section 7.3 from the "OCCAM2.1 Checklist" in your course booklet.

Keywords: q6 , poison

Referrers: Question 55 (2003) , Question 57 (2000) , Question 62 (2000)


Question 54:

What extra marks will we get if we implement the sorting of the names in question 6?

Answer 54:

None - see the answer to Question 51 (2000). But your reward will be a better understanding and greater confidence!

Keywords: q6


Question 55:

What does the process file.in.token (from file_in.occ) do with regards to question 6?

Answer 55:

Nothing that need concern you. Treat the read.data process as a black box. You don't need to understand how it works - only that it parses plain text (redirected file) input, extracts the relevant information and outputs that as a NAME.NUMBER protocol. You do have to understand the latter.

See the answer to Question 52 (2000) to understand about Unix file redirection to standard input.

Keywords: q6


Question 56:

For q6, using this input:

  Alison -20
  Fred -10
  Alison 944
  Fred 720
  George 628
  Alison 20
  Peter 331
  Fred 100
  Peter 13
  Alison 100
  Fred 24

I get this output:

  Alison    1044
  Fred       710
  George     628
  Peter      344
  Fred       124

It manages to add up Alison's and Peter's marks but not Fred's!

I have spent hours trying to solve this and I can't find the problem ... do you have any suggestions?

Answer 56:

The documentation in your q6.occ starter file tells you to check out the documentation of the string handling routines in string.occ, which is part of the course library and contained in the libsrc directory.

That documentation defines "strings" as BYTE arrays left-justified with trailing NULLs. The equal.string and compare.string functions assume its arguments conform to this definition of strings. The make.string procedure does this for you and has to be applied to any BYTE array used as the target of a counted array input. If you don't do this, you get results like the above.

Keywords: q6

Referrers: Question 60 (2000)


Question 57:

I'm unsure on how to make reference to the particular name and number components of the NAME.NUMBER protocol. I realise that this variant is itself a counted array protocol combined with an INT and is one variant of the tagged protocol. More specifically, I'm using a process named cell with the following declaration:

  PROC cell (CHAN OF NAME.NUMBER in, out)

I believe I'm going to need to be able to discern the name (which I understand is held as a BYTE array and an INT value to tell the length of the array) and the number (which is an INT) from all the data coming in on the in channel. I just don't know how to refer to these items within the in channel in the code?

Answer 57:

Look at the code in the main cycle of the display process (in your q6.occ starter file). Also, see the answer to Question 53 (2000).

Keywords: q6

Referrers: Question 62 (2000)


Question 58:

Please could you type up the example on abbreviations you showed us in the lecture? They were on hand-drawn slides and about adding up elements of a 2-D array. Thanks.

Answer 58:

OK. Here's some code for adding up the elements of a 1-D array:

  SEQ
    sum := 0
    SEQ i = 0 FOR SIZE a
      sum := sum + a[i]

where a is an array of REAL64s (say) and sum is a single REAL64 variable.

Now, suppose a is a 2-D array of REAL64s and we need to add up each of its rows into corresponding elements of sum (which is now a 1-D array of REAL64s). The naive code, based on the above, would be:

  SEQ row = 0 FOR SIZE a
    SEQ
      sum[row] := 0
      SEQ col = 0 FOR SIZE a[row]
        sum[row] := sum[row] + a[row][col]

This code is correct but somewhat inefficient. Firstly, occam 2-D arrays live in a contiguous block of memory with all its rows having the same lengths (which is not the case for Java 2-D arrays). Therefore, it's slightly wasteful to look up the size of each row each time the inner loop starts. Instead, look this up once before doing anything else, give it a VAL name and use that name:

  VAL INT n.cols IS SIZE a[0]:
  SEQ row = 0 FOR SIZE a
    SEQ
      sum[row] := 0
      SEQ col = 0 FOR n.cols
        sum[row] := sum[row] + a[row][col]  -- innermost loop code

But the real inefficiency lies in the code of the innermost loop. That code is executed n.rows * n.cols times and involves calculating the addrresses of elements sum[row] and a[row][col]. The latter requires a multiplication and an addition - the former just an addition. Three run-time checks that row and col lie within their respective array index ranges may also be required (although a really clever optimiser may be able to deduce that they will always be within bounds and, therefore, omit these checks).

Compare the above with:

  VAL INT n.cols IS SIZE a[0]:
  SEQ row = 0 FOR SIZE a
    REAL64 sum.row IS sum[row]:             -- this is where we will do the sum
    VAL []REAL64 a.row IS a[row]:           -- this is what we are going to sum
    SEQ
      sum.row := 0
      SEQ col = 0 FOR n.cols
        sum.row := sum.row + a.row[col]     -- innermost loop code

Now, the innermost loop contains just one array reference, requiring only one addition for the address calculation and one range check on col (for which an optimiser does not have to be that clever to optimise away). Two new array references have been introduced in the abbreviations themselves - but these are not part of the innermost loop and only happen once per row. This code will execute much faster than the previous version.

The other benefit from introducing those abbreviations is that the inner code:

    SEQ
      sum.row := 0
      SEQ col = 0 FOR n.cols
        sum.row := sum.row + a.row[col]     -- innermost loop code

is as simple as the 1-D array summing code with which we started:

Keywords: abbreviation , arrays , size

Referrers: Question 69 (2010)


Question 59:

I am considering using a CASE protocol to distinguish between names? Is it better to create a peipeline of 20 cells instead? In which case, when I do create a pipeline that big, what happens when their aren't enough names to fill in the pipeline?

Answer 59:

Your first question makes no sense. A CASE protocol has to list all the tags it's going to support - one for each of its variants. You have to process names and you don't know what these names are going to be in advance - the names are data on which you have to operate. So, declaring a CASE protocol with the names burnt in as tags can't be done.

The answer to your second question is yes. The answer to your third is no problem - you will need to think why though!

Keywords: q6


Question 60:

I have got my question 6 to compile and run, but it is not producing the correct output. When I run the file with nn_tiny.txt, I get the following output:

            Name             Mark
            ----             ----

            Peter             331
            Fred              -10
            Alison            964
            Fred              720
            George            628

The strange thing is that it is adding the two entries for Alison correctly, but not the two for Fred!!

Answer 60:

See the answer to Question 56 (2000).

Keywords: q6

Valid CSS!

Valid XHTML 1.0!

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Last modified Mon May 20 13:50:24 2013
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.